Spring Oauth2 隐式流

Posted

技术标签:

【中文标题】Spring Oauth2 隐式流【英文标题】:Spring Oauth2 implicit flow 【发布时间】:2016-02-23 04:46:39 【问题描述】:

致力于使用 Spring 实现 Oauth2。我想实现隐式工作流:

我的配置文件:

@Configuration
@EnableAutoConfiguration
@RestController
public class App 

    @Autowired
    private DataSource dataSource;

    public static void main(String[] args) 
        SpringApplication.run(App.class, args);
    

    @RequestMapping("/")
    public String home() 
        return "Hello World";
    

    @Configuration
    @EnableResourceServer
    protected static class ResourceServer extends ResourceServerConfigurerAdapter 

        @Autowired
        private TokenStore tokenStore;

        @Override
        public void configure(ResourceServerSecurityConfigurer resources)
                throws Exception 
            resources.tokenStore(tokenStore);
        

        @Override
        public void configure(HttpSecurity http) throws Exception 
            // @formatter:off
        http.authorizeRequests().antMatchers("/oauth/token").authenticated()
                .and()
                .authorizeRequests().anyRequest().permitAll()
                .and()
                .formLogin().loginPage("/login").permitAll()
                .and()
                .csrf().disable();
        

    

    @Configuration
    @EnableAuthorizationServer
    protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter 

        @Autowired
        private AuthenticationManager auth;

        private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        @Bean
        public JdbcTokenStore tokenStore() 
            return new JdbcTokenStore(DBConnector.dataSource);
        

        @Bean
        protected AuthorizationCodeServices authorizationCodeServices() 
            return new JdbcAuthorizationCodeServices(DBConnector.dataSource);
        

        @Override
        public void configure(AuthorizationServerSecurityConfigurer security)
                throws Exception 
            security.passwordEncoder(passwordEncoder);
        

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                throws Exception 
            endpoints.authorizationCodeServices(authorizationCodeServices())
                    .authenticationManager(auth).tokenStore(tokenStore())
                    .approvalStoreDisabled();            
        

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
            // @formatter:off
            clients.jdbc(DBConnector.dataSource)
                    .passwordEncoder(passwordEncoder)
                    .withClient("my-trusted-client")
                    .secret("test")
                    .authorizedGrantTypes("password", "authorization_code",
                            "refresh_token", "implicit")
                    .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
                    .scopes("read", "write", "trust")
                    .resourceIds("oauth2-resource")
                    .accessTokenValiditySeconds(0);

            // @formatter:on
        

    

    @Autowired
    public void init(AuthenticationManagerBuilder auth) throws Exception 
        // @formatter:off 
        auth.jdbcAuthentication().dataSource(DBConnector.dataSource).withUser("dave")
                .password("secret").roles("USER");

        // @formatter:on
    


到目前为止,这是有效的。数据库中也会生成一个用户。

问题如下。当我尝试执行以下请求时:

http://localhost:8080/oauth/token?grant_type=authorization_code&client_id=my-trusted-client&username=dave&password=secret

我总是收到一个弹出窗口(身份验证),要求我输入用户名和密码。但是我进入那里并不重要,我永远不会通过。那么那里有什么问题呢?

我想要它,当我调用这个 url 时,我可以取回我的 access_token。

【问题讨论】:

【参考方案1】:

在隐式流的情况下,所有令牌都将通过授权 url 而不是令牌 url 生成。所以你应该用隐式响应类型点击 ../oauth/authorize 端点。即

../oauth/authorize?response_type=implicit&client_id=trusted_client&redirect_uri=<redirect-uri-of-client-application>.

您将收到用户名密码弹出窗口,因为令牌端点已通过 spring 的 BasicAuthenticationFilter 保护,并且它希望您将 client_id 作为用户名和 client_secret 作为密码传递。您需要保护授权端点,而不是令牌端点,因此您的端点安全配置也要按照给定...

 @Override
        public void configure(HttpSecurity http) throws Exception 
            // @formatter:off
        http.authorizeRequests().antMatchers("/oauth/authorize").authenticated()
                .and()
                .authorizeRequests().anyRequest().permitAll()
                .and()
                .formLogin().loginPage("/login").permitAll()
                .and()
                .csrf().disable();
        

【讨论】:

为什么要禁用跨站请求伪造? 隐式授权流response_type 值必须设置token 见this 但是如何在没有基本身份验证的情况下获取令牌? (即使我配置了 .permitAll() ),Spring 总是抱怨:访问被拒绝(用户是匿名的)并且不生成令牌 response_type=implicit 不存在。而是response_type=token

以上是关于Spring Oauth2 隐式流的主要内容,如果未能解决你的问题,请参考以下文章

如何保护来自iframe的Oauth2隐式流

Azure api OAuth2 隐式流适用于 http 但不适用于 htt

是否可以仅请求用户已在 Azure AD OAuth2 隐式流中同意的范围的子集?

OAuth2 隐式流程 - IFrame 刷新身份

创建隐式JWT时的Spring Boot OAuth2?

使用 Spring Security 实现 OAuth2 隐式授权