Spring security login form jsessionid not sent accros domains - spring

I have two Spring boot applications one is a client UI app and the other acts as an Authorization Server (using spring security oauth, implicit flow and form login).
When the two applications run on localhost (different ports) I can see the following flow:
The client makes a request to oauth/ahthorize to retrieve a token.
Since the client is not authenticated the server responds with a 302 redirect to its login form, setting also two cookies (XSRF, JSESSIONID).
The user enters his credentials and a POST is performed in the login form. Since the two apps run in localhost the two Cookies are sent in the POST request.
This way, the server retrieves the SavedRequest for this JSESSIONID and performs a redirect to the saved client url, as expected.
The problem is when running the two applications in different domains (I am trying to run it in Pivotal Web services environment).
The JSESSIONID cookie is not sent on POST of the login form.
This makes sense because the cookie was set for the client domain, whereas the login form is in a different domain and does not have access to the cookie.
This has as a result that the server does not find a SavedRequest object to retrieve the redirect URL
of the client and it redirects to the root of the server (/)
What am I missing?
EDIT: here is the POST on the login page on localhost (working scenario):
and here is the POST when domains are different (not working):
EDIT 2: Here is the authorize request, which is made to the client domain (and proxied to the server through Zuul:

Related

How to handle cookies with Azure AD authentication, Apache Reverse Proxy and Tomcat?

I have an Angular App with a Spring Boot Backend. I use "azure-active-directory-spring-boot-starter" for the authentication via Azure AD. Everything works fine locally.
After the successful external (azure) login "https://local.../login/oauth2/code/azure?code=..." is called.
The request headers on this request contain authorization cookies from azure and the response header contains two "set-cookie"-entries: JSESSIONID, XSRF-TOKEN
After that request the user is logged in as expected.
With the production setup however it seems, that cookies are not set successfully.
The application runs on a Tomcat 9 behind a apache reverse proxy. The azure login itself is successful.
Also the request headers contain the two cookies, however "set-cookie" is not set. Any ideas how to solve this?

Pass Information with URL redirection

We are working on an existing application where web services (tomcat) as well as UI (nginx) applications are hosted on separate containers. One of the service application is used for sending login request (SAML request) to identity provider (ping). Here are the steps for user login to the system:
User loads the application (domain URL: https://ui.domain.com), it loads the UI where it checks for logged in user (JWT token string generated for user/role) on local storage and when not found, it redirects to ping (IDP) for authentication.
Once authenticated with ping, it calls the spring controller which is configured for the success URL on service application (https://api.domain.com/auth-service/auth).
This controller service (/auth), gets the SAML response sent by ping and processes it further to get user details and generates the JWT token for the user and redirects the user to UI (https://ui.domain.com).
Problem Statement:
To pass the token to UI, the JWT token string is added to URL by using
redirectAttributes.addAttribute(“auth-token”, token);
With the above, it shows up in the address bar like: https://ui.domain.com/?auth-token=
This has raised a concern with respect to security as the token is displayed on address bar and exposed which can be decoded to get user information.
Current Approach (tried):
Before redirection from controller to UI, tried to set cookie
Cookie cookie = new Cookie(“auth-token”, token);
cookie.setMaxAge(-1);
cookie.setPath(“https://ui.domain.com”);
response.addCookie(cookie);
However we couldn’t find the cookie from UI.
We tried to set it to response header too.
response.addHeader(“auth-token”, token);
Since it is a redirection, the adding to response doesn’t help.
Further trials:
We are also putting a thought about changing the approach of authentication controls where after ping authentication is done, the success URL can be replaced with UI url rather than service URL, i.e.
Current: saml.sso.default-success-url= https://api.domain.com/auth-service/auth
Proposed: saml.sso.default-success-url= https://ui.domain.com/
With the above, the SAML response supposed to go directly to UI (after ping authentication is successful).
However we couldn’t get the response in UI and it also behaves like ping is doing a redirection to UI and due to the same reason, UI doesn’t get it.
Any ideas and suggestions over this would be great.

CORS and LTPA token from local domain

I'm struggling with CORS and a SSO configuration between two WAS servers using LTPA key share.
CORS calls from server1 (domain1) to server2 (domain2) work fine if I don't have authentication on server2 (meaning the cross domain Ajax call works), but it doesn't if I have.
The context is: The web client logs into domain1, one part of the UI needs to display some data coming from server 2 (domain2). Server 1 and server 2 share the same LTPA key with the same realm. That works fine, I can make manual calls (with curl for example) to domain2 using the LtpaToken2 from the webclient obtain from domain1.
The problem is: When I make the CORS call from the web client, I use withCredentials to true, but withCredentials includes cookies from the remote domain, and of course I have no cookie yet since the browser does not know the domain2 yet. What I need to do is include the LtpaToken2 cookie from the local domain (domain1) when doing the cross-domain ajax call to domain2. That way I will be authenticated. But because of the cookie cross domain policy I'm stuck.
Am I approaching the problem in the wrong way here? How would you handle that: doing a CORS call to a yet unknown domain using the LtapToken from the local domain?
Thank you very much for your help!

If possible, How to authenticate thin server SPA users through backend REST where nginx role limited to serve static content and proxy Backend REST?

I am building SPA with thin server architecture (in my case it mean: webserver role restricted to server static content and route xhr with backend REST services):
so far I failed to find any example that provide user authentication scheme that cover my requirements, when it comes to user authentication all what I see webserver (server side code) involved whether its php/nodejs/asp.net..etc.
I want to build the authentication with zero dependency on server side code that belong to webservers:
details:
user requested login.html.
NGINX served the user request.
user supplied credentials and submit.
Ajax XHR received by NGINX and routed to the Authentication backend REST service.
authentication backend service validated the request and returned response that include session cookie/access token/api key.
Ajax XHR received the response through NGINX, then what? how should I proceed? below are current ideas I have:
a. in many examples (including instagram): window.location.reload();. but in my case reload login.html will not cause NGINX to forward the user to the landing page unless it maintain the authentication logic! so how I can pass this obstacle?
b. in case I redirect the user to landing.html, NGINX will serve it. but again that's not acceptable because every resource request (except login.html) must be validated first (I mean both authentication and authorization).
I hope the question is clear now. I think if NGINX can be configured to pass every request to the authentication backend REST service before it go to the original destination, big part will be resolved though it might be big overhead for auth service!
Your best option here is to use X-Accel-Redirect. This will allow you to pass your requests to the authentication service and then in the authentication service you can run your auth logic and if successful set the X-Accel-Redirect header so that when nginx gets the response it will perform an internal redirect to the resource that you actually want to call. If authentication fails your service can reply with a 401 and not set the header so nginx will provide the proper response to the client.
Your other option, which will be more daunting, is to implement this as a custom Lua module.

Spring Security : restrict other web application access

I am running spring web application in broswer. I logged in to my account and update some value using a url say localhost:80/update/name. On the controller side I check principal==null if not redirect to login page.
Now while login to this application. I open other web application page in the same browser and execute the same update url localhost:80/update/name through ajax call and it is updating the value. How can i avoid this security threat.
How can i make sure that Application1 update url will be executed by application1 request only? Application2 should not be allowed to execute app1's update request no matter whether it is in same browser ?
Why are you surprised ? You are logged, thus the browser has a valid session cookie. You ask the browser to send a request to the host (be it in first window or any other window, it is the same) : it sends the request with all relevant cookies, including session cookie and if appropriate any other security cookie. The server receives a request containing a valid session cookie for a valid logged user and even if it controls IP addressed coming from same address : all is valid and it proceeds with the request.
If you have a different browser on your client machine and if you open the connection from this unrelated browser, the server should reject your request, because the browser would not present a valid cookie.
You are describing a variant of cross-site request forgery, you should enable Spring Security CSRF protection. You can read about it in the reference manual.
Even if the two applications are on the same server, they will get different CSRF tokens, which will protect your case.
You described Cross-Site request forgery attack. Typically when POST method is used hidden token is added to prevent it. I assume You are using GET method - It is good practice to not change any state using GET method.

Resources