origins invalid example application allow all spring-security cors jwt spring-security-oauth2

spring-security - invalid - spring boot cors allow all origins



Servidor de autorizaciĆ³n independiente de Spring OAuth2 JWT+CORS (5)

¡Encontré la razón de mi problema!

¡Solo necesitaba terminar la cadena de filtros y devolver el resultado inmediatamente si CorsFilter procesa una solicitud de OPCIONES!

SimpleCorsFilter.java

@Component @Order(Ordered.HIGHEST_PRECEDENCE) public class SimpleCorsFilter implements Filter { public SimpleCorsFilter() { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization"); if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } @Override public void init(FilterConfig filterConfig) { } @Override public void destroy() { } }

Después de eso, podría ignorar la solicitud de verificación previa de OPTIONS en mi AuthServer = D

Por lo tanto, el servidor funciona como en el recorte anterior y puede ignorar el comentario de bloque con la clase MyWebSecurity al principio.

Así que tengo el siguiente Servidor de Autorización condensado de este ejemplo de Dave Syer

@SpringBootApplication public class AuthserverApplication { public static void main(String[] args) { SpringApplication.run(AuthserverApplication.class, args); } /* added later @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) protected static class MyWebSecurity extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http //.csrf().disable() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll(); } }*/ @Configuration @EnableAuthorizationServer protected static class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); KeyPair keyPair = new KeyStoreKeyFactory( new ClassPathResource("keystore.jks"), "foobar".toCharArray()) .getKeyPair("test"); converter.setKeyPair(keyPair); return converter; } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("acme") //.secret("acmesecret") .authorizedGrantTypes(//"authorization_code", "refresh_token", "password").scopes("openid"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager).accessTokenConverter( jwtAccessTokenConverter()); } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess( "isAuthenticated()"); } } }

cuando lo ejecuto y lo pruebo con curl

curl acme@localhost:8110/oauth/token -d grant_type=password -d client_id=acme -d username=user -d password=password

Recibo un JWT como respuesta, pero tan pronto como intento acceder al AuthServer desde mi Frontend (Angular JS en un puerto diferente) recibo un error CORS. No porque faltan encabezados, sino porque la solicitud de OPCIÓN es rechazada y faltan las credenciales.

Request URL:http://localhost:8110/oauth/token Request Method:OPTIONS Status Code:401 Unauthorized WWW-Authenticate:Bearer realm="oauth", error="unauthorized", error_description="Full authentication is required to access this resource"

Ya sabía que tenía que agregar un CorsFilter y además encontré esta publicación donde utilicé el fragmento para la primera Respuesta para permitir que las OPCIONES soliciten acceso /oauth/token sin credenciales:

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

Después de eso obtuve con curl el siguiente error:

{"timestamp":1433370068120,"status":403,"error":"Forbidden","message":"Expected CSRF token not found. Has your session expired?","path":"/oauth/token"}

Entonces, para simplificar, acabo de agregar http.csrf().disable() al método de configure de la clase MyWebSecurity, que resuelve el problema con la solicitud OPTION, pero por lo tanto la solicitud POST ya no funciona y obtengo There is no client authentication. Try adding an appropriate authentication filter. There is no client authentication. Try adding an appropriate authentication filter. (también con rizo).

Traté de averiguar si tengo que conectar de alguna manera la clase MyWebSecurity y el AuthServer, pero sin suerte. El ejemplo original (enlace al principio) también inyecta el Administrador de autenticación, pero esto no cambió nada para mí.


Encontré un problema similar usando siguiente

  • Backend Spring Boot 1.5.8.RELEASE
  • Spring OAuth2 Spring OAuth 2.2.0.RELEASE w
  • Vuejs usando la biblioteca de solicitudes axios ajax

¡Con el postman todo funciona! Cuando comencé a hacer una solicitud desde la aplicación Vuejs , recibí los siguientes errores

OPCIONES http://localhost:8080/springboot/oauth/token 401 ()

y

XMLHttpRequest no puede cargar http://localhost:8080/springboot/oauth/token . La respuesta para la verificación previa tiene un código de estado HTTP no válido 401

Después de leer un poco, descubrí que puedo ordenar a mi Spring OAuth que ignore la solicitud de OPTIONS anulando la configure en mi clase de implementación WebSecurityConfigurerAdapter siguiente manera

@Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers(HttpMethod.OPTIONS); }

La adición de lo anterior ayudó pero luego, me encontré con el error específico de CORS

OPCIONES http://localhost:8080/springboot/oauth/token 403 ()

y

XMLHttpRequest no puede cargar http://localhost:8080/springboot/oauth/token . La respuesta a la solicitud de verificación previa no pasa la verificación de control de acceso: no hay encabezado ''Access-Control-Allow-Origin'' en el recurso solicitado. Por lo tanto, el origen '' http: // localhost: 8000 '' no tiene acceso permitido. La respuesta tenía el código de estado HTTP 403.

Y resolvió el problema anterior con la ayuda de un CorsConfig como se muestra a continuación

@Configuration public class CorsConfig { @Bean public FilterRegistrationBean corsFilterRegistrationBean() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.applyPermitDefaultValues(); config.setAllowCredentials(true); config.setAllowedOrigins(Arrays.asList("*")); config.setAllowedHeaders(Arrays.asList("*")); config.setAllowedMethods(Arrays.asList("*")); config.setExposedHeaders(Arrays.asList("content-length")); config.setMaxAge(3600L); source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); return bean; } }

Después de agregar la clase anterior, funciona como se esperaba. Antes de comenzar, investigaré las consequences de usar

web.ignoring().antMatchers(HttpMethod.OPTIONS);

así como las best practices para la configuración de Cors anterior. Por ahora * hace el trabajo pero definitivamente no es seguro para la producción.

La respuesta de Cyril me ayudó partially y luego me encontré con la idea de CorsConfig en este número de Github .


Encontré una solución usando la solución para la pregunta. Pero tengo otra forma de describir la solución:

@Configuration public class WebSecurityGlobalConfig extends WebSecurityConfigurerAdapter { .... @Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers(HttpMethod.OPTIONS); } ... }


Usando Spring Boot 2 aquí.

Tenía que hacer esto en mi AuthorizationServerConfigurerAdapter

@Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { Map<String, CorsConfiguration> corsConfigMap = new HashMap<>(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); //TODO: Make configurable config.setAllowedOrigins(Collections.singletonList("*")); config.setAllowedMethods(Collections.singletonList("*")); config.setAllowedHeaders(Collections.singletonList("*")); corsConfigMap.put("/oauth/token", config); endpoints.getFrameworkEndpointHandlerMapping() .setCorsConfigurations(corsConfigMap); //additional settings... }


bueno, tienes razon! esa es una solución, y también funcionó para mí (tuve el mismo problema)

Pero permítanme suscribir el uso de una implementación más inteligente del filtro CORS para Java: http://software.dzhuvinov.com/cors-filter.html

Esta es una solución muy completa para aplicaciones Java.

En realidad, puedes ver here cómo se resuelve tu punto.