Spring boot Oauth2 Resource Server — Kotlin
Agenda
Spring/ Spring Boot recently had changed the support for oauth2 and have provided resource server based starter dependency spring-boot-starter-oauth2-resource-server.
This means they are providing some special support for configuring your Spring boot based project to act as a resource server out of the box.
This one is just a basic code and has following Assumptions/ Notes to start with:-
- One should be knowing the basics of Spring boot as we are going to use spring-boot-starter-oauth2-resource-server based setup.
- I could have used Java for this? Yes one may, But just wanted to smell some fragrance of Kotlin. One may easily be able to get the Java based working within no time. For java use the branch java here
- Using JDK 11.
- Have basic knowledge of Oauth2, JWT, Spring Boot, Spring Security, Kotlin/Java etc.
- The Authorization Server implementation is out of context for this article, but one may contact/ message me for further understanding around that.
- The Authorization Server will create JWT type access token and payload will match like below(for different format customization will be required):-
7. The main flow is like below, and our focus would be mainly on the 4th one i.e. Resource Server :-
Code
The link to the code repository for Kotlin is — https://github.com/krnbr/demo-resource-server
And for Java it is — https://github.com/krnbr/demo-resource-server/tree/java
Details
- To start with you can see we added two main dependencies in the pom.xml
2. In the spring application.properties we added below properties related to the JWT based authorization
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/.well-known/jwks.json
issuer-uri is for setting the issuer that we will receive in the JWT payload
jwk-set-uri is the JWKS url
3. The project has only one url as of now and it is GET/api/v1/test while other are related to the actuator available at /manage/* and /api/v1/test is protected and annotated with the annotation @PreAuthorize as below:-
@PreAuthorize("hasAuthority('SCOPE_system')")
Above annotation will require the request to have a scope system in access token’s JWT payload as below:-
"scopes": "system",
scopes above can be space separated like below example:-
"scopes": "system messages:read",
4. Other urls available are actuator urls
/manage/info & /manage/health are available to all
all other /manage/* urls will require the request to have an access token with scope of “admin”
5. CustomBearerTokenServerAccessDeniedHandler is a custom access denied handler & CustomBearerTokenServerAuthenticationEntryPoint is a custom authentication entry point. They were brought in to support the return of JSON based error response for few scenarios.
6. HasScope is a custom ReactiveAuthorizationManager to support the kind of access management feature as below(see the bold HasScope):-
// health and info url's will be open(permitted to all) others will be checked for authorization
.matchers(EndpointRequest.to(HealthEndpoint::class.java, InfoEndpoint::class.java)).permitAll()
// all other endpoints will require the scope to be "admin"
.matchers(EndpointRequest.toAnyEndpoint()).access(HasScope("admin"))
7. ApplicationExceptionHandler is the exception handler to handle various exceptions in the application