带有 Spring Boot 的 OAuth2 SSO 没有授权屏幕

Posted

技术标签:

【中文标题】带有 Spring Boot 的 OAuth2 SSO 没有授权屏幕【英文标题】:OAuth2 SSO with Spring Boot without the authorization screen 【发布时间】:2017-12-21 12:50:29 【问题描述】:

我有使用 Spring Boot 1.5.3、OAuth2 和 MongoDB 编写的资源、授权和 _ui 应用程序。

将通过移动应用程序以及几个网络应用程序(一个用于普通用户,另一个用于管理员)访问这些资源。这些应用程序与 Dave Syer 指南中的 samples 非常相似。不同的是,用户存储在数据库中,客户端存储在授权服务器资源文件夹中的 xml 文件中。

我正在为网络用户的登录体验而苦苦挣扎。按照基于 JWT 的 OAuth 应用程序的指南,在登录页面之后,用户被重定向到授权屏幕,这不是所需的行为。即,我不希望我的授权服务器询问用户是否信任我的 Web 应用程序来访问其资源。相反,我希望用户在登录后立即重定向到 ui 页面,正如人们所期望的那样。

我发现this project on GitHub(与指南中的应用程序非常相似)的行为完全符合我的要求,但是一旦我通过添加身份验证和授权实现来自定义它,它就会恢复使用授权屏幕。显然,我遗漏了一些东西,但我无法弄清楚到底是什么。

authorization/src/main/resources/application.yml

security:
  oauth2:
    client:
      client-id: trusted-app
      client-secret: secret
      scope: read, write
      auto-approve-scopes: .*
  authorization:
      check-token-access: permitAll()
server:
  port: 9999
  context-path: /uaa
mongo:
  db:
    name: myappname

authorization/src/main/resources/client-details.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:oauth="http://www.springframework.org/schema/security/oauth2"

   xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/security/oauth2
                    http://www.springframework.org/schema/security/spring-security-oauth2.xsd">

<oauth:client-details-service id="client-details-service">

    <!-- Web Application clients -->
    <oauth:client
            client-id="trusted-app"
            secret="secret"
            authorized-grant-types="authorization_code, password,refresh_token"
            authorities="ROLE_WEB, ROLE_TRUSTED_CLIENT"
            access-token-validity="$oauth.token.access.expiresInSeconds"
            refresh-token-validity="$oauth.token.refresh.expiresInSeconds"/>
    </oauth:client-details-service>
</beans>

authorization/src/main/java/AuthorizationApplication.java

@SpringBootApplication
@RestController
public class AuthorizationApplication extends AuthorizationServerConfigurerAdapter 

    @RequestMapping("/user")
    @ResponseBody
    public Principal user(Principal user) 
        return user;
    

    @Configuration
    static class MvcConfig extends WebMvcConfigurerAdapter 
        @Override
        public void addViewControllers(ViewControllerRegistry registry) 
            registry.addViewController("login").setViewName("login");
            registry.addViewController("/").setViewName("index");
        
    

    @Configuration
    @Order(-20)
    static class LoginConfig extends WebSecurityConfigurerAdapter 
        @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();
        
    

    @Configuration
    @EnableAuthorizationServer
    @ImportResource("classpath*:client-details.xml")
    protected static class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter 

        @Autowired
        private AuthenticationManager authenticationManager;

        @Resource(name="client-details-service")
        private ClientDetailsService clientDetailsService;

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
            clients.withClientDetails(clientDetailsService);
        

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
            endpoints
                .authenticationManager(authenticationManager)
                .accessTokenConverter(jwtAccessTokenConverter());
        

        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() 
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            return converter;
        
    

    @Bean
    PasswordEncoder passwordEncoder()
        return new StandardPasswordEncoder();
    

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


授权/src/main/java/mypackage/UserService.java

@Service
public class UserService implements UserDetailsService 

    private UserAccountRepository userAccountRepository;

    @Autowired
    public UserService(UserAccountRepository userAccountRepository)
        this.userAccountRepository = userAccountRepository;
    

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException 

        UserAccount userAccount = userAccountRepository.findByEmail(s);

        if (userAccount != null) 
            return userAccount;
         else 
            throw new UsernameNotFoundException("could not find the user '" + s + "'");
        
   

ui/src/main/resources/application.yml

auth-server: http://localhost:9999/uaa
server:
  port: 8080
spring:
  aop:
    proxy-target-class: true
security:
  oauth2:
    client:
      clientId: trusted-app
      clientSecret: secret
      access-token-uri: $auth-server/oauth/token
      user-authorization-uri: $auth-server/oauth/authorize
      scope: read, write
    resource:
      token-info-uri: $auth-server/oauth/check_token

ui/src/main/java/UiApplication.java

@SpringBootApplication
@EnableOAuth2Sso
public class UiApplication extends WebSecurityConfigurerAdapter

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

    @Bean
    OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext, OAuth2ProtectedResourceDetails details) 
        return new OAuth2RestTemplate(details, oauth2ClientContext);
    

【问题讨论】:

【参考方案1】:

来自http://www.springframework.org/schema/security/spring-security-oauth2.xsd元素client-details-service> complexType client>属性autoaprove

自动批准(逗号分隔)的范围或范围模式,或 只需“true”即可自动批准所有内容。

只需将autoapprove="true" 属性添加到client-details.xml 中的受信任应用程序即可。这样authserver就不会请求用户确认访问资源。

Here 是如何在 Java 配置中直接实现此行为的示例。

【讨论】:

【参考方案2】:

另外,如果你的客户端是由数据库提供的,实际上是DataSource,那么在OAUTH_CLIENT_DETAILS表中相关客户端的AUTOAPPROVE列应该设置为'true'。

【讨论】:

以上是关于带有 Spring Boot 的 OAuth2 SSO 没有授权屏幕的主要内容,如果未能解决你的问题,请参考以下文章

带有加密 JWT 访问令牌的 Spring Boot OAuth2

带有 Spring Boot REST 应用程序的 OAuth2 - 无法使用令牌访问资源

带有 Google 的 OAuth2 - CORS 错误(Angular + Spring boot)[重复]

带有访问/刷新令牌的 Spring Boot OAuth2 SSO 未正确存储在数据库中

Spring Boot security/OAuth2 - 丢弃远程身份验证并在访问远程 userInfo 端点后恢复本地

带有jdbc令牌存储的spring boot oauth2给出oauth_access_token关系不存在