5

Sto lavorando a un'app di Spring Boot di esempio che utilizza OAuth2. Il problema è che il client ospitato su localhost:8080 chiama lo https://localhost:8443/oauth/authorize per autorizzarsi (tipo di sovvenzione implicita) ma dal momento che lo /oauth/authorize richiede che l'utente venga autenticato, viene reindirizzato alla pagina di accesso allo https://localhost:8443/login.Spring OAuth2 non reindirizzamento al client all'accesso modulo

Questo è tutto previsto, ma quando l'utente atterra sulla pagina di accesso mancano tutte le stringhe di query tra cui redirect_uri. L'utente accede e viene reindirizzato su https://localhost:8443 anziché sul redirect_uri specificato di http://localhost:8080.

C'è un modo per reindirizzare l'utente al client dopo aver effettuato l'accesso con il modulo di login del server? Mi sto perdendo qualcosa nella mia configurazione? Posso postare di più se necessario.

La richiesta autorizzano assomiglia: https://localhost:8443/oauth/authorize?response_type=token&state=6c2bb162-0f26-4caa-abbe-b65f7e5c6a2e&redirect_uri=http%3A%2F%2Flocalhost%3A8080&client_id=admin

SecurityConfig:

@Configuration 
public static class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    private final Logger log = LoggerFactory.getLogger(WebSecurityConfig.class);       

    @Override 
    public void configure(WebSecurity web) throws Exception { 

     web.ignoring().antMatchers("/resources/**"); 
    }  

    @SuppressWarnings("deprecation") 
    @Override 
    protected void configure(HttpSecurity http) throws Exception {     

     http 
      .requestMatchers() 
       .antMatchers("/**") 
     .and() 
      .addFilterAfter(new CsrfCookieGeneratorFilter(), CsrfFilter.class) 
      .exceptionHandling() 
       .accessDeniedPage("/login?authorization_error=true") 
     .and() 
      .authorizeRequests() 
      .antMatchers("/resources/**", "/csrf").permitAll() 
      .anyRequest().authenticated() 
     .and() 
      .formLogin() 
       .loginPage("/login") 
       .usernameParameter("j_username") 
       .passwordParameter("j_password") 
       .defaultSuccessUrl("/", false) 
       .failureUrl("/login?authentication_error=true") 
       .permitAll() 
     .and() 
      .logout() 
       .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) 
       .logoutSuccessUrl("/login") 
       .invalidateHttpSession(true) 
       .deleteCookies("JSESSIONID", "CSRF-TOKEN") 
       .permitAll() 
     .and() 
      .headers() 
       .frameOptions() 
       .disable(); 
    } 

OAuthConfig:

@Configuration 
@EnableAuthorizationServer 
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { 

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

    @Bean 
    public TokenStore tokenStore() { 

     return new InMemoryTokenStore(); 
    } 

    @Primary 
    @Bean 
    public ResourceServerTokenServices tokenServices() { 

     DefaultTokenServices tokenServices = new DefaultTokenServices(); 
     tokenServices.setSupportRefreshToken(true); 
     tokenServices.setTokenStore(tokenStore()); 

     return tokenServices; 
    }   

    @Bean 
    public ApprovalStore approvalStore() throws Exception { 

     TokenApprovalStore approvalStore = new TokenApprovalStore(); 
     approvalStore.setTokenStore(tokenStore()); 

     return approvalStore; 
    } 

    @Override 
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 

     clients 
      .inMemory() 
       .withClient("read-only") 
        .secret("readme") 
        .resourceIds(RESOURCE_ID) 
        .authorizedGrantTypes("implicit", "password", "refresh_token")       
        .authorities(Constant.USER) 
        .scopes("read") 
        .autoApprove(true) 
        .redirectUris("https://localhost:8443") 
       .and() 
       .withClient("admin") 
        .secret("admin") 
        .resourceIds(RESOURCE_ID) 
        .authorizedGrantTypes("implicit", "password", "refresh_token") 
        .authorities(Constant.USER, Constant.ADMIN) 
        .scopes("read", "write") 
        .autoApprove(true) 
        .redirectUris("https://localhost:8443", "http://localhost:8080") 
       .and() 
       .withClient("super-admin") 
        .secret("super") 
        .resourceIds(RESOURCE_ID) 
        .authorizedGrantTypes("implicit", "password", "refresh_token") 
        .authorities(Constant.USER, Constant.ADMIN) 
        .scopes("read", "write", "delete") 
        .redirectUris("https://localhost:8443"); 
    } 

    @Override 
    public void configure(AuthorizationServerEndpointsConfigurer configurer) throws Exception { 

     configurer 
      .tokenStore(tokenStore()) 
      .authenticationManager(authenticationManager); 
    }   

    @Override 
    public void configure(AuthorizationServerSecurityConfigurer security) 
      throws Exception { 

     security.realm("hubble/client"); 
    } 

} 

