Keep authentication between 2 applications with Keycloak SSO - java

I have 2 JHipster apps running each on one subdomain (app1.domain.tld & app2.domain.tld).
In both apps, users login through Keycloak. The sequence is as such :
Angular app sends /authenticate request with credentials to Keycloak
In case of successful response returns a authentication cookie
POST request is is sent to Jhipster backend app that generates JSessionID cookie
JSessionID is then used for every request to backed app.
What would be the best way to automatically login user (without asking username & password) if they are already logged in one of the apps of the domain (*.domain.tld) ?
I tried to use the JSessionID as a global token before understanding it only works on the app it was generated on...
Maybe catching Keycloak authentication cookie (returned at step 2) and authenticating on second application would do the trick ?
From what I saw while testing, after being authenticated on first app, when I go to the second one, Angular 401 HTTP interceptor redirects to keycloak login page with a session token. Thus at that time Keycloak should see that I'm already logged in and should redirect me to home page of my second app.
Am I right ?

The javascript adapter solve this by creating an iframe that's loaded from the authentication server.
From the keycloak docs:
Session Status iframe
By default, the JavaScript adapter creates a hidden iframe that is used to detect if a Single-Sign Out has occurred. This does not require any network traffic, instead the status is retrieved by looking at a special status cookie. This feature can be disabled by setting checkLoginIframe: false in the options passed to the init method.You should not rely on looking at this cookie directly. Its format can change and it’s also associated with the URL of the Keycloak server, not your application.
The success callback of init function has a parameter that gives the authentication status of the user.
<script src="keycloak.js"></script>
<script>
var keycloak = Keycloak();
keycloak.init().success(function(authenticated) {
alert(authenticated ? 'authenticated' : 'not authenticated');
}).error(function() {
alert('failed to initialize');
});
</script>
If the user is authenticated redirect the user to the login page, since the user is already authenticated there is no need to input the login credentials again. The adapter can handle this automatically if it's initialized with the onload option check-sso
For more details on the inner workings of the javascript adapter, the source can be found here

I solved this problem by changing the cookie name generated on the client where token information is stored. In this way, using app2 will not invalidate the token of app1 because it will use a different name. Maybe there is a better way to accomplish this in a SSO environment but it works for me.
Change application.yaml by adding server.servlet.session.cookie.name entry with the new cookie name:
server:
servlet:
session:
cookie:
http-only: true
name: JSESSIONID_APP1

Related

How to login to backend from frontend in vaadin

My question is how can I login into backend secured by spring security WebSecurityConfigurerAdapter ?
How to send request to login to default page spring security ?
Login page is on localhost:8080/login (default spring login page) and my front is on localhost:8081. How can I write method to login on this page ?
Because you have two seperate servlets on different ports running they cannot communicate with each other unless you explicitly implement that. One way to perform an automatic login would be some token you pass via the URLs GET parameters.
For example if you want to login from localhost:8080 to localhost:8081 you first have to check if the entered credentials on localhost:8080 are correct. If so, you can do a HTTP redirect to localhost:8081?token=123456 where the value of token is generated in the backend any stored in some place (e.g. in a database). If a user is now accessing this localhost:8081 page and is passing a token via GET parameter in the URL you can verify this token. If it is correct, you can login the user automatically.
But you have also have to ensure that the token handling is secure. Use long, cryptic tokens that have a limited, small live-span. Also delete used tokens after the login is performed. Never use the same token multiple times!
This may be one way you can do that.

Websphere 9, how to check incoming ltpatoken2

