Spring OAuth2 - / oauth / authorize - ошибка аутентификации пользователя - PullRequest
1 голос
/ 28 мая 2019

Я пытаюсь защитить мои остальные API с помощью потока authorization_code. У меня есть сервер ресурсов и отдельный сервер авторизации. Я использую конечную точку oauth / token сервера авторизации для генерации токена пользователя и использую этот токен для доступа к серверу ресурсов, который внутренне вызывает конечную точку / oauth / authorize сервера авторизации. Но когда вызывается конечная точка авторизации, выдается ошибка

org.springframework.security.authentication.InsufficientAuthenticationException: пользователь должен пройти аутентификацию в Spring Security, прежде чем авторизация может быть завершена.

Ниже приведены конфигурации

Сервер авторизации

WebSecurity

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin().disable()//
            .csrf().disable() //
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //
            .and().exceptionHandling() //
                .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)) //
            .and().requestMatchers().antMatchers("/login") //
            .and().authorizeRequests()
                .antMatchers("/login").permitAll() //
                .anyRequest().authenticated();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    @Bean
    public AuthenticationKeyGenerator authenticationKeyGenerator() {
        return new DefaultAuthenticationKeyGenerator();
    }

    @Bean
    public ClientKeyGenerator clientKeyGenerator() {
        return new DefaultClientKeyGenerator();
    }

}

AuthorizationServer

@Configuration
@EnableAuthorizationServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private MyTokenStore myTokenStore;

    @Autowired
    private MyClientDetailsService myClientDetailsService;

    @Autowired
    private MyApprovalStore myApprovalStore;

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(myClientDetailsService);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter()));
        endpoints.tokenStore(myTokenStore) //
                .tokenEnhancer(tokenEnhancerChain) //
                .approvalStore(myApprovalStore) //
                .authenticationManager(authenticationManager);
    }

    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new MyTokenEnhancer();
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "123456".toCharArray());
        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("123456"));
        return converter;
    }

    @Configuration
    protected static class GlobalAuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter {

        @Autowired
        private UserDetailsService userDetailsService;

        @Autowired
        private PasswordEncoder passwordEncoder;

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
        }

    }
}

ResourceServer

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Autowired
    private MyTokenStore myTokenStore;

    @Override
    public void configure(ResourceServerSecurityConfigurer config) {
        config.tokenServices(tokenServices());
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable() //
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //
                .and().authorizeRequests() //
                .antMatchers("/login").permitAll() //
                .anyRequest().authenticated();
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        Resource resource = new ClassPathResource("public.cert");
        String publicKey = null;
        try {
            publicKey = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8);
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
        converter.setVerifierKey(publicKey);
        return converter;
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenEnhancer(accessTokenConverter());
        defaultTokenServices.setTokenStore(myTokenStore);
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }

}

Сервер ресурсов (клиент)

WebSecurity

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**").authorizeRequests() //
                .antMatchers("/", "/login**").permitAll() //
                .anyRequest().authenticated() //
                .and().oauth2Login();
    }

}

application.yml

spring:
  security:
    oauth2:
      client:
        registration:
          custom-auth:
            client-name: custom-auth
            client-id: org1
            client-secret: 123456
            scope: openid
            provider: custom-auth
            redirect-uri: http://localhost:8080/login/oauth2/code/
            authorization-grant-type: authorization_code
        provider:
          custom-auth:
            token-uri: http://localhost:8180/oauth/token
            authorization-uri: http://localhost:8180/oauth/authorize
            user-info-uri: http://localhost:8180/user/me

Я видел запрос oauth / authorize, отправленный на сервер авторизации, и токен-носитель включен в запрос.

Это полностью основанный на API интерфейс, и у меня нет страниц.

Отредактировано

Я искал внутри пружины и вижу, что FilterChainProxy вызывается для ресурсов, которые внутренне вызывают OAuth2AuthenticationProcessingFilter, и объект Authentication устанавливается в RequestContext. Но для / oauth / authorize я не вижу, как вызывается FilterChainProxy, есть ли возможность заставить FilterChainProxy работать на /oauth/authorize.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...