-3

I know this question has been answered a number of times ... but all the answers I found refer to earlier versions of Keycloak, and I cannot find the equivalents in the current versions (22.0.1).

I am trying to develop an application that uses OAuth2 login, where the login is referred to keycloak. That's pretty simple to do with the use of org.springframework.boot:spring-boot-starter-oauth2-client, and a security config like this:

public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) {
        httpSecurity.authorizeHttpRequests()
                .anyRequest().authenticated()
                .and()
                .oauth2Login();

       return  httpSecurity.build();
    }

So far, so good. When I navigate to any page, I first have to log in through keycloak, and get forwarded to the page successfully. A call to SecurityContextHolder.getContext().getAuthentication() gets me the content of the token ... but what is missing are the roles that I assigned to the user in Keycloak. So I cannot use role based API access control.

When I follow the many examples that obtain the token through Postman (through /realms/{realm}/protocol/openid-connect/token, the roles are present. I could technically just write my own login screen, and use that approach, but I'd rather let keycloak handle the login (to cover for MFA and stuff).

Is it even possible to get the roles defined in Keycloak through a Spring boot OAuth2 login?

Thx,

Stefan

IndyStef
  • 747
  • 1
  • 6
  • 15

1 Answers1

0

First, and most importantly, Mapping Keycloak roles to Spring authorities has nothing to do with Keycloak version.

Second, you are using oauth2Login => you are configuring an OAuth2 client (not an OAuth2 resource server) and the requests are secured with sessions, not access tokens (just check in your browser debugging tools, you'll find a session cookie but no header with a Bearer token). You should definitely read the OAuth2 essentials section of my tutorials.

About Keycloak roles mapping to Spring authorities, what you have not read, apparently is the Spring Security manual. No more than the accepted answer to this question here on stackoverflow.

Instead of writing a GrantedAuthoritiesMapper or an OAuth2UserService yourself as instructed in the doc, you could use the GrantedAuthoritiesMapper which is auto-configured by the additional starter I wrote, which configures OpenID provider (Keycloak or whatever) roles to Spring authorities mapping with just application properties:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>com.c4-soft.springaddons</groupId>
    <artifactId>spring-addons-starter-oidc</artifactId>
    <version>7.0.6</version>
</dependency>
oauth2-issuer: http://locahost:8080/realms/master
oauth2-client-id: change-me
oauth2-client-secret: change-me

spring:
  security:
    oauth2:
      client:
        provider:
          keycloak:
            issuer-uri: ${oauth2-issuer}
            user-name-attribute: preferred_username
        registration:
          keycloak-authorization-code:
            authorization-grant-type: authorization_code
            client-id: ${oauth2-client-id}
            client-secret: ${oauth2-secret}
            provider: keycloak
            scope: openid,profile,email,offline_access
com:
  c4-soft:
    springaddons:
      oidc:
        ops:
        - iss: ${oauth2-issuer}
          username-claim: $.preferred_username
          authorities:
          # In addition to JSON path, you may define prefix and case transformation
          # for each claim to map to spring authorities
          - path: $.realm_access.roles
          - path: $.resource_access.${oauth2-client-id}.roles
        client:
          security-matchers:
          - /**
          permit-all:
          - /login/**
          - /oauth2/**

That simple. And this works in both reactive and servlet applications configured as OAuth2 clients with oauth2Login.

ch4mp
  • 6,622
  • 6
  • 29
  • 49