Skip to content

OAuth2 Resource Server

Resource server provides access to resources and functionality. Resources are protected from unauthorized access. We can also say this server provides API, which is protected by Access control based on OAuth2 (JWT) tokens. We do not need to reinvent wheel, but utilize existing implementation provided by the Spring Security OAuth2/OIDC.

Spring Security OAuth Resource Server add useful capabilities to your application as access token validation and introspection. The Resource Servers communicates with the Authorization server transparently on background, and you do not need to deal with OAuth details.

There is simple application used for this lab, which exposes several API endpoints protected by OAuth2, which means every API request must include Authorization header with valid access token. The token is of type Bearer.

  1. To turn the application into OAuth2 compatible Resource server utilizing Spring Boot, you need to add respective starter into build.gradle file:

      implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
    
  2. You need to configure Resource server to find Auth Server endpoints. The OpenID discovery feature is used, which uses standard Auth Server configuration endpoint to discover other endpoints. The Resource Server adds access token validation filter to API call processing. Validation includes token signature verification, so Resource Server need Auth Server public key, which is automatically downloaded and cached in application. ADD FOLLOWING SECTION INTO application.yaml file.

      spring:
        security:
          oauth2:
            resourceserver:
              jwt:
                issuer-uri: http://auth-server:9000
    
  3. Project includes AuthenticationConverter, which maps roles includes in access token into Spring Security Authorities. The Auth Server encodes roles into token. You need to set custom converter to Resource Server configuration. Modify SecurityFilterChain bean in SecurityConfig class as follows:

      http.authorizeHttpRequests(authorize -> authorize
                       .requestMatchers("/api/ping").anonymous()
               .anyRequest().authenticated()
               // Set custom JWT converter which maps grants from access token
               ).oauth2ResourceServer(oauth2 ->
               oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(new AuthenticationConverter()))
       );
    
  4. Now restart the application nad test API. API requires access token. You can use postman Authorization feature to get one.

Try CORS

Pre-flight request with OPTION:

curl http://localhost:8090/api/ping \
   -X OPTIONS \
   -H "User-Agent: Mozilla/5.0" \
   -H "Access-Control-Request-Method: GET" \
   -H "Access-Control-Request-Headers: content-type" \
   -H "Origin: http://localhost:8080" \
   -v 

Accepted request:

curl http://localhost:8090/api/ping \
   -X GET \
   -H "User-Agent: Mozilla/5.0" \
   -H "Origin: http://localhost:8080" \
   -v

Rejected request as Origin myhost is not allowed:

curl http://localhost:8090/api/ping \
   -X GET \
   -H "User-Agent: Mozilla/5.0" \
   -H "Origin: http://myhost" \
   -v