I am new to spring boot. I have implemented Spring Security with oAuth2 and get acesstoken successfully from spring Security. But when I try to request with token with "Authorization" header..
config.headers["Authorization"] = 'Bearer 0d634d2b-3900-4ca4-a462-cf729e8d0c72';
and my CORS filter is as :
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#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, PUT,DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
if (request.getMethod()!="OPTIONS") {
chain.doFilter(req, res);
} else {
}
}
#Override
public void destroy() {
}
}
But still it given CORS issue.
Please help me where I am wrong.
Problem solve. I have send token as wrong way
config.headers["Authorization"] = 'Bearer 0d634d2b-3900-4ca4-a462-cf729e8d0c72';
right way is:
config.headers.authorization = 'Bearer 0d634d2b-3900-4ca4-a462-cf729e8d0c72';
Try to set your Access-Control-Allow-Headers like this:
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Content-Type");
Related
Spring boot 2.4.3
If the user has no permission for action, it gives 403 response but without any response body. However the header WWW-Authenticate is set:
WWW-Authenticate: Bearer error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token."
I would like still to have some response body with message. How could I achieve it?
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.formLogin(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.authorizeRequests(authorize -> authorize
.mvcMatchers(HttpMethod.GET, "/app/**", "/admin/**").authenticated()
.mvcMatchers(HttpMethod.PUT, "/app/**", "/admin/**").authenticated()
.mvcMatchers(HttpMethod.POST, "/app/**", "/admin/**").authenticated()
)
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(jwtAuthenticationConverter());
}
I had the same problem and found the following solution:
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException e) throws IOException, ServletException {
e.getCause().printStackTrace();
response.setStatus(...);
response.setContentType(...);
response.getWriter().write("your custom error response");
}
}
Then in your security config:
http.
//...
.oauth2ResourceServer()
.authenticationEntryPoint(new CustomAuthenticationEntryPoint())
I'm using Spring Security JWT to secure Angular login page.
I configure Spring CORS filter to accept http CORS request.
I verify the JWT is valid in return and authenticated with correct roles.
The secure routes such as hasRole, hasAuthority fail on CORS requests, it always return 403 status.
//http config
protected void configure(HttpSecurity http) throws Exception{
http.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/list_customers").hasAnyRole("ADMIN","DEV") //FAIL 403 error
.antMatchers(HttpMethod.GET, "/api/list_customers").hasAuthority("ROLE_ADMIN") //FAIL 403 error
.anyRequest().authenticated()
}
//CORS filter
public class CORSFilter extends GenericFilterBean implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletResponse httpResp = (HttpServletResponse) response;
httpResp.setHeader("Access-Control-Allow-Origin", "*");
httpResp.setHeader("Access-Control-Allow-Methods", "*");
httpResp.setHeader("Access-Control-Allow-Headers", "*");
httpResp.setHeader("Access-Control-Allow-Credentials", "true");
httpResp.setHeader("Access-Control-Max-Age", "3600");
chain.doFilter(request, response);
}
}
Delete your filter and replace it with
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*");
configuration.addAllowedMethod("*");
configuration.addAllowedHeader("*");
configuration.setAllowCredentials(true);
configuration.setMaxAge(3600l);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
Reference
Have a loot at org.springframework.web.filter.CorsFilter to see how it picks up CorsConfigurationSource bean and configures the cors filter
As you can see in the chain of filters, CorsFilter is earlier in the chain than filters checking if the user is authenticated or if they have right permission. Your 403 is thrown much earlier by the CorsFilter as it is not configured correctly
Issue Resolved.
I found out my production role name is different.
I changed the role name from ADMIN to ROLE_ADMIN, then it works fine.
I've allowed cors in my grails 3 application through :
cors:
enabled: true
and added the filter :
public CorsFilter() { }
#Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
throws ServletException, IOException {
String origin = req.getHeader("Origin");
boolean options = "OPTIONS".equals(req.getMethod());
if (options) {
if (origin == null) return;
resp.addHeader("Access-Control-Allow-Headers", "origin, authorization, accept, content-type, x-requested-with");
resp.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
resp.addHeader("Access-Control-Max-Age", "3600");
}
resp.addHeader("Access-Control-Allow-Origin", origin == null ? "*" : origin);
resp.addHeader("Access-Control-Allow-Credentials", "true");
if (!options) chain.doFilter(req, resp);
}
The problem is the request is responding correctly,
but if the request has a header 'Origin', the request returns 403
even though the response header is :
Access-Control-Allow-Credentials →true
Access-Control-Allow-Origin →http://localhost:4200
Cache-Control →no-store, no-cache, must-revalidate, max-age=0
Content-Length →0
Date →Sat, 25 Feb 2017 19:44:21 GMT
X-Application-Context →application:development
Any idea how to solve this ?
Thanks
The issue was with websocket, since my error was happening with the url containing /stomp/info
The solution was to add the following class
#Configuration
#EnableWebSocketMessageBroker
class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
void configureMessageBroker(MessageBrokerRegistry messageBrokerRegistry) {
messageBrokerRegistry.enableSimpleBroker "/queue", "/hmi"
messageBrokerRegistry.setApplicationDestinationPrefixes "/app"
}
#Override
void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/stomp","/hmi","/hmi/status").setAllowedOrigins("*").withSockJS()
}
#Bean
GrailsSimpAnnotationMethodMessageHandler grailsSimpAnnotationMethodMessageHandler(
MessageChannel clientInboundChannel,
MessageChannel clientOutboundChannel,
SimpMessagingTemplate brokerMessagingTemplate
) {
def handler = new GrailsSimpAnnotationMethodMessageHandler(clientInboundChannel, clientOutboundChannel, brokerMessagingTemplate)
handler.destinationPrefixes = ["/app"]
return handler
}
}
and then add it to resources.groovy
beans = {
websocketConfig WebSocketConfig
}
I am using Spring Security and Spring Oauth2 and JWT in my API project
The default API in order to login which Spring oauth 2 provided, is /oauth/token
This API always adds "Strict-Transport-Security: max-age=31536000 ; includeSubDomains" header to the response.
But I don't want this in my situation. And I have removed HSTS with the below source code.
#EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers()
.httpStrictTransportSecurity().disable();
}
}
With above code, APIs I defined is removed HSTS in header. But the default API /oauth/token still return HSTS in header.
Is there any way to do this ?
Please help.
Thanks,
Tin
I just ran into the same issue.
The best solution I found is writing a filter that prevents others from setting the HSTS header in general.
#Component
#Order(value = Ordered.HIGHEST_PRECEDENCE)
public class HstsHeaderPreventionFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
public void setHeader(String name, String value) {
if (!name.equalsIgnoreCase("Strict-Transport-Security")) {
super.setHeader(name, value);
}
}
});
}
#Override
public void destroy() {
}
}
How do I enable URL rewriting in dropwizard? I need to rewrite all urls matching a certain pattern to /.
I'm using dropwizard 0.7.1 and I'm trying to run an Angular.js app in html5 mode in the front-end and this requires url rewriting (see https://docs.angularjs.org/guide/$location under the Server side section).
you can try with this: http://www.tuckey.org/urlrewrite/
it's very symilar to mod_rewrite.
You could add a Filter like this:
environment.getApplicationContext().addFilter(
new FilterHolder(new Filter() {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (shouldRedirect(request.getRequestURI())) {
response.sendRedirect("/");
} else {
chain.doFilter(req, res);
}
}
#Override
public void destroy() {}
}), "/*", EnumSet.allOf(DispatcherType.class));
For simple rules it seems to me that the best option is to use the Dropwizard PathRedirect RedirectBundle.
Add dropwizard-redirect-bundle to your dependencies
Register the bundle:
#Override
public void initialize(Bootstrap<?> bootstrap) {
bootstrap.addBundle(new RedirectBundle(
new PathRedirect("/old", "/new")
));
}
It supports regular expressions as well.
Just a note that for this to work with other bundles, such as static assets and HTTPS redirect, order matters. It should be:
AssetsBundle first
HttpsRedirect second
PathRedirect last