Spring SAML - Is it mandatory to call SAML local logout when user signs off from application? - saml-2.0

As per the answer from the link, I understand that if SAML local logout (/saml/logout?local=true) is invoked Spring-SAML will clean the local cookies. So, I have modified the logout logic in my application to invoke it.
All looks good till now. But my application have session timeout set to 20 minutes in web.xml.
<session-config>
<session-timeout>20</session-timeout>
</session-config>
In case of user inactive for 20 minutes or browser is closed by the user, session will be destroyed by the container silently. In that case SAML Logout is not invoked.
Questions:
Does Spring-SAML maintains any references once user is authenticated after SAML response is received?
If yes, where does it maintain references (session or somewhere else)? Any alternative way to clean them up?
What are the implications if we do not call SAML local logout?
My worry is that if the references are not cleaned up, It might cause memory leaks in a long run of the application.

By default all state of Spring SAML is stored in HttpSession (as part of Spring Security context in object SAMLCredential) and will be cleaned at session timeout (or more precisely at time when your container decides to perform the session cleanup after expiration).
It is exactly the same as with any other authentication method supported by Spring Security, so you don't need to worry about not calling the local logout.

Related

Refresh token in Desktop App for OAuth2 Authorization Code Flow

I want to use API in my .net WinForms application which are closed by JWT token. Such tokens can be received from the Identity Provider using Authorization Code Flow + PKCE. I worked with such flow before in Web Application and I know how to request code, exchange it on the access token and I used silent refresh approach to refresh the access tokens.
For my clientId I'm not able to use refresh tokens. So, I'm slightly confused how to implement to refresh tokens in the Winforms application.
It's definitely I need to open Login page to allow the customer enter credentials. Then I guess I need to catch code from the Redirect URL. It seems I need to use loopback IP address as a redirect URL and catch request in the application.
But how to set up refreshing process I have no idea. Please help with advice or add links to examples.
For a desktop app you should follow the recommendations from RFC8252. Without a token refresh you will get usability problems. Eg access token expires after 15 or 30 minutes, then user experiences a re-opening of the system browser.
This might be fine for a high security app, such as for banking, but for most apps it is not what you want. Alternatives such as long lived access tokens are bad from a security viewpoint, since the long lived value is then exposed on every API request.
You won't be able to use silent renew via hidden iframes either, since you don't have that much control over the system browser. You can only open it by executing a URL.
So you have these main choices, and maybe you can explain trade offs to stakeholders. You won't be able to implement a workaround in code:
No refresh token, and sub-optimal usability
Refresh token used, so a longer lived API credential is used in a public client
Locking down what can be done with an access token issued to the desktop app - using scopes and claims - is usually the main mitigation of this type of security concern.

Concurrent login with identity server4

Want to logout from all other session(s) when user logs in other browser.
I am able to delete the PersistedGrants but cookies are still present.
When user refreshes the page a new access_token is generated due to refresh_token.
So basically we want only one concurrent session of user.
Any help would be appreciated.
By default IdSrv persists user session in a cookie. You can change that by implementing IUserSession and registering in DI. Doing so you get access to logged in clients within one session. Having that knowledge, you can register your custom middleware with the check: when authenticated, i.e. has auth cookie, and no other session for the same user id then ok, else handle the collision: the one who logged in earlier logs out. Just an idea, but should work. See my customization of the DefaultUserSession - backing it to Redis, used for another purpose, but should be enough to demonstrate the approach.

In IdentityServer4 what is the difference between the 'idsrv' and the 'idsrv.session' cookie?

I understand that the idsrv.session cookie is used to detect whether or not a user's session has changed. This cookie is part of the the OIDC Session Management implementation that is provided in IdentityServer. What I then don't understand is what the idsrv cookie is used for. Can someone please explain?
The idsrv cookie is used for ASP.NET Core Cookie Authentication.
See http://docs.identityserver.io/en/release/topics/signin.html
IdentityServer registers two cookie handlers (one for the authentication session and one for temporary external cookies). These are used by default and you can get their names from the IdentityServerConstants class (DefaultCookieAuthenticationScheme and ExternalCookieAuthenticationScheme) if you want to reference them manually.
DefaultCookieAuthenticationScheme value is 'idsrv'
The .session cookie is only used by the session monitoring endpoint to detect if the current session has changed. You’ll notice that it is not set as HTTP only and thus can be accessed by script run by that endpoint. It is not the authentication cookie.

Incorporate Keycloak login into SPA

