Redirect after successful CORS preflight fails with 401 (Spring Security) [closed] - spring-boot

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 19 hours ago.
Improve this question
I am using Spring Boot and I have CORS enabled in my Spring Security config (5.8.1) configuration:
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
We have setup a login success handler for our REST requests which redirects after succssful login
Authentication authentication) throws IOException {
String redirectUrl = applicationPropertyReader.getRedirectUrl() + "/tiles";
response.sendRedirect(redirectUrl);
}
Please see also my Dev Tools Network Screenshot below:
Chrome Network Screenshot
Request works fine:
https://myDomain.de
redirect to https://myDomain.de/tiles (OK - 200)
Request fails:
https://www.myDomain.de
redirect to https://myDomain.de/tiles (fails with 401)
in 2), after setting up CORS the preflight "OPTIONS" is returned OK (200) but the actual GET fails with HTTP 401.
While tackeling my general CORS preflight issue before, I think I read something about "the redirect is to fast" on stackoverflow. But now since preflight works, I do not find that question again :-(.
Your help is appreciated. Thanks!

Related

Spring Boot Custom Exception showing most peculiar Behavior

Note - I have already set the flag server.error.include-message=always in application.properties
I have made a custom exception which should give a message to client when raised. However, that does not seem to be working whenever error code is 401/403. In that case I only receive a 401/403 status code with no response body at all, like below.
As soon as I change the status code to anything else, I start getting proper response body, like this.
BadCredentialsException.java
#ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public class BadCredentialsException extends RuntimeException{
// Runtime exception just needs this, I guess :/
private static final long serialVersionUID = 1;
public BadCredentialsException(String message){
super(message);
}
}
See First antMatchers, that's where the concerned endpoint is.
SecurityConfiguration.java
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().
authorizeRequests().
antMatchers(HttpMethod.POST, "/api/v2/user/login/**").permitAll().
antMatchers(HttpMethod.POST, "/api/v2/user/", "/api/v2/user", "/api/v2/user/change-role/**").hasAuthority("ROOT").
antMatchers(HttpMethod.GET, "/api/v2/user/", "/api/v2/user").hasAuthority("ROOT").
antMatchers(HttpMethod.POST, "/api/v1/customers/", "/api/v1/customers").hasAnyAuthority("ADMIN", "ROOT").
antMatchers(HttpMethod.GET, "/api/v1/customers/", "/api/v1/customers").hasAnyAuthority("EMPLOYEE", "ADMIN", "ROOT").
anyRequest().
authenticated().
and().
httpBasic();
}
My Thoughts and Observations
-> I can see my message in the terminal, that means the exception is definitely being raised. I have also tried logging something out in the BadCredentialsException file to see if its being raised or not, and yes it seems to be working.
-> There is a possibility that spring security might be deleting the response body on such status codes, although that's only a wild guess. I am going to try and disable spring security for a bit and see if I receive proper response body or not.
UPDATE - I have modified the post so that only currently relevant questions are being shown.
I'm not sure if I understood your post correctly.
But anyways, I advice you to use CURL or other http testing tool such as SoapUi to test the authentication.
Because I guess Postman caches the Cookies returned by the request.
A correct authentication attempt returns the header "Set-Cookie: JSESSIONID=SESSION ID".
Postman sends that cookie in the next requests, thats why the authentication still works after you change the password.
Only if you change the username the cookie is not sent.
Using CURL or SoapUi will prevent that from happen.
Regarding the body being returned or not, I guess the only way to control the response body using spring security is customizing the BasicAuthenticationEntryPoint.

How to resolve the below CORS error I am getting with Vue JS app [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have an with front and in Vue and back end in spring boot, in the spring boot app I have a controller with 2 endpoints - /api/v1/user/login (POST) and /api/v1/user/get (GET). I have added the #CrossOrigin annotation on the controller. The idea is to make a request to the login endpoint retrieve the jwt token from the response, then call the get endpoint by passing the token in the 'Authorization' header. When I call the login endpoint it works fine and I get the token, however when I call the get endpoint I get a CORS error in chrome like below. I don't know why one endpoint works but the other throws the CORS error.
Access to XMLHttpRequest at 'http://localhost:8082/api/v1/user/get' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
I also observed a strange behavior when I checked the Network tab that two requests are going to the get endpoint, one with the 'Authorization' header and other without it. I am not sure why this is happening either.
You have to configure cors in your backend application.
With this configuration you should be able to connect with your backend. But you must configure CORS properly in your application.
Where has a '*' you must point to the address your frontend is being served.
Suppose you have your vuejs application running in http://localhost:3000
You must configure your cors to point to that address:
res.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");
In development you should point to the address your frontend is being served.
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class OriginsFilterConfiguration implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type");
chain.doFilter(request, response);
}
}
To know more about cors follow link.

