I've configured a local instance of Keycloak to act as an Identity Broker (kind of a proxy) to Microsoft EntraID, previously known as Azure Active Directory, which is the actual Identity Provider) via Oauth2/OIDC.
I've succeeded in getting an example Spring Boot application to display basic identity information and roles through this setup. However, it will not return roles or groups, except default roles and scopes ROLE_USER, ROLE_USER, SCOPE_email, SCOPE_openid, SCOPE_profile.
I would like it to return roles I've configured specifically for the user. Is this possible?
Here's the relevant code:
application.properties:
server.port=9080
spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.client-id=azure-client-provider
spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.client-secret=xxxx
spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.scope=openid, profile, roles
spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.redirect-uri=http://localhost:9080/login/oauth2/code/azure-client-provider
spring.security.oauth2.client.provider.oauth2-demo-thymeleaf-client.issuer-uri=http://localhost:8180/realms/demoBroker
@RestController
public class RoleController {
@GetMapping("/roles")
public String printScopes(@AuthenticationPrincipal OAuth2User oauth2User) {
// Get the scopes from the OAuth2User object
StringBuilder htmlContent = new StringBuilder("<html><body><h2>User Information</h2>");
// Get user attributes
String userId = oauth2User.getName();
htmlContent.append("<p><strong>User ID:</strong> ").append(userId).append("</p>");
// Get and append all attributes
oauth2User.getAttributes().forEach((key, value) ->
htmlContent.append("<p><strong>").append(key).append(":</strong> ").append(value).append("</p>"));
htmlContent.append("</body></html>");
// Include user authorities (roles)
htmlContent.append("<p><strong>Authorities:</strong> ");
oauth2User.getAuthorities().forEach(authority ->
htmlContent.append(authority.getAuthority()).append(", "));
htmlContent.append("</p>");
System.out.println("User Info (HTML):\n" + htmlContent.toString());
return htmlContent.toString();
}
}
Output:
User Information
User ID: 60e9bd60-xxx
at_hash: gGDXPZxxx
sub: 60e9bdxxx
email_verified: false
iss: http://localhost:8180/realms/demoBroker
typ: ID
preferred_username: xxxxx
given_name: xxxxx
nonce: xxx
sid: xxxx
aud: [azure-client-provider]
acr: 0
azp: azure-client-provider
auth_time: 2024-03-09T15:27:45Z
name: xxxx
exp: 2024-03-09T15:45:25Z
session_state: fababa49-6ca7-42d5-911d-7379c6719bf6
family_name: xxxx
iat: 2024-03-09T15:40:25Z
email: [email protected]
jti: xxxx
Authorities: ROLE_USER, SCOPE_email, SCOPE_openid, SCOPE_profile,
It should be showing some roles I've assigned to the user such as Application Adminstrator, etc.
Any thoughts?
Two steps to have roles from EntraID as Spring Security authorities in your OAuth2 client with
oauth2Login:GrantedAuthoritiesMapperbeanInstead of the second step, you could consider using my starter which will configure the authorities mapper for you, based on application properties you provide (claims to extract roles from, optional prefix and case transformation you want).