SSO credentials being retained on website logout

I have a asp.net website with a logout button that redirects to logout.aspx… which is actually an HTTP Handler and contains the following code in the ProcessRequest method…


Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
Try
If ctx.Authentication_SingleSignOn Then
Dim ProviderID As String = ctx.siteConfigDef(“sso_provider_id”, “”)
If SAMLServiceProvider.CanSLO(ProviderID) Then
SAMLServiceProvider.InitiateSLO(context.Response, Nothing, Nothing, ProviderID)
End If
End If
Catch ex As Exception
End Try

context.Session.Clear()
context.Session.Abandon()
context.Items.Clear()
context.Request.Cookies.Remove(“ASP.NET_SessionId”)
FormsAuthentication.SignOut()
context.Response.Redirect(“login.aspx”, True)
End Sub


In the top of the login.aspx page I have this…


If ctx.Authentication_SingleSignOn Then
Dim ProviderID As String = ctx.siteConfig(“sso_provider_id”)
If String.IsNullOrEmpty(ProviderID) Then
ctx.accessDenied(“The system is not configured correctly for Single Sign On”)
Return
End If

Try
If SAMLServiceProvider.CanSLO(ProviderID) Then
SAMLServiceProvider.InitiateSLO(ctx.current.Response, Nothing, Nothing, ProviderID)
End If
Catch ex As Exception
End Try

SAMLServiceProvider.InitiateSSO(ctx.current.Response, Nothing, ProviderID)
Return
End If


What’s happening is that when the user presses the logout button, it’s going through the logout code, but when it redirects to the login page, it’s redirecting to the SSO provider, which doesn’t prompt for credentials and just redirects back to our side to the start page… SSO credentials aren’t being cleared on logout. Closing and reopening the browser will prompt for the credentials on the provider site as expected.

I notice that even after logout, the ASP_NET.SessionId is set to the same value once it hits the login page.

Am I not doing something I should be ?
Regards
Adrian

Hi Adrian,
When you call SAMLServiceProvider.InitiateSLO it will return a 302 redirect HTTP response with the logout request encoded as a query string parameter.
At the end of the ProcessRequest you’re calling context.Response.Redirect to redirect to your login page. This will override the redirect for sending the logout request.
Your logic should be to only redirect to the login page if you haven’t called SAMLServiceProvider.InitiateSLO.
Similarly, in your login page don’t call SAMLServiceProvider.InitiateSSO if you’ve called SAMLServiceProvider.InitiateSLO as the sending of the logout request will be overridden by the sending of the SAML authn request.


[quote]
ComponentSpace - 6/4/2020
Hi Adrian,
When you call SAMLServiceProvider.InitiateSLO it will return a 302 redirect HTTP response with the logout request encoded as a query string parameter.
At the end of the ProcessRequest you're calling context.Response.Redirect to redirect to your login page. This will override the redirect for sending the logout request.
Your logic should be to only redirect to the login page if you haven't called SAMLServiceProvider.InitiateSLO.
Similarly, in your login page don't call SAMLServiceProvider.InitiateSSO if you've called SAMLServiceProvider.InitiateSLO as the sending of the logout request will be overridden by the sending of the SAML authn request.


[/quote]

Thanks for the reply,

I've made the following changes..

in the logoff.aspx...

Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
Dim UsedSLO As Boolean = False
Try
If ctx.Authentication_SingleSignOn Then
Dim ProviderID As String = ctx.siteConfigDef("sso_provider_id", "")
If SAMLServiceProvider.CanSLO(ProviderID) Then
SAMLServiceProvider.InitiateSLO(context.Response, Nothing, Nothing, ProviderID)
UsedSLO = True
End If
End If
Catch ex As Exception
End Try

context.Session.Clear()
context.Session.Abandon()
context.Items.Clear()
context.Request.Cookies.Remove("ASP.NET_SessionId")
context.Request.Cookies.Add(New HttpCookie("ASP.NET_SessionId", ""))
FormsAuthentication.SignOut()

If Not UsedSLO Then
context.Response.Redirect("~/secure/login.aspx", True)
End If
End Sub


and in the login.aspx..

Try
If SAMLServiceProvider.CanSLO(ProviderID) Then
SAMLServiceProvider.InitiateSLO(ctx.current.Response, Nothing, Nothing, ProviderID)
Else
SAMLServiceProvider.InitiateSSO(ctx.current.Response, Nothing, ProviderID)
End If
Catch ex As Exception
ctx.accessDenied("There is a problem signing you into the system, please contact support")
End Try


This does beg the question though, if SLO isn't supported, what do you need to remove to have InitiateSSO not think you're already logged in at the remote site ?

In the logout, I know in the sample you have the FormsAuthentication.SignOut() before calling the SLO, but I didn't want to clear out anything that might mean the SLO didn't have enough info to know who we are when calling SLO.

