Securing REST API using Keycloak and Spring Oauth2
Keycloak is Open Source Identity and Access Management Server, which is a OAuth2 and OpenID Connect(OIDC) protocol complaint. This article is to explain how Spring Boot REST APIs can be secured with Keycloak using Spring OAuth2 library.
Keycloak documentation suggest 3 ways to secure Spring based REST APIS.
- Using Keycloak Spring Boot Adapter
- Using keycloak Spring Security Adapter
- Using OpenID Connect (OIDC)+ OAuth2
Let us see how we can use Keycloak OIDC support and Spring OAuth2 library to secure REST APIs. Benefits Of Using Spring OAuth2 Over Keycloak Adapter is explained at the end of this article.
Let us explore how to setup Keycloak and interact with it using Spring OAuth2 library.
This is a lengthy article with step by step instructions, screenshots, code snippets. Complete code is available on github. I recommend reading this article before looking into the code.
Step 1: Getting Started With Keycloak
Refer Keycloak getting started documentation to run and setup keycloak admin user.
After running Keycloak, access keycloak admin console using http://localhost:8080/auth
Setup keycloak username=admin, password=admin.
Note: Standalone Keycloak runs on Wildfly server. Don’t worry about configuring a user to manage Wildfly server. We need a Keycloak admin user to create realm, client, user, role etc in Keycloak.
Step 2: Create dev Realm
Step 3: Create a Client (Micro-Service)
Client ID : employee-service
Client Protocol : openid-connect
Step 4: Configure Client
If Keycloak runs on Port 8080, make sure your microservice runs on another port. In the example, micro-service is configured to run on 8085.
Access Type : confidential
Valid Redirect URIs : http://localhost:8085
# Required for micro-service to micro-service secured calls
Service Accounts Enabled : On
Authorization Enabled : On
Note: Access Type confidential supports getting access token using client credentials and well as using bearer token. If a micro-service need to call another micro-service, caller will be ‘confidential’ and callee will be ‘bearer-only’.
Step 5: Create Client Role
Create a role under the client. In this case, role USER is created under employee-service.
Step 6: Create a Mapper (To get user_name in access token)
By default, Keycloak has “preferred_username” in access token. Spring Security OAuth2 Resource Server expects an element named “user_name” in access token. Hence we had to create below mapper.
Step 7: Create User
Step 8: Map Client Role To User
In order to provide access to client (micro-service), respective role needs to be assigned/mapped to user.
Step 9: Get Configuration From OpenID Configuration Endpoint
Because Keycloak is OpenID Connect and OAuth2 complaint, below is OpenID Connection configuration URL to get details about all security endpoints,
Important URLS from copied from response:
Response also contains grant types and scopes supported
grant_types_supported : ["client_credentials", …]
scopes_supported: ["openid", …]
Step 10: Create a Spring Boot Application
<relativePath/> <!-- lookup parent from repository -->
Step 11: Configure application.properties
General Security Properties
# Can be set to false to disable security during local development
Properties to secure REST Endpoints using OAuth2 Resource Server
security.oauth2.resource.jwt.key-value=-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhWOcKAVAwt+5FF/eE2hLaMVD5zQBBr+RLdc7HFUrlvU9Pm548rnD+zRTfOhnl5b6qMjtpLTRe3fG+8chjPwQriRyFKCzg7eYNxuR/2sK4okJbfQSZFs16TFhXtoQW5tWnzK6PqcB2Bpmy3x7QN78Hi04CjNrPz2BX8U+5BYMavYJANpp4XzPE8fZxlROmSSyNeyJdW30rJ/hsWZJ5nnxSZ685eT4IIUHM4g+sQQTZxnCUnazNXng5B5yZz/sh+9GOXDGT286fWdGbhGKU8oujjSJLOHYewFZX5Jw8aMrKKspL/6glRLSiV8FlEHbeRWxFffjZs/D+e9A56XuRJSQ9QIDAQAB\n-----END PUBLIC KEY-----
Note 1: security.oauth2.resource.jwt.key-value property value can be copied from public key at realm level. This is very important and this property is what uses JwtAccessTokenCustomizer which we will see later.
Note 2: Property values will be different based on your configuration, care should be take to use correct values.
Properties to call another micro-service (Service Accounts)
# If this micro-services that needs to call another
# secured micro-service
Note: Above properties are required for OAuth2RestTemplate that is used to make secure service account calls.
Step 12: JWT Access Token Customizer
In order for Spring OAuth2 to parse and set SecurityConextHolder, it needs the roles or authorities from token. Also, in order to determine the list of clients/application/micro-service a user has access, it needs the list of client ids from token. This is the only setup that needs some special handling.
Step 13: OAuth2 Resource Server Configurer
Note: OAuth2RestTemplate is required if this micro-service needs to call another micro-service.
Step 14: Secure REST Endpoints
PreAuthorize annotation is use to secure REST endpoints with appropriate roles. Refer below example.
Step 15: Disable Basic Auth if not required
In order to disable default security, SecurityAutoConfiguration and UserDetailsServiceAutoConfiguration can be excluded.
For Complete Code
Benefits Of Using Spring OAuth2 Over Keycloak Adapters:
- Most of the time, Keycloak Server upgrade requires upgrading Keycloak adapter as well. If Keycloak adapters were used in 100s of micro-services, then all these micro-services needs to be upgraded to use newer version of Keycloak adapter. This requires regression testing of all micro-services and it is time consuming. This can be avoided by using Spring OAuth2 which integrates with Keycloak at protocol level. As these protocols don’t change often and Keycloak Server upgrade will continue to support the respective protocol version, no change is required in micro-services when Keycloak Server is upgraded.
- Sometimes, Spring Boot version upgrade requires Keycloak and Keycloak Spring Boot adapter or Keycloak Spring Security adapter to be upgraded. This can be avoided if we use Spring OAuth2.
- If organization decides to migrate from Keycloak to Okta (or another OAuth2 OpenID Connect Provider), all the micro-services that used Keycloak Spring Boot adapter and Keyclock Spring Security needs to be refactored significantly. Using Spring OAuth2 + Spring Security can significantly simplify the migrations.
- OAuthRestTemplate class available in Spring OAuth2 takes care of refreshing on need and caching access tokens (OAuth2Context). This is a great benefit when there is a need to securely interact between micro-services.
This post describes OAuth 2.0 in a simplified format to help developers and service providers implement the protocol…aaronparecki.com
In this article, the fundamentals of what JSON Web Tokens (JWT) are, and why they are used will be explained. JWT are…medium.com
As I understand it, a JSON Web Token (JWT) consists of 3 parts: the header, specifying the hashing algorithm to use for…crypto.stackexchange.com
The Authorization Code flow redirects the user agent to Keycloak. Once the user has successfully authenticated with…www.keycloak.org