1

I am working on a microservices project involving 4 services - Auth Service, Service-A, Service-B and Service-C.

All the services are implemented using Spring Boot. The Auth Service is responsible for authenticating logged in user and generating a JWT bearer token. Each of Service-A/B/C has JWT filters which checks for validity of token and then provide access to the Rest APIs.

Now I want to implement logout feature. The logout request goes to Auth Service. The Auth Service uses Redis. The token is added to list of invalid tokens with ttl set so that after the expiry the token is removed automatically.

Now how can JWT filters in Service-A/B/C access the blacklisted token so that Rest API access is approved/disapproved? If all the services are deployed in same system the services can access Redis easily. If the services are deployed in different systems, how can they access the invalid tokens?

Should I implement pub/sub messaging and each service have a list of invalid tokens stored in redis? Or is there a better approach in microservices environment?

4
  • Do you have a API-gateway?
    – Darem
    Commented Jul 6, 2021 at 8:29
  • Yes, all the requests to Auth service, Service-A/B/C goes to API gateway which then redirects to appropriate service Commented Jul 6, 2021 at 8:52
  • 1
    Then one approach would be to handle the whole thing already in the gateway. The gateway checks the token before forwarding the request to the respective service. When Logout is called, the gateway automatically puts the token on a block list. And so it would be centralized in one place.
    – Darem
    Commented Jul 6, 2021 at 10:49
  • Thanks!. Sounds reasonable and easy. Can you add your comments as answer? Commented Jul 6, 2021 at 11:21

2 Answers 2

1

As already mentioned in the comments, one way to solve the whole problem is with the API Gateway. In it, the gateway checks for each request whether the JWT is included in the blocklist. If yes, the request will be rejected immediately with 401 or similar.

enter image description here

If a user logs out, the gateway adds the token to the blocklist and forwards the request to the auth service, if it wants to execute additional logic.

enter image description here

This way, service A, B and C can always be sure that when they receive a request, it is valid.

The blocklist should of course be selected so that it meets the requirements. If, for example, there are several gateway instances, a distributor storage must of course be selected, etc.

0

Edit: From the question I understood that blacklisting is only required to invalidate tokens on logout. In that scenario, the following solution allows you to achieve the result of sharing blacklisted tokens without actually using a blacklist.

One effective approach I have been using that does not require Redis or a list of invalid tokens utilises just a hash table:

  • Store a table mapping each userId to lastLogout (a Date) on the auth server.
  • Whenever login is called, it would query the auth server for the lastLogout, and only proceed with validating the JWT if it was issued after this date.
  • Whenever logout is called, the auth server will update its table to set the lastLogout for that user to the current time and date.
  • If a logged out user tries to log in to the same service or any other service with a token they used from before, that service will check the auth server for the lastLogout and reject the JWT if it should be considered expired (user has logged out since the creation of this token)

Note that this solution assumes all JWTs are created with iat (issued date).

This avoids consuming much space or processes to maintaining white or blacklists, relying on just a relatively light userId: string => lastLogout: date mapping.

4
  • This does not exactly answer my question. How will Service-A/B/C validate the token when they receive requests? The Auth service has authenticated the user and responded back with token. Now client (Frontend) sends requests to any of the services with token. The services should check if the token is not among the blacklisted tokens, and verify other criterias and then allow access to apis Commented Jul 6, 2021 at 7:33
  • The idea would be that on logout, the Auth server stores the current time as the lastLogout. Any service (A, B or C) can query getLastLogoutOf(userId) on the Auth server to compare the token's issue date and the last logout time. All tokens issued prior to the last logout are invalidated. Does this fulfil your blacklisting requirements?
    – Bharath CS
    Commented Jul 6, 2021 at 8:47
  • blacklisting is not my core issue. How the all services get to know of the blacklisted tokens is the issue. As per your suggestion, when Service-A receives a GET request /getUsers with some token attached, the Service-A has to do a Rest api call to Service-A to check if the token is not blacklisted. If the token is valid then Service-A has to do rest of other verification and then proceed ahead to provide access to API Commented Jul 6, 2021 at 8:58
  • Ah I see, my answer was proposing a solution that fulfils your use case without blacklisting. From the qn I thought you would ONLY blacklist tokens on logout. If that is correct, Service-A can GET /getLastLogoutOf?userId={...} to get the last logout time of user and use that to filter out JWT tokens that you would otherwise blacklist.
    – Bharath CS
    Commented Jul 6, 2021 at 9:15

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.