Regards
Adrian

Normally you would establish a local authentication session once SSO completes (eg call FormsAuthentication.SetAuthCookie). You would only call SAMLServiceProvider.InitiateSSO if you don’t have a local authentication session.

However, if you’ve already called SAMLServiceProvider.InitiateSSO/SAMLServiceProvider.ReceiveSSO you can call this sequence again at any stage. If the user is still logged into the identity provider, they won’t be prompted to login again.

[quote]
ComponentSpace - 6/4/2020
Normally you would establish a local authentication session once SSO completes (eg call FormsAuthentication.SetAuthCookie). You would only call SAMLServiceProvider.InitiateSSO if you don't have a local authentication session.

However, if you've already called SAMLServiceProvider.InitiateSSO/SAMLServiceProvider.ReceiveSSO you can call this sequence again at any stage. If the user is still logged into the identity provider, they won't be prompted to login again.
[/quote]


Here's what I have at the moment.. in pseudocode assuming no errors etc

Login Page..

IF usingSSO THEN
IF canSLO THEN
InitiateSLO
ELSE
InitiateSSO
END IF
ELSE
normal site login
END IF


The reason I put the SLO part in the login page is that when the session times out and it auto-redirects to the login page, I wanted the user to have to login again as normal, but I'm now thinking this will just annoy them so I've asked the vendor whether it should just go back to their start page.. so the code would then just be simply..

IF usingSSO THEN
InitiateSSO
ELSE
normal site login
END IF


SSO Page (where identity provider site redirects to after their login)

ReceiveSSO
IF valid user
FormsAuthentication.SetAuthCookie
redirect to users start page
ELSE
oops
END IF


Logout handler

IF usingSSO THEN
IF canSLO THEN
InitiateSLO
END IF
END IF

destroy the session
FormsAuthentication.SignOut
IF SLO not called
redirect to login page
END IF


I'm still not sure what to do in the logout part if SLO isn't used.. what do I have to clear locally to ensure the user will be prompted for an identity provider login ?

Thanks
Adrian

If the identity provider doesn’t support SLO but you want the user logged out from the identity provider, the only other option is to prompt the user to close the browser.

[quote]
ComponentSpace - 6/5/2020
If the identity provider doesn't support SLO but you want the user logged out from the identity provider, the only other option is to prompt the user to close the browser.
[/quote]

ok thanks.. I'm still curious about what is sent to the identify provider to identify who the current user is... i.e. how would you put the current browser into a state that was the same as closing and re-opening the browser again ?

The logout request includes the name identifier and session index. These should uniquely identify the logged in user.

However, in most use cases the logout request is sent using the HTTP-Redirect or HTTP-Post binding. This means the message is sent via the browser and therefore it’s in the context of the user’s browser session. The identity provider knows who the current user is via whatever cookies it uses.

[quote]
ComponentSpace - 6/5/2020
The logout request includes the name identifier and session index. These should uniquely identify the logged in user.

However, in most use cases the logout request is sent using the HTTP-Redirect or HTTP-Post binding. This means the message is sent via the browser and therefore it's in the context of the user's browser session. The identity provider knows who the current user is via whatever cookies it uses.
[/quote]

ok thanks, I've made the changes, it's going to up to the vendor as to when they test it on their system.

You’re welcome. Let us know if there are any issues.

[quote]
ComponentSpace - 6/6/2020
You're welcome. Let us know if there are any issues.
[/quote]
Got them to test the site again and it's still not working.
What is truly odd is that they close the browser and re-open it, go to the site and it auto logs them in.. i.e. the identify provider doesn't prompt for a login.
completely lost now.
Have asked for credentials and a redirect to my dev site to see what it's doing.


[quote]
ComponentSpace - 6/6/2020
You're welcome. Let us know if there are any issues.
[/quote]
Got them to test the site again and it's still not working.
What is truly odd is that they close the browser and re-open it, go to the site and it auto logs them in.. i.e. the identify provider doesn't prompt for a login.
completely lost now.
Have asked for credentials and a redirect to my dev site to see what it's doing.


[/quote]
Think my unfamiliarity with sso has gotten the better of me again !!

I assume that the PartnerIdentityProviderConfiguration.SingleLogoutServiceUrl needs to be set else CanSLO will return false ?
I was making an assumption that the logout would be part of the SSO url just with different parameters.

They've now provided a url for the SLO. Is there anything else I need to set ?

What should I do if they've just closed the browser and re-open it.. can I call the InitiateSLO then to force them to re-login every time they go to the login page ?

Sorry for being a pain
Adrian




Often the SSO and SLO URLs are different but this isn’t always the case. They should have provided you with these URLs which it sounds like they’re now done. That should be all you need. I recommend signing the SAML logout messages. In your partner identity provider configuration, set SignLogoutRequest and SignLogoutResponse to true.

