Spring boot OAuth2Client, user not authenticated after callback: SecurityContext is empty or contents are anonymous

Viewed 733

I'm configuring a Spring Boot application that will authenticate the user using OAuth2 and OpenID Connect. For the implementation, I follow the reference here: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2

After the AuthorizationCode is done, the user is not authenticated. How do I authenticate the user ?

The OpenID server I rely on requires an extra parameter for the authorization endpoint (acr_values={value}).

I'm able to add the parameter using an AuthorizationRequestResolver and call the authorization endpoint, then the server redirects me on my callback but the user is not authenticated. From the trace, the SecurityContext is empty and not save in the httpsession. I can see in the logs that the POST request to the token endpoint is sent and I get a response 200.

MySecurityConfig


test

package com.uta.security.edc.config;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient;
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import com.uta.security.edc.oauth2.MyAuthorizationRequestResolver;
import com.uta.security.edc.oauth2.MyTokenResponseConverter;

@Configuration
@EnableOAuth2Client
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/", "/connect/**", "/test/**", "/assets/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .oauth2Login()
                .loginPage("/connect/login")
                .authorizationEndpoint()
                    .baseUri("/connect/authorization")
                    .authorizationRequestResolver(this.authorizationRequestResolver())
                    .and()
                .redirectionEndpoint()
                    .baseUri("/connect/callback")
                    .and()
                .tokenEndpoint()
                    .accessTokenResponseClient(this.accessTokenResponseClient())
                    .and()
                .userInfoEndpoint()
                    .and()
                .defaultSuccessUrl("/")
                .failureUrl("/connect/loginFailure")
                .and()
            .oauth2Client();
    }

    @Bean 
    public MyAuthorizationRequestResolver authorizationRequestResolver()
    {
        return new MyAuthorizationRequestResolver(this.clientRegistrationRepository);
    }

    @Bean
    public OAuth2RestTemplate oauth2RestTemplate()
    {
        return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
    }

    @Bean
    protected OAuth2ProtectedResourceDetails resource() {
        ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId("my-connect");
        AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails();
        List<String> scopes = new ArrayList<String>(1);
        scopes.add("uta-poc-edc");
        resource.setAccessTokenUri(clientRegistration.getProviderDetails().getTokenUri());
        resource.setClientId(clientRegistration.getClientId());
        resource.setClientSecret(clientRegistration.getClientSecret());
        resource.setScope(scopes);
        return resource;
    }

    @Bean
    public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient()
    {        
        DefaultAuthorizationCodeTokenResponseClient accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient(); 

        OAuth2AccessTokenResponseHttpMessageConverter tokenResponseHttpMessageConverter = new OAuth2AccessTokenResponseHttpMessageConverter(); 
        tokenResponseHttpMessageConverter.setTokenResponseConverter(new MyTokenResponseConverter()); 

        RestTemplate restTemplate = this.oauth2RestTemplate();
        //RestTemplate restTemplate = new RestTemplate(Arrays.asList(new FormHttpMessageConverter(), tokenResponseHttpMessageConverter)); 
        restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); 
        accessTokenResponseClient.setRestOperations(restTemplate); 

        return accessTokenResponseClient;
    }

    /*@Bean
    public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository)
    {
        OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
                        .authorizationCode()
                        .refreshToken()
                        .build();

        DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }*/
}

and also MyClientApplication

package com.uta.security.edc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextListener;

@SpringBootApplication
public class myClientApplication extends SpringBootServletInitializer
{
    public static void main(String[] args) 
    {
        SpringApplication.run(myClientApplication.class, args);
    }

    @Bean
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    }
}

I need the user to be authenticated and its authentication informations saved in its httpsession in order to request Resource servers.

Thank you for your help!

0 Answers
Related