spring oauth spring-security oauth-2.0 cors

spring - Permitir OPCIONES Método HTTP para solicitud de oauth/token



spring-security oauth-2.0 (3)

Estoy tratando de habilitar la obtención de tokens oauth2 para mi aplicación angular. Mi configuración funciona bien (la autenticación funciona correctamente para todas las solicitudes, la recuperación de tokens también funciona bien), pero hay un problema.

Las solicitudes CORS requieren que antes de GET se envíe una solicitud de OPCIONES al servidor. Para empeorar las cosas, esa solicitud no contiene encabezados de autenticación. Me gustaría que esta solicitud siempre vuelva con el estado 200 sin ninguna autenticación realizada en el servidor. ¿Es posible? Tal vez me estoy perdiendo algo

mi configuración de seguridad de primavera:

@Configuration @EnableWebSecurity @EnableAuthorizationServer public class SecurityConfig extends WebSecurityConfigurerAdapter { private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class); @Inject private UserService userService; @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean public DefaultTokenServices tokenServices() { DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); defaultTokenServices.setTokenStore(tokenStore()); return defaultTokenServices; } @Bean public WebResponseExceptionTranslator webResponseExceptionTranslator() { return new DefaultWebResponseExceptionTranslator() { @Override public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception { ResponseEntity<OAuth2Exception> responseEntity = super.translate(e); OAuth2Exception body = responseEntity.getBody(); HttpHeaders headers = new HttpHeaders(); headers.setAll(responseEntity.getHeaders().toSingleValueMap()); headers.set("Access-Control-Allow-Origin", "*"); headers.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT"); headers.set("Access-Control-Max-Age", "3600"); headers.set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); return new ResponseEntity<>(body, headers, responseEntity.getStatusCode()); } }; } @Bean public AuthorizationServerConfigurer authorizationServerConfigurer() { return new AuthorizationServerConfigurer() { @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); oAuth2AuthenticationEntryPoint.setExceptionTranslator(webResponseExceptionTranslator()); security.authenticationEntryPoint(oAuth2AuthenticationEntryPoint); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("secret-client") .secret("secret") .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") .authorities("ROLE_LOGIN") .scopes("read", "write", "trust") .accessTokenValiditySeconds(60 * 60 * 12); // 12 hours } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenServices(tokenServices()); endpoints.authenticationManager(authenticationManager()); } }; } @Override protected AuthenticationManager authenticationManager() throws Exception { return new AuthenticationManager() { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { log.warn("FIX ME: REMOVE AFTER DEBUG!!!!!!!!!!!!"); log.debug("authenticate: " + authentication.getPrincipal() + ":" + authentication.getCredentials()); final Collection<GrantedAuthority> authorities = new ArrayList<>(); WomarUser user = userService.findUser(authentication.getPrincipal().toString(), authentication.getCredentials().toString()); for (UserRole userRole : user.getRoles()) { authorities.add(new SimpleGrantedAuthority(userRole.getName())); } return new UsernamePasswordAuthenticationToken(user.getLogin(), user.getPassword(), authorities); } }; } @Bean public OAuth2AuthenticationManager auth2AuthenticationManager() { OAuth2AuthenticationManager oAuth2AuthenticationManager = new OAuth2AuthenticationManager(); oAuth2AuthenticationManager.setTokenServices(tokenServices()); return oAuth2AuthenticationManager; } @Bean public OAuth2AuthenticationProcessingFilter auth2AuthenticationProcessingFilter() throws Exception { OAuth2AuthenticationProcessingFilter oAuth2AuthenticationProcessingFilter = new OAuth2AuthenticationProcessingFilter(); oAuth2AuthenticationProcessingFilter.setAuthenticationManager(auth2AuthenticationManager()); return oAuth2AuthenticationProcessingFilter; } @Override protected void configure(HttpSecurity http) throws Exception { OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); oAuth2AuthenticationEntryPoint.setRealmName("realmName"); oAuth2AuthenticationEntryPoint.setTypeName("Basic"); oAuth2AuthenticationEntryPoint.setExceptionTranslator(webResponseExceptionTranslator()); http .antMatcher("/**").httpBasic() .authenticationEntryPoint(oAuth2AuthenticationEntryPoint) .and().addFilterBefore(auth2AuthenticationProcessingFilter(), BasicAuthenticationFilter.class) .authorizeRequests() .antMatchers("/rest/womar/admin/**").hasRole("ADMIN") .antMatchers("/rest/womar/**").hasRole("USER"); }

}

solicitud angular:

var config = { params: { grant_type: ''password'', username: login, password: password }, headers: { Authorization: ''Basic '' + Base64.encode(''secret-client'' + '':'' + ''secret'') } }; $http.get("http://localhost:8080/oauth/token", config) .success(function(data, status) { $log.log(''success''); $log.log(data); $log.log(status); }) .error(function(data, status) { $log.log(''error''); $log.log(data); $log.log(status); });



Solo agrego

@Order (Ordered.HIGHEST_PRECEDENCE)

en

La clase pública OAuth2SecurityConfig amplía WebSecurityConfigurerAdapter {....}

y configurar el soporte de la primavera

@Frijol
public CorsConfigurationSource corsConfigurationSource () {
Configuración de CorsConfiguration = new CorsConfiguration ();
configuration.setAllowedOrigins (Arrays.asList (" "));
configuration.setAllowedMethods (Arrays.asList (" "));
configuration.setAllowedHeaders (Arrays.asList ("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource ();
source.registerCorsConfiguration ("/ **", configuración);
fuente de retorno;
}

Trabajó para mi.


@EnableAuthorizationServer está agregando la configuración de seguridad http para puntos finales como /oauth/token , /oauth/token_key etc. al orden 0. Entonces, lo que debe hacer es definir una regla de seguridad http para /oauth/token endpoint solo para el método OPTIONS http que es en un orden superior

Algo como esto:

@Order(-1) public class MyWebSecurity extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll() } }