If the browser is closed and re-opened, all session cookies will be deleted. Typically this means any authentication cookies will be deleted and so the user will not be logged in. The SAML_SessionId cookie is deleted as well so you won’t be able to call InitiateSLO. However, they should be logged out from the identity provider so when you call InitiateSSO they’ll be prompted to login.

[quote]
ComponentSpace - 6/8/2020
Often the SSO and SLO URLs are different but this isn't always the case. They should have provided you with these URLs which it sounds like they're now done. That should be all you need. I recommend signing the SAML logout messages. In your partner identity provider configuration, set SignLogoutRequest and SignLogoutResponse to true.

If the browser is closed and re-opened, all session cookies will be deleted. Typically this means any authentication cookies will be deleted and so the user will not be logged in. The SAML_SessionId cookie is deleted as well so you won't be able to call InitiateSLO. However, they should be logged out from the identity provider so when you call InitiateSSO they'll be prompted to login.
[/quote]

Ok, I've set the two signlogoutrequest and signlogoutresponse to true and will let then try it tomorrow.. would be easier if they'd just give me a test configuration to use at the provider end, but hey ho.

They say that closing the browser does not clear the login, and that there are only two cookies set, the sessionID and the one for authentication.. so no clue what's going on there.

There is an optional ForceAuthn flag on the SAML authn request that’s sent to the identity provider when you call SAMLServiceProvider.InitiateSSO. ForceAuthn requests that the IdP authenticate the user even if they’re already authenticated. The problem with this flag is that some IdPs ignore it.

You can either specify this flag through the partner identity provider configuration (ForceAuthn=“true”) or call the SAMLServiceProvider.InitiateSSO overload that takes an SSOOptions and set SSOOptions.ForceAuthn to true.

[quote]
ComponentSpace - 6/8/2020
There is an optional ForceAuthn flag on the SAML authn request that's sent to the identity provider when you call SAMLServiceProvider.InitiateSSO. ForceAuthn requests that the IdP authenticate the user even if they're already authenticated. The problem with this flag is that some IdPs ignore it.

You can either specify this flag through the partner identity provider configuration (ForceAuthn="true") or call the SAMLServiceProvider.InitiateSSO overload that takes an SSOOptions and set SSOOptions.ForceAuthn to true.
[/quote]

Many thanks, will let you know

Thanks.

If you run into issues, please enable SAML trace and send the generated log file as an email attachment to support@componentspace.com mentioning your forum post.

https://www.componentspace.com/Forums/17/Enabing-SAML-Trace

[quote]
ComponentSpace - 6/8/2020
Thanks.

If you run into issues, please enable SAML trace and send the generated log file as an email attachment to support@componentspace.com mentioning your forum post.

https://www.componentspace.com/Forums/17/Enabing-SAML-Trace
[/quote]

May have found something.. had them use one browser to login, closed that browser and then try in a different browser which then proceeded to log them in without prompting for credentials.. in IIS session state, they have the "Use hosting identity for impersonation" checked on.. would this cause the behaviour we're seeing ?

I don’t think so. The “Use hosting identity for impersonation” ensures IIS can read and write session state data.

If the authentication session persists then perhaps they’re using a persistent cookie. The identity provider should be able to confirm this. They should also be able to confirm whether they support the ForceAuthn flag.

As the service provider, there are limits to what you can do in terms of the authentication session at the identity provider.

If the browser isn’t closed, does SLO work and is the user prompted to login again on the next SSO?

Is your only concerned related to when the browser is closed?

[quote]
ComponentSpace - 6/9/2020
I don't think so. The "Use hosting identity for impersonation" ensures IIS can read and write session state data.

If the authentication session persists then perhaps they're using a persistent cookie. The identity provider should be able to confirm this. They should also be able to confirm whether they support the ForceAuthn flag.

As the service provider, there are limits to what you can do in terms of the authentication session at the identity provider.

If the browser isn't closed, does SLO work and is the user prompted to login again on the next SSO?

Is your only concerned related to when the browser is closed?
[/quote]
I am still trying to find out exactly what is happening.. at the moment I've just changed the logout button to redirect directly to the logout url.. still waiting to hear on that one.

They are using a computer that's logged into a network.. the computer is available to any of the employees in the branch. A user goes to the computer and clicks on a link which opens the site, they get redirected to the idp and have to enter their credentials and are then taken to the site where they can view their details. They then close the browser and walk away. Another user walks up, opens the browser and they see the first persons record because the idp doesn't ask them for credentials.

Most of this I'm getting third hand because even our vendor doesn't have the ability to log into the customer website.

I've asked the vendor to turn on the verbose logging and see what we get back.. I'm still waiting to be able to use their test idp to try it from my dev site, but nothing yet.