Refresh SAML SSO Session - node.js

I need to implement SSO using SAML for my application which is running on NodeJS. I have doubt regarding refreshing the session expiration time for a user who has logged in through SSO.
Upon reading many documents, I came across this flag called IsPassive. My understanding about this flag is that an AuthnRequest will be sent to the IDP SSO url and the IDP will respond at the SP's Assertion Consumer Service URL with the session expiry time (if the session is alive). Is my understanding correct? Apart from that, I have a couple of questions:
I want to develop a backend service to refresh the session timeout and session token for all the SSO users so that the SP's page is not redirected everytime the first session expires. The AuthnRequest does not allow me to send the NameId for the user whose session has to be validated. How can I send the AuthnRequest with the particular user's NameId to check his/her session's validity?
If the first Login response gave me the SessionNotOnOrAfter as time t, will the response to the IsPassive request give me the response SessionNotOnOrAfter as t or t + x, i.e, will the IsPassive response give me an extended time for the session? Also, will the SessionIndex remain the same or will it change?
I am using a serverless backend hosted on AWS Lambda and plan to send repetitive IsPassive requests to the IDP's SSO url from the Lambda.
Since I am a newbie in this, I hope I got all the names and attributes correct to describe my problem

Related

IdP as the master session

Background
I'm trying implement a browser-based login for a native mobile app from an existing Single Page Application. It uses WebView to render the SPA and it uses Keycloak OIDC as its Identity Provider.
The SPA and IdP is located in completely different domain and authentication is done by redirecting to the SPA domain after a successful login and retrieving the active session (cookie) from IdP domain in one of the SPA's server. The authentication check is achieved by using keycloak middleware which I believe is the protect.js
Summary:
Perform Login -> auth.idp.com
Redirect -> best.app.com
Is Login? -> best.app.com/login
Does auth.idp.com session exists?
User is logged in, redirect -> best.app.com
Token is passed in the URL and is stored only in memory
Token is used to establish WebSocket connection
Issue
Based from the spec, the authorization should happen in the browser / in-app browser, and authorization code must be passed via custom URL scheme. Having that in mind, the SPA that resides in the WebView of native mobile app will never establish a session from IdP's domain since this will be delegated from the browser which is on a different process and obviously using a different cookie store than on WebView in the mobile app, which makes our existing solution to break because it is relying on the IdP's domain cookie.
Proposed Solution
The issue I described above can be mitigated by cutting the reliance on IdP's session and by managing the SPA's own session, which basically means storing the token persistently that can be obtained from the IdP (which the current solution doesn't do).
(I don't want to detail much of the solution since I just want to focus first on the concept of storing the token. I think it's better for me to put this in a separate discussion if someone is interested)
Opinion
It seems like the current implementation doesn't really follow the best practice for OIDC flow but somehow, Keycloak has made some middleware to remove the need to use these tokens (authorization code, id token, and access token)
Relying on IdP's session when implementing SPA or non-web apps seems like not an option, because there is no way to obtain the cookie without reloading the page and provided that IdP session exists in the same cookie store as the SPA.
Redirecting to the IdP's session is not a good user experience for SPA. See the same sentiment here but it seems it does not have any answer: https://lists.jboss.org/pipermail/keycloak-user/2016-October/007937.html
Question
With regards to my proposed solution, i.e., storing the token retrieved from IdP, is there any security flaw or something non-industry standard it's going to introduce? If so, what are those?
Is it typical for OIDC flow to rely on IdP's session (cookie) to check if user is logged in or not?
If answer from #2 is NO, is that authentication flow specific for Keycloak only or does it exists for other IdP as well?
If answer from #2 is YES, is it common for IAM solution to programmatically check if the IdP domain contains a valid session (cookie)?
Is the current implementation flawed knowing we are aiming for SPA?
How does Keycloak handle sessions?
If you're using the default Keycloak middleware in your server and use keycloak.protect() for protecting endpoints, it checks on the request.session['keycloak-token'] which contains the access_token that was created during the token request after user login. If this exist and valid, it means user will not be redirected to Keycloak login page.
How does Keycloak create sessions?
Providing username and password which can be done manually using Keycloak's login page.
Cookies - if you pass valid cookies that are recognized by Keycloak, i.e., KEYCLOAK_SESSION, KEYCLOAK_SESSION_LEGACY, ..., a session will automatically be created.
How to access protected resources?
When using the keycloak-connect client adapters, you can access protected resources if the user agent (browser/app), has a valid session in your server OR if the request contains valid Authorization header.
Standard Solution
Access protected resource via Authorization header and use access_token which the keycloak.protect() also accepts. You can obtain this token in a standard way using Chrome Custom Tabs for Android and ASWebAuthenticationSession for iOS. You can also use AppAuth (iOS, Android) to lessen your work.
Store the refresh_token and access_token from native mobile and inject this in the HTTP request of WebView if possible.
Have a way to check for access_token validity and use refresh_token to request for a new one. If requesting for a new one fails, i.e., the authorization server verifies it's not valid anymore, that means users would need to re login again.
By using the standard solution I have proposed above, you should not need to create a band-aid solution for your issue. Hope this helps anyone that have faced similar issue.

How does the user session work for OAuth2 authentication type Jhipster application?

An Oauth2 client application generated by Jhipster has a behaviour issue after some idle time. After a signed-in user has some idle time on the application, interaction with the application will lead to an undesired behavior such as a data isn't fetched from the database.
I have learned that user session data is stored in a form of a cookie on the front end. For the Vue front-end, searching
this.$cookie.set(
yields no result.
I do see JSESSIONID in a request header after a user signs into the application. So, I assume that the session id also is stored somewhere on the server. For every REST request, the server would verify the session id in the request header by comparing it with the session id on the server. When the session is time out, the server no longer has the session id. Any REST request from the point will lead to undesired behaviour in the current implementation. A filter is needed to verify a REST request session id with the server.
I have a look at the code in the security package as well as the security configuration. But, I don't see any code dealing with a user session.
How does the server work in this regard?
Update:
To deal with an invalid user session for a sign-in, I notice that the ExceptionHandlerExceptionResolver will handle the InsufficientAuthenticationException after refreshing a browser. Otherwise, the exception won't be handled. How to resolve this issue?

How should I handle RESTful authentication while using JWT tokens?

I have read many articles and viewed many videos but there are a lot of contradictions. I try to avoid any external libraries and build the system from scratch, I have read about oAuth 2 but it is more confusing.
This is the flow that I think is ok untill now:
User fills a form using email and password and submits it.
Server verifies the password if it matches and responds back with a httponly cookie with a signed jwt token that expires in like 10
minutes. (I know I have to protect it against csrf attacks)
User gets logged in and every new request he is making to the server he will send the cookie in the header automatically and the
server will verify the token.
Everything is fine but I have encountered some issues and have some questions:
I want the user to stay logged in even after opening a new session so there is no need to login after the token expired or when he closes the browser.
What should happen if the access token expired?
There should be a refresh token attached to the user in database that gets added when the user logs in with an expiration of ex 7 days, then the server will respond with a cookie containing that refresh token?
On the new request while access token is expired,the user will send the refresh cookie to the server, if it matches the user database refresh token,server will respond with a separate cookie that will renew the access token?
If there is a refresh token where should you store it and what format? (cookie,database or where?)
Should I keep the user logged in based on this refresh token cookie?If is it httponly I can't read it and set the state that user is logged in. How should I do it?
I heard about that revoking the jwt token is problematic. How would you fix it?
How would you do this whole thing?Please explain the workflow, I try to avoid localstorage,as I read everywhere that is not safe for sensitive data.
I have implemented and deployed to production systems that do exactly the kinds of things that you are asking about here so I think that I am qualified to provide you with some guidance to solve your particular issues and answer your questions. The flow that you have listed above in the numbered list is definitely the correct path so far. I do understand your confusion going forward from there because there are many different options for how to approach this problem.
In addition to providing a login route that returns a new JWT to the client when the user submits a login form to the server, I would recommend also implementing a token refresh route that accepts a still valid JWT that was received from the initial login process and returns a new JWT with an updated expiration time. The logic for this new token refresh route should first verify that the provided JWT is still valid by matching it with a user in the database. Then, it should generate a new token using the same JWT generation logic as the login route logic. Then, the application should overwrite the access token data in the database for the user replacing the old access token with the newly generated access token. It is not necessary to keep an old access token in the database once it is no longer valid, which is why I suggest simply overwriting it with a new one. Once all of that is finished and successful, you can return the new JWT to the client and then the client should now use that new JWT when making any additional authenticated calls to the server to maintain an authenticated interaction with the server. This logic flow would keep the user logged in, because the client would have a valid JWT before calling the refresh logic and it would have a valid JWT after calling the refresh logic. The user should only be recognized as not logged in and not authenticated if they are no longer able to provide a valid access token that is associated with a user in the database.
As far as cookies go, whichever method that you use for maintaining the cookies on your client should be used for setting the refreshed access token as it is for setting the initial access token that you receive on login. If the server finds that an access token is no longer valid at some point in the future, if for example your client is not used after login until some time after the access token has expired, then the client should recognize a server response indicating that this is the case and present the user with the login flow on the client again so that a new access token can be acquired and stored in a cookie on the client.
I would not worry about revoking JWTs and instead just let them expire if they do and initiate a new login flow if it is found that a JWT has expired. Also, instead of using local storage I would suggest using session storage to store your JWT so that you have it for the duration of your user's session on the website and it is removed as soon as the browser has been closed. This will prevent the JWT from persisting beyond the session and should assuage your fears about saving sensitive data in the session storage. Also, when generating your JWT, you should also make a point of not storing any sensitive data in it because JWTs are easily reverse-engineered. This can also prevent any sort of sensitive data from being exposed on the client.
EDIT:
The key thing to remember when developing your server API is that you should have two different classes of endpoints. One set should be unauthenticated and one set should be authenticated.
The authenticated set of endpoints would not require an access token to be included in the request. An example of this class of endpoint would be your login endpoint, which does not require an access token because it actually generates an access token for you to use later on. Any other endpoint that does not expose sensitive or important information could be included in this class of endpoints.
The unauthenticated set of endpoints would require an access token to be included in the request, and if no access token or an invalid access token is detected the endpoint would respond with a 401 HTTP response code (indicating an unauthorized request). An example of this class of endpoint would be an endpoint that allows a user to update their personal information. Obviously, a user cannot update their own information if they cannot provide credentials to prove that they are the user whose information they are attempting to update. If the client receives a response with a 401 response code, that would be the signal that the client would need in order to tell the user to re-login so that a new valid access token can be retrieved. This possibility can be avoided on the client if the client is programmed to periodically check the expiration of the JWT that is currently being held on the client and initiate an access token refresh, but obviously you should still have logic in place to detect and respond to a 401 response code so that the client user flow is managed properly.

After logout previous captured request still valid in azure ad authentication

We are facing issue on logout from our application. Once we logout then its perfectly fine from browser but if we capture the request from some tools (fidler or burp) and send the request again to server with old cookies and session details give full response. This is only possible through any interceptor tool only. I am using the below code to logout from application:
Session.RemoveAll();
HttpContext.GetOwinContext().Authentication.SignOut(OpenIdConnectAuthenticationDefaults.AuthenticationType,
CookieAuthenticationDefaults.AuthenticationType);
This is happening because access token and refresh tokens issued by Azure AD are not deleted when you initiate the log out from your application. As long as these tokens have not expired, they can be used.
Based on this, access token lifetime is configurable (default I believe is 1 hour) and you should set it based on your needs.
Also, there's a feedback post regarding invalidating tokens: https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/19474918-invalidate-jwt-token. Feel free to upvote this feature.

How to forcibly ask authentication for a web resource for every access?

I have some webserver resources protected with Form based Authentication. The requirement is to have some highly secure resources access result in forced authentication of the user even if he/she is authenticated earlier and have a valid cookie (authentication).
The authentication in a session is maintained by a particular cookie. The first idea to solve this problem is to pass that cookie with "expires" value with back date. But for the form login it is not working, I am getting only login page everytime after providing correct credentials. Cookie with expire value with back date is encountered, cookie is deleted by browser. So this cycle of login is encountered.
Please advise me on what to do.
At this point authentication isn't enough. You're going to have to implement multiple levels of authorization, with some levels not having persistent tokens. There's a number of resources on the Internet that explain token-based auth.
Basic authentication (not to be confused with the HTTP scheme of the same name) uses only a single token to determine whether the user is logged in or not. Just split the application into multiple authz token realms and handle it from there.

Resources