3

I'm working on a Spring-based micro service project and considering different approaches for handling authentication and authorisation. Instead of setting up a dedicated authorisation server, I’m thinking of implementing JWT validation directly within each micro service.

Proposed Approach

Each microservice will contain a JWT decoder bean to validate tokens locally. The public key for verifying JWT signatures will be retrieved from AWS Secrets Manager, allowing dynamic key rotation without service disruption. I plan to expose two authentication endpoints in my resource server:

  1. User authentication → Accepts a username and password to return a JWT access token and a refresh token.
  2. Service-to-service authentication → Issues a short-lived JWT to microservices. This could be implemented using either:
    • A service name and secret pair.
    • Mutual TLS (mTLS) for stronger security.

Reasons for This Approach

  • Cost efficiency – Avoids hosting a standalone authorization server just for issuing tokens.
  • Improved availability – No single point of failure; each microservice can validate JWTs independently.
  • Performance benefits – JWT validation is stateless, eliminating network calls to an external authorization server.
  • Secure key management – Fetching the public key from AWS Secrets Manager enables dynamic key rotation.
  • OAuth2 might be unnecessary – My system has no third-party applications, only: Internal microservices communicating with each other. A dashboard that retrieves user data using JWT authentication.

Question

Is this a valid approach? What are the potential pitfalls or improvements I should consider?

Edit

I forgot to mention that the user never communicates with the micro services. The user only communicates with the resource server. The micro services are purely machine to machine communication.

asked Apr 2 at 21:08
9
  • If every service has a copy of the user authorization code, what happens if you need to update or add complexities to this (SSO support for example)? This is the usual reason to move JWT generation to a central service. Commented Apr 2 at 21:12
  • Alternatively, if you mean having a central JWT authorisation server, and just use the JWT as authorisation on the microservices, the main limitation is revocation. If you need to revoke a users access it will take you the JWT lifetime for them to lose access in the worst case. This may or may not be an acceptable tradeoff. Commented Apr 2 at 21:15
  • 1
    What are you trying to protect against? Why do you need JWT tokens at all vs just using mTLS and trusting the request body then? Commented Apr 2 at 21:30
  • 3
    I think it would be helpful if you could add a diagram of your proposed server config. Commented Apr 2 at 22:33
  • 1
    In a JWT context, the term "resource" describes the server that receives a JWT, validates it, and then acts according to the authorizations in the token. You're using this term differently. Your "resource server" creates tokens and acts like a gateway? If so, please define your terminology more carefully, but yes, this can be a sensible approach. In contrast to "microservices just trust whatever requests they get via the gateway", this can help prevent "confused deputy" style security issues. Commented Apr 3 at 4:50

2 Answers 2

3

Is this a valid approach?

Yes, what you propose is a valid approach. Because authorization data is encoded into the JWT, decentralized authorization checks is a use-case that JWTs are specifically designed for.

What are the potential pitfalls or improvements I should consider?

One thing to consider is that the decentralized checking makes it impossible to revoke individual tokens before their expiry. This can be a major problem or of no consequence at all, but you have to take it into account. Especially when deciding on the lifetime of a token.

Another thing to consider is that even when a human user will never directly access a micro-service, you might want to use the end-user's JWT when the gateway makes a request on behalf of the user or if two micro-services communicate in the context of such a request. The reasoning here is that the permissions that are active might depend on who initiated the request.

Micro-service A might respond differently if it gets a request from an automated process (e.g. service B) or from a non-privileged user (by way of the gateway service) or from a user with administrative rights (by way of the gateway service).

answered Apr 3 at 14:42
1

One potential drawback of this approach is that when there is a security patch in the library that handles JWT tokens, you have to update each and every service on each and every server.

For a simple application, that may not be an issue. For a large application with dozens or hundreds of interdependent services, this could quickly become quite a burden.

If, additionally, the different services use different programming languages, you may have an additional organizational nightmare. If the libraries in those respective languages are patched at different dates, system administrators might have to scratch their heads, trying to understand what exactly should be updated when.

Add to this that the patch could have to be applied to both the service and the client (such as with the support of successive TLS versions). Now you have a gargantuan task of determining the exact correct order in which you have to update things. Or a circular dependency that is impossible to solve. Say service A, in Java, uses service B, in Ruby, which in turn uses service C, in Java. Ruby's gem that deals with JWT gets patched the next day the exploit is made public, but there is no news from Maven library. What do you do?

answered Apr 3 at 20:32
1
  • 2
    Sorry man, but you're really losing me on this one. This reads like you're saying, "Systems should not communicate with each other, because if the communication needs to change in any way for any reason at all, all the systems need to be updated all at the same time, every time. And that's impossible!" But, security vulnerabilities do show up. Sometimes they affect multiple languages. And more often than not, it's perfectly OK to just let patches roll out as they become available. And, it's also sometimes acceptable to just mitigate for systems that are "hard to patch". Commented Apr 3 at 21:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.