Search code examples
spring-security-oauth2

Spring OAuth2 Making `state` param at least 32 characters long


I am attempting to authorize against an external identity provider. Everything seems setup fine, but I keep getting a validation error with my identity provider because the state parameter automatically tacked onto my authorization request is not long enough:

For example: &state=uYG5DC

The requirements of my IDP say that this state param must be at least 32-characters long. How can I programmatically increase the size of this auto-generated number?

Even if I could generate this number myself, it is not possible to override with other methods I have seen suggested. The following attempt fails because my manual setting of ?state=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz is superceded by the autogenerated param placed after it during the actual request:

@Bean
public OAuth2ProtectedResourceDetails loginGovOpenId() {
    AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails() {
        @Override
        public String getUserAuthorizationUri() {
            return super.getUserAuthorizationUri() + "?state=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
        }
    };
    details.setClientId(clientId);
    details.setAccessTokenUri(accessTokenUri);
    details.setUserAuthorizationUri(userAuthorizationUri);
    details.setScope(Arrays.asList("openid", "email"));
    details.setPreEstablishedRedirectUri(redirectUri);
    details.setUseCurrentUri(true);
    return details;
}

The 6-character setting seems to be set here, is there a way to override this? https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/util/RandomValueStringGenerator.java


Solution

  • With the help of this post: spring security StateKeyGenerator custom instance

    I was able to come up with a working solution.

    In my configuration class marked with these annotations:

    @Configuration
    @EnableOAuth2Client
    

    I configured the following beans:

    @Bean
    public OAuth2ProtectedResourceDetails loginGovOpenId() {
        AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
        AuthorizationCodeResourceDetails details = new 
        details.setClientId(clientId);
        details.setClientSecret(clientSecret);
        details.setAccessTokenUri(accessTokenUri);
        details.setUserAuthorizationUri(userAuthorizationUri);
        details.setScope(Arrays.asList("openid", "email"));
        details.setPreEstablishedRedirectUri(redirectUri);
        details.setUseCurrentUri(true);
        return details;
    }
    
    @Bean
    public StateKeyGenerator stateKeyGenerator() {
        return new CustomStateKeyGenerator();
    }
    
    @Bean
    public AccessTokenProvider accessTokenProvider() {
        AuthorizationCodeAccessTokenProvider accessTokenProvider = new AuthorizationCodeAccessTokenProvider();
        accessTokenProvider.setStateKeyGenerator(stateKeyGenerator());
        return accessTokenProvider;
    }
    
    @Bean
    public OAuth2RestTemplate loginGovOpenIdTemplate(final OAuth2ClientContext clientContext) {
        final OAuth2RestTemplate template = new OAuth2RestTemplate(loginGovOpenId(), clientContext);
        template.setAccessTokenProvider(accessTokenProvider());
        return template;
    }
    

    Where my CustomStateKeyGenerator implementation class looks as follows:

    public class CustomStateKeyGenerator implements StateKeyGenerator {
    
      // login.gov requires state to be at least 32-characters long
      private static int length = 32;
      private RandomValueStringGenerator generator = new RandomValueStringGenerator(length);
    
      @Override
      public String generateKey(OAuth2ProtectedResourceDetails resource) {
          return generator.generate();
      }
    }