简体   繁体   中英

OAuth2 SSO with Spring Boot without the authorization screen

I have resource, authorization and _ui applications written using Spring Boot 1.5.3, OAuth2 and MongoDB.

The resources are going to be accessed from mobile apps as well as a couple of web applications (one for regular users and the other one for admins). The apps are quite similar to the samples from the guides by Dave Syer. What different is that the users are stored in the database and the clients are stored in an xml file located in the resources folder of the authorization server.

I am struggling with the logon experience for the web users. Following the guides for the JWT based OAuth app, after the login page, the user is redirected to the authorization screen, which is not the desired behavior. Ie, I don't want my authorization server to ask if the user trusts my web application to access its resources . Instead, I want users redirected to the ui pages right after login, as one would expect.

I found this project on GitHub (very similar to the apps from the guide) which behaves exactly as I want, but once I start customizing it by adding my authentication and authorization implementation, it reverts back to using the authorization screen. Apparently, I am missing something, but I was not able to figure out what exactly.

authorization/src/main/resourcs/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/resourcs/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);
    }

}

authorization/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);
    }
}

From http://www.springframework.org/schema/security/spring-security-oauth2.xsd Element client-details-service > complexType client > attribute autoaprove

Scopes or scope patterns that are autoapproved (comma-separated), or just "true" to autoapprove all.

Just add the autoapprove="true" attribute to your trusted-app in client-details.xml . That way the authserver will not request user's confirmation to access the resources.

Here is an example of how to implement this behaviour directly in your Java configuration.

Additionally, if your clients are provided by a database, actually DataSource , then the AUTOAPPROVE column of related client should be set to 'true' in the table OAUTH_CLIENT_DETAILS .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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