Good day
I have an incoming request to my application based on websphere 9 with ltpatoken2 cookie.
Previously, the ltpa key was exported from my websphere and add to another server. The option Application security was enabled.
How I can check, at websphere or at my application, that the token is exists and correct?
And my application should be not avialable for requests without token.
In WebSphere 9, if request contains a LTPA cookie, LTPA cookie will be processed automatically. Inside your application code, if you call API com.ibm.websphere.security.auth.WSSubject.getRunAsSubject(), you will see a subject created form the ltpa token if LTPA token is presented and is also valid.
And you will see unauthenticated subject if ltpa is missing or invalid. Or inside your application, if you call HttpServletRequest.getPrincipal().getName(), you will see a user name represented by the LTPA cookie if it presents and valid, and you will see principal name or see unauthenticated user name if LTPA is missing or invalid.
There's no API to inspect that token, but you can test it implicitly. You can capture browser traffic with Firefox or Chrome developer tools, then after successful login, using either the browser tools or curl, send a modified request without the cookie, or with a bad cookie value, and you should get an authentication challenge since the cookie's not there.
The easiest would be to just add security constraints to your web.xml protecting whole application (you will find many examples), and map security role to All authenticated. Then your application will be available only, if user is already logged in (so the LTPA token exists and is correct), otherwise it will redirect you to login page that you can include in your application and redirect user somewhere, informed that he is not logged in, or whatever you want to do in case there is no valid LTPA token.

How to authenticate and authorize Java application with KeyCloak

I have a Java servlet that accepts HTTP requests, "protected" by KeyCloak. I can manually send a GET request, which redirects me to the KeyCloak login page, and I can log in and see the correct webpage from the servlet. Now I would like to make it such that my other Java application can also authenticate itself and access the webpage.
In my current setup I have the Java servlet running in Wildfly and the keycloak standalone. I have a KeyCloak realm with a user "testuser" with the role "testrole" and client "testclient". To be fair I don't really know what the client does, since it has no role or other attributes set. Should it represent the servlet application or the requesting Java application? What attributes should I set here?
The documentation mentiones JWT Tokens, but I don't know how I can obtain one. The actual request should be to "localhost:8080/testservlet" , do I have to query for a token at the KeyCloak server first, or should I go through the redirect process as when it is "manual"?

Losing spring security remember me subdomain cookie following redirect

I believe my issue is something very similar to the following question Spring security 'remember me' cookie not avaiable in first request.
Basically I have a set of applications for a corporate intranet that share authentication through a remember me cookie. The cookie's domain is set to .domain.com so it can be shared across applications since they are all on the same domain or subdomain.
If a user is not logged in and attempts to goto a secured application they are redirected to a central application for login. After logging in the user is redirected to the original application they were sent to the login screen from however here is where the issue begins. On this first request the Remember Cookie will not be present in the HttpServletRequest on the app receiving the redirect and the user will fail to login, being redirect right back to the login screen. At this point though the actual cookie is in existence and valid and the user can manually go to the url they just came from and be logged in by remember me cookie.
For example
domain.com/app -> redirect -> domain.com/main/login -> redirect -> domain.com/app -> redirect -> domain.com/main/login -> manually navigate -> domain.com/app -> logged in.
I've tried several solutions from redirecting on the backend with response.sendRedirect to send the user to an intermediate page first that redirects with JS and none of it has helped. The cookie is simply not there on the first request for the other applications. To make it even more confusing, if the login redirects to the main application that contains the login page, the cookie is there instantly on the first request.
Any thoughts?
This ended up being do to the request cache getting in the way during our series of post login redirects. Add the following to our java security config fixed the issue.
public HttpSecurity configureHttp(HttpSecurity http, IntranetSecurityAccessDeniedHandler intranetSecurityAccessDeniedHandler) throws Exception {
http
.requestCache().requestCache(new NullRequestCache()).and()}

JBoss Custom Login Module Only Works Once

I have written a custom login module for JBoss that authenticates/authorizes requests to a web service. The first call to the service authenticates fine. I can connect a debugger to the login module and trace the code execution. However, all subsequent calls to the web service skip the login module entirely. It appears JBoss/jaas is reusing the results of the first connection.
I'm stuck. Any suggestions to get me over the hump?
I figured it out. I was trying to setup cookie based authentication. Apparently, JBoss/Jaas caches successful authentications based on username and password and cookies are ignored. To get things working, I dropped the cookie from the web service request and replaced it with a username and password in the authentication header.
Is the authentication/authorization associated with a session object? How have you set the timeout/invalidation of the session?
JBOSS is probably caching the credential somehow. You want it to skip the login module in that case. You should only invalidate it if you log out or timeout the session.
Did you test it with two separate users/browsers, each with their own session?

Categories

Resources