Client Credentials Resource Server#
- In the Keycloak Setup, we learned how to set up
Keycloak
authorization server forClient Credentials Grant Type
. Now, in this section, we will continue to configure a Spring BootToken Signature
Resource Server to verify in coming token withKeycloak
before accessing the data. - If you haven't know about
Token Signature
Resource Server, you can view this post: OAUTH2 Resource Server Token Validation.
Prepare#
- So firstly, we need to overview the simple diagram that we are going to do as in the image below.
- So as you can see, when the
Resource Server
is starting up, then it will call to the Keycloak authorization server to get the public key. - Then if the
Client
calls to Keycloak authorization server to get the access token, the the Keycloak authorization server will generate and use it's private key to sign the access token and send back to client. - Then when the client call to
Resource Server
with the access token. So theResource Server
will use the public key which is downloaded from Keycloak authorization server in the start up time to verify the token and check it is valid of not to make sure the token is no tampered.
As the authorization server makes available new public keys, Spring Security will automatically rotate the public keys used to validate access tokens.
-
So with the
Token Signature
Resource Server. Whenever theClient
sends the same access token to theResource Server
, it doesn't have to make a call toAuth Server
or doesn't have to look into the database. It can simply check the signature or hash value of the token generated with the encryption algorithm that it maintains to understand the token is valid or not. -
For setting up Keycloak authorization server please view Keycloak Setup with Client Credentials Grant Type.
Resource Server Setup#
Dependencies#
- Now, let's create a Spring Boot application and add some dependencies as below.
pom.xml | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
- To make Spring Boot application become resource service we need to apply
spring-boot-starter-security
andspring-boot-starter-oauth2-resource-server
dependencies.
Controller#
- Let's create a simple controller for the Spring Boot Resource server which will be protected and need the access token which is issued from Keycloak authorization server to access.
CardController.java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Configuration#
- Firstly, we need to create a
KeycloakRoleConverter.java
as below.
KeycloakRoleConverter.java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
- This converter class is used to extract the
roles
from the jwt access token. The roles field is a part of the claimrealm_access
. Each role will be converted to aSimpleGrantedAuthority
object. - Let's take a look into the access token that we got in the Keycloak Setup, then we can see where the roles field of access token is stored.
- Now, let's continue to create the
ProjectSecurityConfig.java
class to configure the security forResource Server
apis as below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
|
- So we will need to create a
PasswordEncoder
withBCryptPasswordEncoder
because the access token is a jwt. - Next, Then for the api security configuration, we will use
hasRole
andhasAnyRole
with the value is the role that we got from the access token (USER, ADMIN). - Finally the most important to make Spring Boot Resource Server security configuration works is the config below:
.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter);
-
In which we will config the jwt authentication conveter for the
oauth2ResourceServer
with theKeycloakRoleConverter
that we created on the step above. So base on this configuration the our Resource Server can read the jwt access token and extract the roles correctly and compare with the roles that we configured in theProjectSecurityConfig.java
. -
Finally, we need to put the configuration as below into the
application.yml
to make the Resource Server can know where to download the public key from the authorization server when the Resource Server starts up.
application.yml | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
- The Url for downloading the public key from the authorization server can be found in the
discovery endpoint
of Keycloak with the parttern as below:
{{KEY_CLOAK_DOMAIN}}/auth/realms/{{REALM_ID}}/protocol/openid-connect/certs
Example:
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/certs
Testing#
- Let's start the Keycloak authorization server first then start the Spring Boot Resource Server application later.
If the authorization server is down when Resource Server queries it (given appropriate timeouts), then startup will fail.
- Then, we can start testing following steps below:
- Firstly, we need to use Postman to call to the Keycloak authorization server to get the access token with the information that we created in the Keycloak Setup Client Credentials Grant Type as in the image below.
- Then we will try to call to the
/v1/card
api that we created from the beginning, then you should received a successful result as below.
- Now, if you wait a little bit about 5 minutes, the token will be expired or you can change a single character in the access token and you call again you will get the 401 error.
- Because the api
/v1/card
need the roleADMIN
to access, so if we go to the Keycloak authorization server and unassign the roleADMIN
out of themyclient
and get access token and try again, then you will get the 403 error as below.
- It means the
v1/card
api require the access token withADMIN
role, but the access token only hasUSER
role, so we will get 403 error code.