Keycloak OIDC backchannel logout multiple sessions on same client - keycloak

While testing the backchannel logout of our OIDC client implementation, I noticed the following behavior in Keycloak when multiple sessions exist.
Preconditions:
Log in the user in the same client using, e.g., two browsers. You will see two sessions for the registered OIDC client in Keycloak
On the user’s sessions tab, click on “Logout all sessions”.
This results in one single backchannel request being performed, where of course I can identify the user through SID (ID of one of the two open sessions) or SUB (internal ID of the keycloak user).
Now you can imagine that the client itself may have internal session information (session cookie, other pieces of information of the client) that you’d like to invalidate/terminate as a result of the backchannel request
However, it is impossible for the client to identify which of the sessions to actively terminate, as seemingly only one of the active sessions in Keycloak will be submitted as a backchannel logout request.
How can I identify as a client which sessions to terminate? Is this a bug in keycloak? (I would have expected one request per session to get both SID logout requests in the client), or some other means of transporting the intent to the client of logging out all sessions of the subject.

Related

What does it mean to "redirect with token" for single sign on?

(Background: I am trying to use my website hosted on wix as a simple identity provider so my members can access a separate sveltekit app I am creating--without logging in again--on a separate server because I do not think I can create the app on the wix platform. Basically I just need the user id, but I would like to also ensure they are in fact authenticated on my Wix hosted site before granting access).
In multiple pages explaining single sign on, it is explained that when my browser requests a protected resource from a web server, the server can (if it is configured to do so) verify my identity via a separate identity provider. This is done via a redirect to the identify provider. If I am not authenticated by the identify provider, I am asked to authenticate (by entering username and password, or whatever).
Once I am authenticated (by logging in or by verifying the presence of a valid session id on the identify provider's server from a prior login), the identify provider then "redirects with token" or a "token can be passed to the original domain by a redirect" according to these web sites I have encountered.
But what does it mean to "redirect with token"? This conflicts with other reading I have done which points out that redirects cannot have authentication or other headers or data associated with them.
How does it come to pass that (1) the web server I made my original request from gets my token from the identify provider while at the same time (2) returning my requested resource to my browser instead of back to the identity provider's server?
"Redirect with token" is a common method used in single sign-on (SSO) systems to authenticate users. In this method, when a user tries to access a protected resource on a server, the server redirects the user's browser to the SSO login page, along with a token that identifies the resource being accessed and the server that is requesting authentication.
The user then enters their login credentials on the SSO login page. If the credentials are correct, the SSO system authenticates the user and sends them back to the original server, along with a token that indicates that the user has been authenticated. The server checks the token to confirm that the user has been authenticated, and if the token is valid, the user is granted access to the protected resource.
Redirecting with a token is a secure and efficient way to authenticate users across multiple servers, as it allows the servers to rely on the SSO system to authenticate users and eliminates the need for each server to store and manage its own set of login credentials.

Issue with SAML 2.0 single logout - How should IdP terminate SP sessions running in different user agents?

I'm having an issue with SAML 2.0 single logout.
I have a SAML 2.0 environment with an IdP (identity provider) and a web application acting as SP (service provider).
As user I start a web application session in an user agent (browser). The user is authenticated using the IdP.
In a different browser (running on the same client machine) I start another session as the same user in the same web application, i.e. in the same SP in terms of SAML.
Now I have two independent web application sessions where the same user is authenticated.
When I then perform a single logout initiated by the IdP in one of the browsers the IdP issues only one logout request which terminates the session that is running in that browser. The element of the logout request issued by the IdP equals the one that was sent by the IdP in the attribute SessionIndex of the AuthnStatement of the Assertion sent to the SP using that browser (user agent).
Wouldn't it actually be necessary for the IdP to send logout requests for all open sessions in order to achieve a true "single logout"?
Short answer: The SAML spec allows for Single Logout (SLO) to behave the way you want but a typical implementation isn't that sophisticated.
From SAML Profiles spec, section 4.4 (Single Logout Profile):
Once a principal has authenticated to an identity provider, the
authenticating entity may establish a session with the principal
(typically by means of a cookie, URL re-writing, or some other
implementation-specific means). The identity provider may subsequently
issue assertions to service providers or other relying parties, based
on this authentication event; a relying party may use this to
establish its own session with the principal. In such a situation, the
identity provider can act as a session authority and the relying
parties as session participants.
If the SLO sequence were to be initiated by one of the session participants, this whole discussion would be moot. The spec requires the session participant to identify the "shared" session being terminated via a unique ID (aka session index) that was originally sent to the session participant by the identity provider. As required by the spec, this ID will be different in your SP session #1 vs SP session #2.
...but when the SLO sequence is initiated by the IdP, your scenario is possible. Section 4.4.4.1 talks about the rules around issuing and processing <LogoutRequest>:
If the requester is a session participant, it MUST include at least
one <SessionIndex> element in the request. [...] If the requester is a
session authority (or acting on its behalf), then it MAY omit any such
elements to indicate the termination of all of the principal's
applicable sessions
Translation: if you could somehow tell the IdP to issue a <LogoutRequest> without a <SessionIndex> and your SP is sophisticated enough to correctly interpret such request and the SP can terminate all sessions for a particular user via its backend, then you've won.
In reality, the combination of conditions above is a very tall order. Out of the box, most IdPs will not issue a <LogoutRequest> without a <SessionIndex>. The very few SPs that even bother implementing SLO will not accept a request without a <SessionIndex>. In an extremely rare case where you'll be able to come up with a correct <LogoutRequest> and SP won't choke on it, you'll be very, very lucky if the SP correctly identifies all IdP-initiated sessions AND will be able to terminate them via the backend.

Is the web browser a security threat to my Delphi REST application?

I have created a REST application in Delphi using kbmMW middleware. It works really great, is fast, efficient etc. But in testing I've used both a Delphi client - which more closely simulates how it will be used in production (iOS, Android, Windows Tablet clients), and several different web browsers with manual REST uri entry.
The REST response format for the most part is JSON, but can be anything I want it to be. One of the REST calls I coded returns the session token.
In order to obtain the session token one has to request a resource using https; when the server sees that you have not yet authenticated it kicks back a 401 unauthorized, which tells the browser to force an authentication dialog, seeking username and password, or triggers the indy client to supply the pre-coded credentials.
I set the internal, kbmMW-wrapped Indy http component to use basic authentication (only inside ssl, of course); once authenticated the server generates a session-based token and returns the token to the client.
When I test this in my Delphi client, which uses Indy's TIdHTTP client, and I set it to use basic auth, set the username and the password, and initiate the request, the Indy components preserve the session token and apparently reuse it. I can call the function on the server that returns my session token, and the token remains the same for the lifetime of the session.
If I authenticate with the browser and the un/pw dialog, then call the function to return the session token, I am required to authenticate once using un/pw, but every subsequent request to retrieve the session token returns a different token every time.
My question is, does this mean that a web browser poses a potential security risk to my server? What governs how long a session lasts when the requesting client is a TIdHTTP vs. when the requesting client is a web browser (I've tested IE, Chrome, Firefox, Opera - all the same response)?
Why does a browser get a different token with every request, while an indy client reuses the same token over and over until expiration?
Does this mean that a potential hacker could compromise my server by utilizing a DDOS attack vector and creating sessions on my server until it runs out of memory?
I thought that the Indy http server would distinguish a requestor based on form vars like Referer, IP Address, Browser type etc. How can a browser, executing the same request over and over with the same IP, Referer etc. force a new login at the server side each time?
Is the browser caching the username and password and ignoring the token?
The server side authentication event only fires once with an indy client request, but fires with every request from a web browser, resubmitting the un/pw combo every time, and ignoring the token.
Should I set an ETag in the response header to the token so that the browser won't keep logging in and creating new sessions?
Help!

Identity Server 4 - Check iframe session issue - oidc client

I'm using OIDC Client in my angular application for authentication against identity server 4. Everything works fine until i hit sign out.
I've enabled monitor session (enabled by default) so that other browser can detect the sign out and i can log the user out in other tab of the same browser. When I sign out from one tab, the other tab makes a request to the identity server for silent refresh token and that get succeed. I'm expecting the other browser to signout as well. If i hit the F5 in the other tab then yes, it gets redirected to login again. but not automatically.
Update
to log out from other clients that share the same identity server frontChannel
, you can add an Iframe in your identity to notify your clients about the logout (oidc-client.js supports front-channel signout)
Front-channel server-side clients
To signout the user from the server-side client applications via the front-channel spec, the “logged out” page in IdentityServer must render an to notify the clients that the user has signed out. Clients that wish to be notified must have the FrontChannelLogoutUri configuration value set. IdentityServer tracks which clients the user has signed into, and provides an API called GetLogoutContextAsync on the IIdentityServerInteractionService (details). This API returns a LogoutRequest object with a SignOutIFrameUrl property that your logged out page must render into an .
Back-channel server-side clients
To signout the user from the server-side client applications via the back-channel spec, the SignOutIFrameUrl endpoint in IdentityServer will automatically trigger server-to-server invocation passing a signed sign-out request to the client. This means that even if there are no front-channel clients, the “logged out” page in IdentityServer must still render an to the SignOutIFrameUrl as described above. Clients that wish to be notified must have the BackChannelLogoutUri configuration value set.
Browser-based JavaScript clients
Given how the session management specification is designed, there is nothing special in IdentityServer that you need to do to notify these clients that the user has signed out. The clients, though, must perform monitoring on the check_session_iframe, and this is implemented by the oidc-client JavaScript library.
after that you can listen the event addUserSignedOut of oidc-client in all your clients and trigger signoutRedirect to logout your client
this._userManager.events.addUserSignedOut(() => {
this._userManager
.signoutRedirect()
.then(resp => {
console.log('Success');
})
.catch(err => {
console.log(err);
});
});
check this documentation for more details

GWT security one more time

I'm going to develop site accessible to anonymous and registered users. Planed security schema is similar to let's say YouTube and most of others "web 2.0" sites. Logged user will get access to more functions, more data etc. What is best approach to implement that?
I'm thinking about create simple service returning random session code to client, and adding session object to singleton application object. When user provide credential, I'll change parameter "logged" in his session object. Session token will be passed as one of parameters in every single request, and services will change their behavior if user is registered or not (i.e. there will be returned only "public" data, or restricted content only)
Is it good approach, or should I use something different?
There is nothing inherently different about GWT security, it is the same with JSP,PHP, ASP, ROR, etc..., that is web application security.
There is already a session mechanism on the server side, that generates secure random session cookies, use it. As a bonus, it handles session expiration and other things you would have to handle if you rolled your own.
You cannot trust ANYTHING the client sends you, so if you send the username or some kind of token from the client to the server (other than the user logging in), you are doing it wrong.
If your information has any value, force SSL on all connections.
Your implementation of the server calls should check the server session for the current user info, and determine if the user is authorized to perform the action. Again, your RPC information should not include any information about the user making the call, other than the session cookie that is sent automatically with the request headers. Anything you store, such as whether the user is logged in, should be in the server side session.
Of course, you need to do something on the client to present logged in and anonymous users with the proper user interface. But that is not security, only work to present a consistent interface. All the security is on the server side.