Search code examples
spring-bootopenid-connect

Spring boot + OpenIdConnect: Get information about who the user is on the api request after login


I have to add OpenId Connect as a login option to our application. The application is running spring boot 3.1.2 and the client is a SPA, currently it is possible to redirect to the open id connect login page and get back to our application when the login is succesful, but I can't figure out how to find out who the user is on the subsequent request, the only information the client sends back is the JSESSIONID.

I need to be able to identify the user on the subsequent requests to check the permissions of the user in our local permission manager. I got recommended to link the sessionId to a User and look up the user via the sessionId on the subsequence request. Is this the correct way to handle the identification?

Is there a build in way to do this in spring security (Get the openIdConnection user-information from the session) I have overlooked or do I have to implement a link between a active session and the user. I have not been able a easy way to do this and it feels like I'm trying to work around Spring and not with it.

I have not been able to identify the current session in my OidcUserService, this is the location I have been able to find the user information needed to identify the local user which is linked to the openId user. I have also tried to add a filter after the OAuth2LoginAuthenticationFilter, however here it is not possible to identify the user from the open id connection, the SecurityContextHolder.getContext().getAuthentication() is null. I have also tried to set the authentication in SecurityContextHolder inside the OidcUserService however when setting the authentication I am still not able to retrieve the user in the filter after OAuth2LoginAuthenticationFilter and my filter is running after the OidcUserService.

application.yaml

  security:
    oauth2:
      client:
        registration:
          open-id-connect-client:
            client-id: ...
            client-secret: ...
            redirect-uri: http://localhost:8088/login/oauth2/code/open-id-connect-client
            client-name: open-id-connect-client
            scope: 
              - openid
              - email
              - profile
            authorization-grant-type: authorization_code
        provider:
          open-id-connect-client:
            issuer-uri: ...

SecurityConfig

public class SecurityConfig {

    @Autowired
    AuthenticationService authenticationService;

    private final UserAuthenticationEntryPoint userAuthenticationEntryPoint;
    private final UserAuthProvider userAuthenticationProvider;

    public SecurityConfig(UserAuthenticationEntryPoint userAuthenticationEntryPoint,
                          UserAuthProvider userAuthenticationProvider) {
        this.userAuthenticationEntryPoint = userAuthenticationEntryPoint;
        this.userAuthenticationProvider = userAuthenticationProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager(){
            UserAuthProvider authProvider = new UserAuthProvider(authenticationService);
        return new ProviderManager(authProvider);
    }


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http.exceptionHandling(httpSecurityExceptionHandlingConfigurer -> httpSecurityExceptionHandlingConfigurer
                        .authenticationEntryPoint(new UserAuthenticationEntryPoint())
                        .authenticationEntryPoint(new RedirectAuthenticationEntryPoint())
                )
                .addFilterBefore(new UsernamePasswordAuthFilter(this.userAuthenticationProvider), BasicAuthenticationFilter.class)
                .addFilterBefore(new CookieAuthenticationFilter(this.userAuthenticationProvider), UsernamePasswordAuthFilter.class)
                .addFilterAfter(new AfterOAuth2LoginAuthenticationFilter(), OAuth2LoginAuthenticationFilter.class)
                .addFilterBefore(new MultipleReadEnableFilter(), CookieAuthenticationFilter.class)
                .addFilterBefore(new RequestLoggingFilter(), MultipleReadEnableFilter.class)
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.deleteCookies(CookieAuthenticationFilter.COOKIE_NAME).deleteCookies("JSESSIONID"))
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers(HttpMethod.POST, "/rest/login").permitAll()
                        .requestMatchers(HttpMethod.GET, "/login.html").permitAll()
                        .requestMatchers(HttpMethod.GET, "/login-classic.json").permitAll()
                        .requestMatchers(HttpMethod.GET, "/login-classic.jsonp").permitAll()
                        .requestMatchers(HttpMethod.GET, "/login-classic/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/login-resources/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/sencha-workspace/ext751/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/sencha-workspace/login-app/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/sencha-workspace/build/development/Login/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/sencha-workspace/build/production/Login/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/oauth2/code/open-id-connect-client").permitAll()
                        .anyRequest().authenticated()

                )
                .oauth2Login(oauthLogin -> oauthLogin.loginPage(OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/open-id-connect-client")
                                                     .permitAll()
                       .userInfoEndpoint(userInfoEndpointConfig -> userInfoEndpointConfig
                            .oidcUserService(this.oidcUserService()))
                )
                .build();
    }


    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService(){
        final OidcUserService delegate = new OidcUserService();

        return (userRequest) -> {
            OidcUser oidcUser = delegate.loadUser(userRequest);
            SecurityContextHolder.getContext().setAuthentication(userAuthenticationProvider.test(oidcUser));

            oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());

            return oidcUser;
        };


    }
}

Solution

  • The old application used the SessionCreationPolicy.STATELESS, when I changed it to SessionCreationPolicy.IF_REQUIRED the user was saved in the session