Start example server

mvn spring-boot:run

Chapter 14. OAuth 2: Implementing the resource server

14.1 Implementing a resource server

ssia-ch14-ex1-rs

pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
pom.xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
HelloController.java
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello!";
    }
}
ResourceServerConfig.java
@Configuration
@EnableResourceServer
public class ResourceServerConfig {
}

14.2 Checking the token remotely

ssia-ch14-ex1-as

AuthServerConfig.java
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig
        extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client")
                .secret("secret")
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("read")
        .and()
                .withClient("resourceserver")            (2)
                .secret("resourceserversecret");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(authenticationManager);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security.checkTokenAccess("isAuthenticated()");   (1)
    }
}
1 Specifies the condition for which we can call the check_token endpoint
2 Adds a set of credentials for the resource server to use when calling the /oauth/ check_token endpoint
curl -v -XPOST -u client:secret "http://localhost:8080/oauth/token?grant_type=password&username=john&password=12345&scope=read"

curl -XPOST -u resourceserver:resourceserversecret "http://localhost:8080/oauth/check_token?token=ef63fec7-fd58-4fed-a381-cd4f4e223b16"

curl -H "Authorization: bearer ef63fec7-fd58-4fed-a381-cd4f4e223b16" "http://localhost:9090/hello"

ssia-ch14-ex1-rs-migration

pom.xml
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-resource-server</artifactId>
    <version>5.2.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.nimbusds</groupId>
    <artifactId>oauth2-oidc-sdk</artifactId>
    <version>8.4</version>
    <scope>runtime</scope>
</dependency>
ResourceServerConfig.java
@Configuration
public class ResourceServerConfig
        extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and().oauth2ResourceServer(
                c -> c.opaqueToken(
                        o -> {
                            o.introspectionUri("http://localhost:8080/oauth/check_token");
                            o.introspectionClientCredentials("resourceserver", "resourceserversecret");
                        })
        );
    }
}

14.3 Implementing blackboarding with a JdbcTokenStore

2022-01-20: To be continued…​

Chapter 15. OAuth 2: Using JWT and cryptographic signatures

15.1 Using tokens signed with symmetric keys with JWT

15.1.1 Using JWTs

15.1.2 Implementing an authorization server to issue JWTs
ssia-ch15-ex1-as
pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
AuthServerConfig.java
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig
        extends AuthorizationServerConfigurerAdapter {

    @Value("${jwt.key}")
    private String jwtKey;  (1)

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client")
                .secret("secret")
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("read");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
          .authenticationManager(authenticationManager)
          .tokenStore(tokenStore())                           (2)
          .accessTokenConverter(jwtAccessTokenConverter());
    }

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

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        var converter = new JwtAccessTokenConverter();
        converter.setSigningKey(jwtKey);                      (4)
        return converter;
    }
}
1 Gets the value of the symmetric key from the application.properties file
2 Configures the token store and the access token converter objects
3 Creates a token store with an access token converter associated to it
4 Sets the value of the symmetric key for the access token converter object
WebSecurityConfig.java
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public UserDetailsService uds() {
        var uds = new InMemoryUserDetailsManager();

        var u = User.withUsername("john")
                .password("12345")
                .authorities("read")
                .build();

        uds.createUser(u);

        return uds;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}
curl -v -XPOST -u client:secret http://localhost:8080/oauth/token?grant_type=password&username=john&password=12345&scope=read
15.1.3 Implementing a resource server that uses JWT
ssia-ch15-ex1-rs
pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
HelloController.java
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello!";
    }
}
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Value("${jwt.key}")
    private String jwtKey;     (1)

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.tokenStore(tokenStore());                      (2)
    }

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

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        var converter = new JwtAccessTokenConverter();           (4)
        converter.setSigningKey(jwtKey);
        return converter;
    }
}
1 Injects the key value from the application.properties file
2 Configures the TokenStore
3 Declares the TokenStore and adds it to the Spring context
4 Creates an access token converter and sets the symmetric key used to validate token signatures
curl -H "Authorization:Bearer eyJhbGciOiJIUzI1NiIs..." http://localhost:9090/hello