3

Following the documentation here and there, I managed to setup an Authorization Server that gives out JWT access tokens signed with asymmetric key, which are verified locally by a Resource Server using a local copy of the public key. So far so good.

My final goal is for Resource Servers to use the JWKS endpoint on the Authorization Server, and use the 'kid' header in the JWT to lookup the right key in the JWKS and verify locally, supporting key rotation. I've found how to make the Authorization Server expose a JWKS endpoint, and also how to specify the key-set-uri for the resource server.

However, it seems that there is no way to

  • publish kid (key id) values in the JWKS
  • include the kid header in the JWT

Is there a way to do this?

Free Willaert
  • 1,139
  • 4
  • 12
  • 24

2 Answers2

2

I found a way to set the kid in jwks endpoint:

@FrameworkEndpoint
public class JwkSetEndpoint {
    private final KeyPair keyPair;

    public JwkSetEndpoint(KeyPair keyPair) {
        this.keyPair = keyPair;
    }

    @GetMapping("/.well-known/jwks.json")
    @ResponseBody
    public Map<String, Object> getKey() {
        RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic();
        RSAKey key = new RSAKey.Builder(publicKey)
                .keyID("YOUR_KID_HERE")
                .keyUse(KeyUse.SIGNATURE).build();
        return new JWKSet(key).toJSONObject();
    }
}

What I did not find was a way to set it in the header of JWT.

Franziskus Karsunke
  • 4,948
  • 3
  • 40
  • 54
1

While having the same problem I stumbled upon this post. So i hope it will be useful to someone. I do not think this is the best solution, so maybe some one comes up with a better answer i hope like setting some external bean for example.

Background: The Jwk store is comparing the KID in the token header with the one in memory if not available it will request the well-known endpoint

So putting the KID in the JwkSetEndpoint will result in a json file with the kid inside. next to this you need to get the KID on the header of the jwt token.

my solution in my class which extends JwtAccessTokenConverter

@Override
protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
    String content = null;
    try {
        content = objectMapper.formatMap(getAccessTokenConverter().convertAccessToken(accessToken, authentication));
    } catch (Exception e) {
        throw new IllegalStateException("Cannot convert access token to JSON", e);
    }
    Map<String, String> headers = getJwtHeader();

    String token = JwtHelper.encode(content, signer, headers).getEncoded();
    return token;
}

next to the KID header the Tokenstore expects a use header set to signing. i also had to override the signer object because i got stuck with a hmac signer instead of the desired RsaSigner.

Ziel
  • 21
  • 1