Authorization headers not working with cors [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I've been facing this issue for several days now. I'm trying to make a call to my API (api.mywebsite.com) from my website (mywebsite.com), and it works fine until I try to pass the Authorization header. At that point, it's not a simple request anymore, but a preflighted request.
However, at the end the auth headers are not sent, and the input I get is this one:
This is my front end code (JS):
fetch(generalInfo.url.api+"users/"+userId, {
method: 'GET',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"Authorization": "Bearer "+accessToken
},
withCredentials: true
});
While this is a middleware in the API backend:
//Allow the cors from every domain
module.exports = function (req, res, next){
res.setHeader('Access-Control-Allow-Origin', req.host);
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Authorization');
if(req.method === 'OPTIONS'){
return res.send(200);
}
next();
}
Can anybody help me?
According to https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
In particular, a request is preflighted if any of the following conditions is true:
If, apart from the headers set automatically by the user agent (for example, Connection, User-Agent, or any of the other header with a name defined in the Fetch spec as a “forbidden header name”),
The forbidden headers include:
https://fetch.spec.whatwg.org/#forbidden-header-name
Which has Access-Control-Request-Headers which we can see is being sent with your request. This explains the use of a preflight.
I think the process looks ok - but in your response headers to the preflight i notice the access control allow origin is api.myapp.com whereas in the request if was on port 8888. I think in the response you should have the port number if it's not 80 for http. See https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy. An origin is the same if:
Two pages have the same origin if the protocol, port (if one is specified), and host are the same for both pages. You'll see this referred to as the "scheme/host/port tuple" at times (where a "tuple" is a set of three components that together comprise a whole).
So i think the issue might be that your preflight is saying to the client that only api.myapp.com is allowed but the actual request might be made to http://api.myapp.com:8888 so the origins don't match. Or have I misunderstood what you are trying to do?
You must remove "8888" port of your api url, the api server has to have already a port setted for api.myapp.com address

Spring SPNEGO without form

I have some questions about setting up SPNEGO without use of form fall back.
I am writing a web service that uses SPNEGO authentication and returns a signed JWT for the authenticated principal. I don't have any use for forms (can't use forms with authentication-only principals, for example).
Can I skip the formLogin() and logout() parts as shown in the spring SPNEGO reference, and use the zero-argument SpnegoEntryPoint constructor?
It seems from looking at the source for SPNEGO filter that if the Authorization header is missing then the filter doesn't actually return a 401 Unauthorized response with a WWW-Authenticate: Negotiate challenge to the caller. That is, there is no else to the check on line 135. Am I reading this correctly? The RFC states
If the server receives a request for an access-protected object, and
if an acceptable Authorization header has not been sent, the server
responds with a "401 Unauthorized" status code, and a "WWW-
Authenticate:" header
If the above is correct, are clients expected to preemptively send the Authorization header?
Thanks!
EDIT (and probably RESOLVED): My original security config had:
http.exceptionHandling()
.authenticationEntryPoint(spnegoEntryPoint())
.and()
.authorizeRequests()
.antMatchers("/v1/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore()...`
When I remove .antMatchers("/v1/**").permitAll() the SpnegoEntryPoint kicks in and I now see a 401 with WWW-Authenticate: Negotiate response.
Of course now I get a Server not found in Kerberos database gss_init_sec_context() failure but i suspect that has to do with SPN setup or host name resolution (since I am testing this locally on my Macbook) than the Spring app.
Will update once finally when I get this working.
Yes, the zero argument cosntructor is correct.
The Filter is not responsible for setting the Status and Header. The SpnegoEntryPoint is. org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint.commence(HttpServletRequest, HttpServletResponse, AuthenticationException)
No, see 2.

What is the concern about bad request(400) or forbidden(403)? [duplicate]

This question already has an answer here:
Which HTTP status code to say username or password were incorrect?
(1 answer)
Closed 5 years ago.
I am implementing an endpoint which offer some secret data and I want to make a simple verify mechanism. Which status should I response when user does not have the correct crediential?
400? 403? Or something else?
thanks.
You should use 403, HTTP status code 403 responses are the result of the web server being configured to deny access to the requested resource by the client.
See HTTP 403
You can use 401 if you intend to authenticate via www-authenticate header field. If the authentication information was incorrect or missing send 401.
Or use 403 to notify the sender of the request that he is not allowed to access the requestet content. According to the documentation the response should state the reason why the request was refused.
If you do not with to do so you could alternatively send a 404.
For further information see the linked Documentation.
w3.org http Protocol
EDIT: improved from link only answer.

Resources