简体   繁体   English

Spring Boot OAuth2具有基本身份验证和自定义UserDetailsS​​ervice

[英]Spring Boot OAuth2 with basic authentication and custom UserDetailsService

I'm trying to configure an OAuth2 server that will be capable to complete the basic OAuth2 flows (see here for examples). 我正在尝试配置能够完成基本OAuth2流程的OAuth2服务器(请参阅此处的示例)。

Apologies for the long question 为长期问题道歉

My first attempt is to be able to perform an authorization_code flow. 我的第一次尝试是能够执行authorization_code流程。

I have the following configuration: 我有以下配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig
        extends WebSecurityConfigurerAdapter {

    ....

        @Inject
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth
              .userDetailsService(userDetailsService)
              .passwordEncoder(passwordEncoder());
    }

...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin().loginPage("/login").permitAll()
                .and()
                .requestMatchers().antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
                .and()
                .authorizeRequests().anyRequest().authenticated();
    }

...

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

My Server configuration 我的服务器配置

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorServerConfig
        extends AuthorizationServerConfigurerAdapter {

    @Inject
    private TokenStore tokenStore;

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

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
            .tokenStore(tokenStore)
            .authenticationManager(authenticationManager);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
            .allowFormAuthenticationForClients()
            .checkTokenAccess("authenticated()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        .inMemory()
                .withClient("foo")
                .secret("foo")
                .authorizedGrantTypes("authorization_code","password", "refresh_token")
                .scopes(new String[] { "read", "write" })
    }

And indeed my authorization code flow works ok! 事实上我的授权代码流程正常! Problem start when I try to do a password flow as follows: 当我尝试执行密码流时,问题开始如下:

POST localhost:8200/oauth/token
Content-Type: application/x-www-form-urlencoded
Accept:application/json
Authorization:Basic Zm9vOmZvbw=="
username=admin&password=admin&grant_type=password&scope=read%20write&client_secret=foo&client_id=foo&

My problem is that the Authorization header is ignored, whether it is there or not the result is the same, it gives me back the access_token and refresh_token 我的问题是Authorization标头被忽略,无论结果是否相同,它都会返回access_token和refresh_token

If I try to enable the basic authentication as follows, enable ClientUserDetailsService, reading clients from database JDBC: 如果我尝试按如下方式启用基本身份验证,请启用ClientUserDetailsS​​ervice,从数据库JDBC中读取客户端:

public class SecurityConfig
        extends WebSecurityConfigurerAdapter {

    ....

@Bean
public ClientDetailsUserDetailsService   clientDetailsUserDetailsService(ClientDetailsService clientDetailsService){
    // JDBC clientDetailsService
    return new ClientDetailsUserDetailsService(clientDetailsService);
}


        @Inject
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth
              .userDetailsService(clientDetailsUserDetailsService());
    }

...

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    DaoAuthenticationProvider p = new DaoAuthenticationProvider();
    p.setUserDetailsService(userDetailsService);
    p.setPasswordEncoder(passwordEncoder());
    return new ProviderManager(Lists.newArrayList(p));
    //        return super.authenticationManagerBean();
    }

    }

Now what I have achieved is to have the basic authentication working properly BUT i loose the authorization_code flow since the basic authentication now it is done against the clientid and secret and NOT the user's actual credentials 现在我所取得的是让基本身份验证正常工作但是我放弃了authorization_code流程,因为基本身份验证现在是针对clientid和secret而不是用户的实际凭据完成的

Am I missing something? 我错过了什么吗? How can I have both flows? 我怎么能同时拥有这两种流量? Please help, I'm struggling for some days now. 请帮忙,我现在已经挣扎了好几天了。

Some Similar questions, but without any luck: 一些类似的问题,但没有任何运气:

I think this is because you've turned on form authentication for clients, you it's using that instead of the Basic header. 我认为这是因为您已经为客户启用了表单身份验证,您使用它而不是Basic头。

public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security
        .allowFormAuthenticationForClients()
        .checkTokenAccess("authenticated()");
}

Take out .allowFormAuthenticationForClients() . 取出.allowFormAuthenticationForClients()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM