kirill1722
kirill1722

Reputation: 21

OAuth2 multiple keys, public key migration, Resource Server

My System: A Security Provider generates JWT Tokens based on a Private Key. The Private Key belongs to a Certificate which will expire.

  1. Is it possible to set multiple Public Keys in Resource Server?

I would like to do a rolling Update, so for a short time it has to Support the old Public Key and a new Public Key. Thats a default use case because the certificates expires.?

  1. Can oauth/token_key deliver multiple Keys or just one?

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        Resource resource = new ClassPathResource("public.txt");
        String publicKey = null;
        try {
            publicKey = IOUtils.toString(resource.getInputStream());
        } 
        catch (final IOException e) { throw new RuntimeException(e);
    }
        **converter.setVerifierKey(publicKey);**
        **converter.setVerifierKeys(publicKey1, publicKey2);?**
        return converter;
    }
    

http://www.baeldung.com/spring-security-oauth-jwt

Thanks

Upvotes: 0

Views: 1893

Answers (1)

cosbor11
cosbor11

Reputation: 16034

This is not standard practice and Spring's jwt framework does not support multiple security providers (or multiple active verifier keys) out-of-the-box. Having said that, what you wish to do is theoretically possible. You would have wire-up a new implementation for the AccessTokenConverter similar to the JwtAccessTokenConverter, but implement the decode method like this:

protected Map<String, Object> decode(String token) {
    try {
        Jwt jwt = JwtHelper.decodeAndVerify(token, verifier1);
        String content = jwt.getClaims();
        Map<String, Object> map = objectMapper.parseMap(content);
        if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) {
            Integer intValue = (Integer) map.get(EXP);
            map.put(EXP, new Long(intValue));
        }
        return map;
    }
    catch (Exception e) {
      //try the other verifier
      try {
        Jwt jwt = JwtHelper.decodeAndVerify(token, verifier2);
        String content = jwt.getClaims();
        Map<String, Object> map = objectMapper.parseMap(content);
        if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) {
            Integer intValue = (Integer) map.get(EXP);
            map.put(EXP, new Long(intValue));
        }
        return map;
    }
    catch(InvalidTokenException te){
       throw te;
    }catch (Exception e) {

        throw new InvalidTokenException("Cannot convert access token to JSON", e);
    }
    }
}

Essentially, the code above trys to verify the first key but if any exception is thrown it will try to validate the second one.

I would also suggest you override to tokenConverter to split the provided token by some delimiter like a "." or something that is not in the encoding char set of your hash algo that generates the verifier key. Then when calling the you could do: setVerifierKey("verifierKey1" + delimiter + "verifierKey2")

  • Note: I have not tested this code, just some thoughts :)

Upvotes: 2

Related Questions