We're currently evaluating Keycloak as our SSO solution and while it works for our servlet-based applications there's a question regarding our (React-based) SPAs.
What our designers want: as an example let's say we have an email client spa. The user is in the process of writing an email but then gets distracted. When he returns the SSO session has already timed out and a re-login is required. The user should now be presented with a login form and after login it should be possible to send the email that's still in the SPA's local storage (i.e. re-login without restarting the SPA or losing data).
AFAIK Keycloak doesn't provide an authentication-api (for good reasons) and uses a redirect to the login page and back to the application (as I understand it for mobile apps the system browser would be used). If I'm not mistaken that redirect would then mean the SPA is then reinitialized and thus the data would be lost.
So here's the question: is what our designers want possible to do with Keycloak?
If yes, how would it be done? Directly posting to the login-url that Keycloak is using seems like a bad idea since the tokens would probably not be stored correctly and there might be same-origin policy problems. Would doing it inside an iframe or popup-window work?
For someone who comes back to this question,
I think it's better to stick to the best practice for oAuth2/OpenId Connect for SPAs which is currently "Authorization Code Flow" with PKCE.
https://oauth.net/2/pkce/
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-13
A normal flow here needs a complete redirect to the auth server and back so your app will completely re-initialize. Or you use check-sso like Sébastien already mentioned with silent mode.
https://github.com/keycloak/keycloak-documentation/blob/master/securing_apps/topics/oidc/javascript-adapter.adoc
You can configure a silent check-sso option. With this feature enabled, your browser won’t do a full redirect to the {project_name} server and back to your application, but this action will be performed in a hidden iframe, so your application resources only need to be loaded and parsed once by the browser when the app is initialized and not again after the redirect back from {project_name} to your app. This is particularly useful in case of SPAs (Single Page Applications).
This way the login will happen in an iframe and the app initializes only once and should preserve state.
Even if it's not considered as a best practice you can turn on Direct Grant Access for your client which enables to login through a REST call.
Anyway, about not loosing the state of your app, this is a bit outside the scope of Keycloak but you should be able to achieve that with having the state in your redirect URL for instance ?
Also, if you don't want your app to automatically reidrects to the login page you can use : keycloak.init({ onLoad: 'check-sso' }) instead of login-required

Spring Security SAML assertion expiry with Application Session Expiry

I'm getting confused with the SAML assertion expiry vs Application session expiry.
In simple words, when we have an application deployed in a container, there is a session created. This session expiry can be controlled with the below entry in web.xml
<session-config>
<session-timeout>60</session-timeout>
</session-config>
Moving on, when I have Spring Security with SAML extension, obviously the same session concept applies. (I'm deploying the application in WildFly 8.2, if that matters)
Further, when the application session expires, the logout behaviour seems to be equivalent to Local Logout concept.
So far so good. Now lets say that the SAML assertion is good for 2 hours and the user has been actively working for 2 hours. What should happen to the subsequent request then? Should it re-login to the IDP? But, wouldnt that be inconvenient to the user? If the application redirects to IDP for logging in again after 2 hours of assertion expiry, How should AJAX requests be handled?
This is in reference to the question here
Spring SAML issues an ExpiringUsernameAuthenticationToken for authenticated users. The token starts returning false in its isAuthenticated() method once the SAML Assertion used to authenticate the user reaches its sessionNotOnOrAfter time.
This behavior can be disabled by overriding SAMLAuthenticationProvider and changing method getExpirationDate(credential), which returns time when the Assertion expires, or null in case it never does. Application will then fully rely on session expiration configured in the container.
Once the ExpiringUsernameAuthenticationToken expires, Spring Security will pass the current token to the AuthenticationManager (configured in securityContext.xml under <security:authentication-manager>).
You can affect what happens next, by adding your own AuthenticationProvider able to handle the ExpiringUsernameAuthenticationToken. Otherwise system fails with ProviderNotFoundException or some other AuthenticationException like BadCredentialsException (in case you're using username/password authentication at the same time).
The exception is subsequently handled by ExceptionTranslationFilter, which start new authentication process by invoking the configured authentication EntryPoint - e.g. SAMLEntryPoint which either starts authentication with default IDP or displays IDP selection page. The process will also essentially perform local logout, as you say.
System by default behaves the same for all HTTP calls - AJAX or not. You can define different behavior by splitting your API and normal URLs into separate <security:http> elements and use different EntryPoints (interface AuthenticationEntryPoint) for each. For example Http403ForbiddenEntryPoint might be suitable for your AJAX calls.

Resources