Log a user out of a SP but not IDP - saml

Is it possible to log a user out of an application that uses SAML authentication, but keep them logged into the IDP so they can continue to access other service providers?
I want to be able to log a user out of an application, and have them authenticate when they return to the application without logging them out of the IDP (i.e. I don't want to use single sign out). Is this possible with SAML?

There is no standard way to exclude termination of the IDP session when performing Single Logout. Also termination of a session with an individual session participant (a single Service Provider) while keeping the others opened is explicitly out of scope of the SAML 2.0 Single Logout profile (see saml-profiles-2.0-os.pdf, lines 1139-1143). So that's not the way to go.
But there's another solution. You can use local logout at your service provider (e.g. simply invalidate local HTTP session) and combine it with attribute ForceAuthn when sending the AuthnRequest to the IDP (see saml-core-2.0-os, line 2042). Setting the ForceAuthn attribute to true forces the Identity Provider to authenticate user even in case when there's an existing IDP session.
The whole flow could look like this:
User accesses SP and is required to authenticate
SP sends an SAML 2.0 AuthnRequest to IDP and sets the ForceAuthn flag to true
IDP forces user to authenticate and responds to the SP
SP creates a local session after validating the response
User logs-out of the SP application which terminates only the local session and doesn't interfere with the IDP session or sessions at other SPs
Setting the ForceAuthn flag to true effectively disables single sign-on, so you might want to use some SP-side logic determining whether to use the flag or not.
An example of a valid request with the flag set follows:
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest AssertionConsumerServiceIndex="0"
AttributeConsumingServiceIndex="myServiceID"
Destination="https://idp.ssocircle.com:443/sso/SSOPOST/metaAlias/ssocircle"
ForceAuthn="true" ID="a228aje276h0id1g48eihj5gfj9h8bi"
IsPassive="false" IssueInstant="2014-04-11T22:07:05.438Z"
Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:test:sp</saml2:Issuer>
</saml2p:AuthnRequest>

Related

SSO - Multple SP with only one IdP (ADFS)

I have two service providers set up with one IdP and users are required to be authenticated twice to access both services at the same time. From my point of view, this is not "SSO" and I am thinking that there might have been settings done incorrectly and I would like to see if the community here can provide me with directions and/or possible solutions.
Just a thought - the behaviour for the authentication on each service looks valid as I understand that IdP is required to send signed SAML assertions to the providers in order to access the services. However, because I only have one IdP, can I not be authenticated just once and be able to access all the services?
Any suggestion is appreciated. Thanks.
Typically in this scenario the user would authenticate once to the IdP when the first SP SSO's to it. There would be no authentication at the IdP when the second SP SSO's to it as there's already an authentication session at the IdP for the user.
However, there might be use cases where you want the user to be authenticated at the IdP even if they already have an authentication session. The SP can set the ForceAuthn flag in the SAML authn request sent to the IdP. This requests that the IdP authenticates the user regardless of whether or not they already have an authentication session.
ADFS also has a configuration option for relying parties (SPs) to always require authentication. Take a look at the AlwaysRequireAuthentication flag.
https://learn.microsoft.com/en-us/powershell/module/adfs/set-adfsrelyingpartytrust?view=windowsserver2022-ps

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.

SAML: is it possible to force user to go through login process even when user has an IDP session

In SAML, is it possible to force the user to go through idp's login process everytime even when the user has an active idp session?
To make a concrete example here:
Let's call my application "SP"
I use SSOCirecle as idp and I use POST and redirect (SP initiated).
To test, I will first login to SSOCircle to get an active idp session. Then when I try going to SP, I should be redirected to idp.
Normally, since I already have an active idp session, the idp will see "oh, you already being authenticated before, you can go directly to SP!"
But I don't want that, I want idp to force the user to enter credential everytime, maybe by either (I guess)
ignore active idp session
don't create an idp session
I want to knwo whether this is doable.
Yes, the SP can send a flag ForceAuthn to the Idp in the AuthnRequest to require a new authentication instead of reusing an existing session.
As always with SAML2, you can't expect all Idps to support everything. Yyou have to test if your Idp supports the ForceAuthn flag.

How to maintain state parameter in Identity Provider (IdP) initiated SAML sso?

I started with Service Provider based SSO for SAML. Since the user had to enter his email before proceeding with the login, a state variable was initiated and passed on to the SSO. It comes back through the callback URL and hence was check again for the sanity purpose. It protected against CSRF attacks.
Now IdP initiated SSO doesn't allow me to set state variable at all. Login starts at Identity Provider and only an auth token is provided to the app. I do not know which user is authenticating from the beginning. If I remove the state variable check, it could trigger a CSRF attack as well.
I am also using omniauth in rails which makes state variable a compulsory param and SSO provider is auth0.
What is the way to attach state variable to IdP initiated SSO solutions?
The de-facto standard value of the RelayState parameter in IDP-init-SSO SAML flows is the URL that you want to send the user to after successful validation of the SAML assertion at the SP. That would work for the vast majority of SAML deployments out there.
However, that mechanism indeed does not protect against CSRF attacks this is why the spec is silent on the value of RelayState in IDP-init-SSO and leaves it open to agree on mechanisms between IDP and SP to prevent CSRF through the value of that parameter. One such mechanism would be to use a signed value in the RelayState but as said, nothing is standardized and it would thus depend on a bi-lateral agreement between IDP and SP which does not scale.
In summary: send the value of the URL that you want the user to go to as the RelayState value in the "unsolicited" SAML Response that you send to the SP. How you get the IDP's SAML stack to do that is implementation specific. For Auth0 you can read on this at: https://auth0.com/docs/protocols/saml/saml-configuration#idp-initiated-sso, and in your case it would look like:
https://{accountname}.auth0.com/samlp/YOUR_CLIENT_ID?RelayState=http://FINAL_DESTINATION_URL

Is this SAML SSO implementation correct?

I have a site say www.e1.com. www.e1.com is Service Provider. Whenever I click a service in it, I am redirected to a Identity provider, say www.e2.com. Before that,In service provider(www.e1.com) I will check if any cookie is set for the user. For the first time there will be no cookie so it will send empty SessionId value. Thus, I am sending a SAML Request to www.e2.com along with with no id(as no cookie is set. Cookie contains Id)
Now in www.e2.com i.e.In identity provider,I will check whether www.e1.com has sent any Id value. If it is null I will create a session Id and store it in database(In www.e2.com). Then I will redirect browser to my Authentication page where User's Name and password will be asked and accordingly he will be authenticated. If the authentication is successfull, I will redirect browser to Service provider(www.e1.com) with SAML Response which contains session Id.
Now in Service provider the SessionId value will be stored in Cookie and browser will be redirected to consumer service page(service page the user wants to access).
Now if the same user wants to access some other service from same Service provider
(within the session), the browser will obviously send the SessionId in Cookie along with the request SAML. Identity Provider will check the SessionId value in his database, If its there in its database then it will give direct access to service to user without entering login credential as the user is already authenticated for the session.
Is this the right way to achieve Single Sign On with SAML? or
If this method has flaws, Can you explain those flaws?
Thanks in advance :)
Your understanding is not quite correct :)
Here is the flow:
User tries to access a protected resource on the SP. SP checks if the
user has a local (and authenticated session). If not it generates a
SAML <AuthRequest> which includes a random id. The SP then redirects
the user to the IDP with this AuthnRequest.
The IDP will check if the user has a local authenticated session. If
not it will authenticate the user The IDP will send an AuthResponse
back to the SP with an inReplyTo attribute which matches the id sent by
the SP in it's AuthnRequest
The SP will then create a local session. Subsequent requests to the
SP will not involve the IDP unless a) The session expires or b) the SP
receives a SingleLogout message from the IDP