Search code examples
javaauthenticationspring-securityjwtmicroservices

Am I understand Auth + Application server approach correct?


Help me to understand the main idea.

Let`s assume that I have Auth server which can:

  1. Registration

  2. Authentification (consume login + pass, return Refresh and Access JWTokens)

  3. Update access token by refresh token. Refresh token updates as well.

I have application server with business logic. I want to make all API in application server secured. I have to use tokens from auth server. So now I have that servers. Are my thoughts correct about approach with auth + application server?

My thoughts:

  1. Client (Android app) trying to authorize. It sends login + pass to auth server. If success then he will get Refresh and Access tokens generated via refresh secret key and access secret key on auth server correspondingly.

  2. When user is authentificated (he has access token) he can use functionality on application server. But APIs on application server are secured. So user needs that access token in request header (Authorization: Bearer <access_token>) and our application server should recognize it correct. To do this application server has to have access secret key too. And due to this access secret key we can decide in security filter chain is our token correct like this:

    private boolean validateToken(@NonNull String token, @NonNull SecretKey accessSecretKey) {
            try {
                Jwts.parser()
                        .verifyWith(accessSecretKey)
                        .build()
                        .parseSignedClaims(token);
                return true;
            } catch (ExpiredJwtException expEx) {
                log.error("Token expired", expEx);
            } catch (UnsupportedJwtException unsEx) {
                log.error("Unsupported jwt", unsEx);
            } catch (MalformedJwtException mjEx) {
                log.error("Malformed jwt", mjEx);
            } catch (Exception e) {
                log.error("invalid token", e);
            }
            return false;
        }
    

    If the access token is correct then we will get payload (user`s not essential info like login) from JWT access token to use application server APIs.

  3. When access token is expired then we will get 401 error from application server and client application (Android app) will send request to auth server for updating access token using refresh token (which saved in sharedPreferences on android). So response will give us new Tokens (access and refresh) and we can use application API again.

    Are my thouhts correct about this pipeline of actions with auth + application servers? The main idea is to store access secret key on auth`s server side and on application server`s side too, so we can easily check our tokens on correctness.

I thought about another one idea:

  1. Similar to first idea, client (Android app) trying to authorize and sending login + pass to auth server. If success then he will get Refresh and Access token generated via refresh secret key and access secret key on auth server.

  2. After that auth server uses kafka to send current access token to application server. Application server receives token and stores it in SecurityContextHolder. So after that all client`s request will be able until access token expired. This approach allows us not to store access secret key in aplication server for validation (we trust that kafka sends only approved tokens because its inner communication tool between auth and application server)

But I think this idea has possible pitfalls and makes us to have kafka between services (auth and application) which not looking good for this task. Or am I wrong?

I think first approach is easier but I do not know is it correct and best way to solve that problem? I am not using SSL yet, i am just trying to make authentification feature with JWT


Solution

  • Authentication servers like Keycloak usually use a pair of private and public keys (https://en.wikipedia.org/wiki/Public-key_cryptography).

    The authentication server is the only one that knows the private key. It uses the private key to sign the JWT.

    All the other components know the public key. They use the public key to verify that the JWT has been signed with the private key.

    You can freely distribute or expose the public key, as it is only possible to verify signature with this key. Every component that trust the authentication can query the authentication server to get its public key.