@Configuration 
@EnableResourceServer 
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {   

    @Override 
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 

     resources.resourceId(RESOURCE_ID); 
    } 

    @Override 
    public void configure(HttpSecurity http) throws Exception { 

     http 
      .requestMatchers() 
       .antMatchers("/api/**") 
     .and() 
      .authorizeRequests() 
       .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() 
       .antMatchers(HttpMethod.GET, "/api/**").access("#oauth2.hasScope('read')") 
       .antMatchers(HttpMethod.POST, "/api/**").access("#oauth2.hasScope('write')") 
       .antMatchers(HttpMethod.PATCH, "/api/**").access("#oauth2.hasScope('write')") 
       .antMatchers(HttpMethod.PUT, "/api/**").access("#oauth2.hasScope('write')") 
       .antMatchers(HttpMethod.DELETE, "/api/**").access("#oauth2.hasScope('delete')") 
       .antMatchers("/api/**").access("hasRole('" + Constant.USER + "')")     
     .and() 
      .anonymous().authorities(Constant.ANONYMOUS) 
     .and() 
      .sessionManagement() 
       .sessionCreationPolicy(SessionCreationPolicy.STATELESS);       
    } 
} 

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) 
protected static class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {  

    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 

     OAuth2MethodSecurityExpressionHandler methodHandler = new OAuth2MethodSecurityExpressionHandler(); 

     return methodHandler; 
    } 
} 
+0

Funziona per me (non ho mai utilizzare il 'defaultSuccessUrl()', ma non vedo alcun problema evidente con questo) . Puoi pubblicare un link a un progetto completo? –

+0

Grazie @DaveSyer per dare un'occhiata! Ho provato defaultSuccessUrl() nella speranza che avrebbe risolto il mio problema, ma nessun dado con o senza. Funziona se proteggi/oauth/** con l'autenticazione di base piuttosto che un accesso al modulo. Cercherò di portare il progetto su Github domani e di fornire un collegamento. –

+3

Ciao, qualsiasi successo con questo? Ho lo stesso problema. – pborbas

risposta

0

il problema si verifica con l'autenticazione modulo solo e non è collegato a OAuth. org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint ha un metodo buildRedirectUrlToLoginPage che crea l'URL di accesso e dimentica le stringhe di query.

Attualmente lo abbiamo risolto con una soluzione alternativa.

  1. invece di reindirizzare l'utente all'URL di autorizzazione, reindirizziamo direttamente alla pagina di accesso.
  2. la pagina di accesso ha un controller che controlla se l'utente era già loggato e, in tal caso, reindirizza all'URL di autorizzazione con redirect_uri se presente o l'URL di app predefinito come redirect_uri.
  3. da qui il redirect_uri viene gestito correttamente dall'URL di autorizzazione.

Un esempio LoginController dal punto 2. potrebbe essere la seguente:

@Controller 
@RequestMapping(value = {"/login"}) 
public class LoginController { 
    @RequestMapping(method = RequestMethod.GET) 
    public String getPage(HttpServletRequest request, HttpServletResponse response, Principal principal) 
      throws IOException { 
     if (principal != null) { //depends on your security config, maybe you want to check the security context instead if you allow anonym access 
      String redirect_uri = request.getParameter("redirect_uri"); 
      //here you must get all the other attributes thats needed for the authorize url 
      if (redirect_uri == null) { 
       redirect_uri = "https://your.default.app.url"; 
      }   
      return "redirect:https://localhost:8443/oauth/authorize?response_type=token&state=6c2bb162-0f26-4caa-abbe-b65f7e5c6a2e&client_id=admin&redirect_uri=" + URLEncoder.encode(redirect_uri, "UTF-8"); 
     } 
     return "login"; 
    } 
} 
Problemi correlati