2
votes

I am building microservice applications with spring cloud, oauth and JWT. My Oauth2 server generates JWT token but when I am trying to validate the token in gateway (implemented using ZUUL) I am getting below Error

Could you please let me know what is wrong and what could be the solution. I am using Spring 4.3, Spring boot 1.5.8, Spring cloud Dalston.SR4

org.springframework.security.jwt.crypto.sign.InvalidSignatureException: Calculated signature did not match actual value
    at org.springframework.security.jwt.crypto.sign.MacSigner.verify(MacSigner.java:62) ~[spring-security-jwt-1.0.8.RELEASE.jar:na]
    at org.springframework.security.jwt.JwtImpl.verifySignature(JwtHelper.java:287) ~[spring-security-jwt-1.0.8.RELEASE.jar:na]
    at org.springframework.security.jwt.JwtHelper.decodeAndVerify(JwtHelper.java:77) ~[spring-security-jwt-1.0.8.RELEASE.jar:na]
    at com.debopam.gateway.filter.CustomPostZuulFilter.run(CustomPostZuulFilter.java:57) ~[classes/:na]
    at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) [zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193) [zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157) [zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.FilterProcessor.postRoute(FilterProcessor.java:92) [zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.ZuulRunner.postRoute(ZuulRunner.java:87) [zuul-core-1.3.0.jar:1.3.0]

I have used signing key 12345AsDfG in both Auth server and gateway server.

Below Are the code snippet Auth Server

@Configuration
public class JWTTokenStoreConfig {

    @Autowired
    private ServiceConfig serviceConfig;

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        defaultTokenServices.setAccessTokenValiditySeconds(60*30);
        return defaultTokenServices;
    }


    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(serviceConfig.getJwtSigningKey());
        return converter;
    }

    @Bean
    public TokenEnhancer jwtTokenEnhancer() {
        return new JWTTokenEnhancer();
    }
}


@Configuration
public class JWTOAuth2Config extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private DefaultTokenServices tokenServices;

    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Autowired
    private TokenEnhancer jwtTokenEnhancer;


    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception
    {
        //oauthServer.checkTokenAccess("permitAll()");    

        oauthServer
        .tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')")
        .checkTokenAccess("permitAll()");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer, jwtAccessTokenConverter));

        endpoints.tokenStore(tokenStore)                             //JWT
                .accessTokenConverter(jwtAccessTokenConverter)       //JWT
                .tokenEnhancer(tokenEnhancerChain)                   //JWT
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);


    }



    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        clients.inMemory()
                .withClient("uiapp")
                .secret("secret")
                .authorizedGrantTypes("refresh_token", "password", "client_credentials")
                .scopes("webclient", "mobileclient");
    }
}

In the Gateway application, I am using below code to verify the Token

@Override
public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    try {
        InputStream is = ctx.getResponseDataStream();
        String responseBody = IOUtils.toString(is);

        if (StringUtils.hasText(responseBody) 
                && responseBody.contains("access_token")) {
            Map<String, Object> responseMap = objectMapper.readValue(
                    responseBody, new TypeReference<Map<String, Object>>() {});
            String accesToken = responseMap.get("access_token").toString();

            Jwt jwt = JwtHelper.decodeAndVerify(accesToken, new MacSigner(serviceConfig.getJwtSigningKey()));

            System.out.println(jwt.getClaims());
            //System.out.println(jwt.getBody());

        }
        ctx.setResponseBody(responseBody);
    } catch (Exception e) {
        logger.error("Error occured in zuul post filter", e);
    }
    return null;
}
1
I looked through other implementations and tests in spring oauth, but didn't find nothing. I would debug it. is the token in the right format on arrival? is it the same as was produced? is the key the same on both ends?MarianP
Sorry, there was a key mismatch between the services.Debopam

1 Answers

0
votes

There was a signing key mismatch between the services.