Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the expected behavior when setting `security.oauth2.resource.jwk.key-set-uri` in spring boot

Tags:

spring-boot

In spring boot, upon configuring a Resource server we have the option to set the security.oauth2.resource.jwk.key-set-uri property if the access tokens will be JWTs and the issuer provides an endpoint for clients to acquire the public RSA key for verification in JWK format.

What is the expected behavior to initiate a keystore from this JWK? The property is being loaded in the ResourceServerProperties.JWK but then what. Should spring boot call this URI and fetch the jwks then create a store for me to use in verification?

I am following this tutorial to setup the configuration of the keystore http://www.baeldung.com/spring-security-oauth-jwt

    @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);
        return converter;
    }

But instead of loading a .pem public key I think I want to load it from a jwk.

like image 357
Aly T. Ibrahim Avatar asked Sep 28 '17 09:09

Aly T. Ibrahim


People also ask

What is OAuth 2.0 and how it works in spring boot?

OAuth2 is an authorization framework that enables the application Web Security to access the resources from the client. To build an OAuth2 application, we need to focus on the Grant Type (Authorization code), Client ID and Client secret.

How does OAuth2 work in REST API spring boot?

It works by delegating user authentication to the service that hosts the user account and authorizing third-party applications to access the user account. Oauth2 provides authorization flows for web and desktop applications, and mobile devices.

What is Jwk URI?

The JSON Web Key Set (JWKS) is a set of keys containing the public keys used to verify any JSON Web Token (JWT) issued by the Authorization Server and signed using the RS256 signing algorithm.


1 Answers

If you want to use JWKS, use JwkTokenStore in place of JwtTokenStore.

spring-security-oauth2/jwk internally implements key loading and management according to the auth0 spec

You can also see docs on auto-configuration of the same, however i feel configuring it in quite straight-forward (see below).

We don't have to do any verification as JwkTokenStore sets up the verification with JwkDefinitionSource JwkVerifyingJwtAccessTokenConverter using JWKS exposed at @Value("{jsecurity.oauth2.resource.jwk.key-set-uri}")

However, the spring-security-oauth2/jwk classes from spring don't have any public constructors, we often need and can perform any custom steps in AccessTokenConversion, like a common need is to extract jwt content to auth context, we can always inject a custom converter to JwkTokenStore

import org.springframework.security.oauth2.provider.token.store.jwk.*;
import org.springframework.security.oauth2.provider.token.store.*
import org.springframework.security.oauth2.provider.token.*;
import java.utl.*;

@Configuration
class JwtConfiguration {

  @Bean
  public DefaultTokenServices tokenServices(final TokenStore tokenStore) {
    final DefaultTokenServices dts = new DefaultTokenServices();
    dts.setTokenStore(tokenStore);
    dts.setSupportRefreshToken(true);
    return dts;
  }

  @Bean
  public TokenStore tokenStore( 
    @Value("{jsecurity.oauth2.resource.jwk.key-set-uri}") final String jwksUrl,
    final JwtAccessTokenConverter jwtAccessTokenConverter) {
    return new  JwkTokenStore(jwksUrl, jwtAccessTokenConverter, null);
  }

  @Bean
  public JwtAccessTokenConverter createJwtAccessTokenConverter() {
    final JwtAccessTokenConverter converter;   
    converter.setAccessTokenConverter(new  DefaultAccessTokenConverter() {
      @Override
      public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
        final OAuth2Authentication auth = super.extractAuthentication(map);
        auth.setDetails(map); //this will get spring to copy JWT content into 
        return auth;
        }

      }
    return conveter;
  }

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableResourceServer
class ResourceServerConfig extends ResourceServerConfigurerAdapter {

  private String resourceId;
  private TokenStore tokenStore;

  public ResourceServerConfig(
    @Value("\${jwt.reourceId}") private String resourceId,
    private TokenStore tokenStore) {
           this.resourceId = resourceId;
           this.tokenStore = tokenStore;
  }

  /**
  * Ensures request to all endpoints ore a
  @Override 
  public void configure(final HttpSecurity http) {
    http.csrf().disable()
     .authorizeRequests()
     .antMatchers("/**").authenticated();
  }

  /**
  * Configure resources
  * Spring OAuth expects "aud" claim in JWT token. That claim's value should match to the resourceId value
  * (if not specified it defaults to "oauth2-resource").
  */
   @Override 
   public void configure(final ResourceServerSecurityConfigurer resources) {
     resources.resourceId(resourceId).tokenStore(tokenStore);
   }
}
like image 166
Simar Singh Avatar answered Jun 03 '23 15:06

Simar Singh