Search code examples
springkeycloakopenid-connect

How do I configure Spring to retrieve the OIDC user?


What do I need to do to get the user's OIDC or some information about the current session?

In my program I use Keycloak as an authorization provider.

My SecurityConfig:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http)
            throws Exception {
        http.csrf(AbstractHttpConfigurer::disable);
        http.addFilterAfter(createPolicyEnforcerFilter(),
                BearerTokenAuthenticationFilter.class);

        http.sessionManagement(
                t -> t.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        );
        return http.build();
    }

    private ServletPolicyEnforcerFilter createPolicyEnforcerFilter() {
        return new ServletPolicyEnforcerFilter(new ConfigurationResolver() {
            @Override
            public PolicyEnforcerConfig resolve(HttpRequest request) {
                try {
                    return JsonSerialization.
                            readValue(getClass().getResourceAsStream("/policy-enforcer.json"),
                                    PolicyEnforcerConfig.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
}

policy-enforcer.json:

{
  "realm": "kasia",
  "auth-server-url": "http://localhost:9090",
  "resource": "kasia-security",
  "credentials": {
    "secret": "fHW7Vm6lnNUp3Cmm4IcYbnHlIq5CZ69Z"
  },
  "paths" : [
    {
      "path": "/test/api/public",
      "enforcement-mode": "DISABLED"
    },{
      "path": "/swagger-ui/*",
      "enforcement-mode": "DISABLED"
    },{
      "path": "/v3/api-docs/*",
      "enforcement-mode": "DISABLED"
    }
  ]
}

My controller is where I should get the OIDC of the user:

@GetMapping("/api/v1/user")
public ResponseEntity<?> testUser(@AuthenticationPrincipal OidcUser user) {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    return ResponseEntity.ok("You have accessed the resource and you have the USER role");
}

At the moment my user is null and authentication contains the following data (no matter which account I log in with):

AnonymousAuthenticationToken [
Principal="anonymousUser",
Credentials=[PROTECTED],
Authenticated=true,
Details=WebAuthenticationDetails [
    RemoteIpAddress=0:0:0:0:0:0:0:0:0:0:0:0:1,
    SessionId=null
],
Granted Authorities=[ROLE_ANONYMOUS]
]

UPD. I also send the JWT token in my request:

eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6eTdPbVN1b3NTVGJCUlhEYnRzZFBtOUtDV3FBQWZhQy1iMzh6RHBVOTlVIn0.eyJleHAiOjE3MDM4MTMyNDgsImlhdCI6MTcwMzgxMjM0OCwiYXV0aF90aW1lIjoxNzAzODEwNDIzLCJqdGkiOiIyODA4NjA0Mi05NjU2LTRhNzktYjNjMy05MjYyMDc4OWE0YWMiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjkwOTAvcmVhbG1zL2thc2lhIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjMwMWVlZDdlLWFmOTYtNDRjMC05MDc1LWVjZjBiNDY2NDVkMSIsInR5cCI6IkJlYXJlciIsImF6cCI6Imthc2lhLXNlY3VyaXR5Iiwibm9uY2UiOiI5YmI0Y2ZmOS1jMmNkLTQ5MTQtOGY2MS02MDUyNDFkYzE2YmIiLCJzZXNzaW9uX3N0YXRlIjoiYTE1NWNmMGEtYmQwYi00MGUxLTkxMWUtYmZiZWQ1OTU1MTRlIiwiYWNyIjoiMCIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjgwODAiLCIqIiwiaHR0cDovL2xvY2FsaG9zdDozMDAwLyIsImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC8iLCJodHRwOi8vbG9jYWxob3N0OjMwMDAiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMta2FzaWEiLCJST0xFX1VTRVIiLCJvZmZsaW5lX2FjY2VzcyIsIlJPTEVfQURNSU4iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJzaWQiOiJhMTU1Y2YwYS1iZDBiLTQwZTEtOTExZS1iZmJlZDU5NTUxNGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInJvbGVzIjpbImRlZmF1bHQtcm9sZXMta2FzaWEiLCJST0xFX1VTRVIiLCJvZmZsaW5lX2FjY2VzcyIsIlJPTEVfQURNSU4iLCJ1bWFfYXV0aG9yaXphdGlvbiJdLCJuYW1lIjoiQXJ0ZW0gRHViZW5rbyIsInByZWZlcnJlZF91c2VybmFtZSI6ImFydGVtLmR1YmVua28wMzA4QGdtYWlsLmNvbSIsImdpdmVuX25hbWUiOiJBcnRlbSIsImZhbWlseV9uYW1lIjoiRHViZW5rbyIsImVtYWlsIjoiYXJ0ZW0uZHViZW5rbzAzMDhAZ21haWwuY29tIn0.Uy26DtYh_d3vRXqSOosNxIp8qVKPKQtUiId6DqTPVAzO-YmDyDgx0QjdTtDEH9mZbA06qKSeRTgbaBkINAZG5I9GvAgFMrAyw1VJ-1cOu-sIr1JZHJDan4uDB2gn2CpOFC2OkXfu3RbrI6hrH7_POUN4v70oWeG1lb4oHMfXVwiAMMduaoNiMXDTNojB3O_3bd4L5DqgQYsvq5sB-FAqqe-XpqhUGLvQ8c26AYRyocDg5wG_9QsK1JaN4MljRqcGHXEYcKYJsc7R3kDDRjzjP-by_NR4ooTxdUkyInq4iAVZXTimrmP_RU4eTQWxfVowhs3BvFjllSHemJYTdyT63A

Solution

  • In your question: "some information about the current session" and in your conf: sessionCreationPolicy(SessionCreationPolicy.STATELESS). Do you get the inconsistency?

    OidcUser is the principal of an OAuth2AthenticationToken on an OAuth2 client with oauth2Login() in an OIDC environment (authorized with sessions), when you are apparently trying to configure a resource server (REST API authorized with JWT).

    Also, your ServletPolicyEnforcerFilter might be part of Keycloak adapters which were deprecated two years ago and which aren't compatible with Spring Security 6 / Spring Boot 3