My application consists of:
The UI is talking with the backend server via RESTful API using the keycloak client with authorization code grant flow. This is working fine.
Now, I need the additional possibility to access resource of the backend using a system/service account (with usually more permissions than the user). How would you implement this requirement? I thought the client credentials flow would be useful here.
Is it possible to use the OAuth2 client credentials flow with the keycloak client for Spring Boot? I found examples that used the Spring Security OAuth2 client features to achieve a client credentials flow but that feels weird because I already use the keycloak client for the OAuth thing.
Thanks for your answers which helped me a lot. In my UI webapp, I am now able to communicate with the backend either by using the authenticated user OAuth2 token or by using the token from the client credentials flow of my UI service account. Each way has its own RestTemplate
, the first is done via the keycloak integration and second is done by Spring Security OAuth2 as explained here.
Yes, you can use OAuth 2.0 Client Credentials flow and Service Accounts.
Keycloak suggest 3 ways to secure SpringBoot REST services:
Here is a good explanation about this with an example in the OAuth2/OIDC way:
If you follow this example, keep in mind:
Take care to configure your client as:
Take care to configure your target service as:
So, caller should be confidential
and target service should be bearer-only
.
Create your users, roles, mappers... and assign roles to your users.
Check that you have this dependencies in your spring project:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
Configure authentication to be used in the REST client (application.properties) e.g.:
security.oauth2.client.client-id=employee-service
security.oauth2.client.client-secret=68977d81-c59b-49aa-aada-58da9a43a850
security.oauth2.client.user-authorization-uri=${rest.security.issuer-uri}/protocol/openid-connect/auth
security.oauth2.client.access-token-uri=${rest.security.issuer-uri}/protocol/openid-connect/token
security.oauth2.client.scope=openid
security.oauth2.client.grant-type=client_credentials
Implement your JwtAccessTokenCustomizer
and SecurityConfigurer
(ResourceServerConfigurerAdapter) like Arun's sample.
And finally implement your service Controller:
@RestController
@RequestMapping("/api/v1/employees")
public class EmployeeRestController {
@GetMapping(path = "/username")
@PreAuthorize("hasAnyAuthority('ROLE_USER')")
public ResponseEntity<String> getAuthorizedUserName() {
return ResponseEntity.ok(SecurityContextUtils.getUserName());
}
@GetMapping(path = "/roles")
@PreAuthorize("hasAnyAuthority('ROLE_USER')")
public ResponseEntity<Set<String>> getAuthorizedUserRoles() {
return ResponseEntity.ok(SecurityContextUtils.getUserRoles());
}
}
For a complete tutorial, please read the referred Arun's tutorial.
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With