Closed kevinmcody closed 5 months ago
There are quite a few things required for logout to work. One (unexpected) thing is that there must be a service certificate configure on the SP.
The full check is logged if you switch the log level up to Verbose: https://github.com/Sustainsys/Saml2/blob/594e3b311734c26c7bd87e8f78c176507c340ef7/Sustainsys.Saml2/WebSSO/LogOutCommand.cs#L174-L180
Thanks for that! You were right - it was the Signing Certificate. I fixed this by adding the following to DynamicProviderUtils.Saml2ConfigureOptions.cs line 42:
options.SPOptions.ServiceCertificates.Add(new X509Certificate2("Sustainsys.Saml2.Tests.pfx"));
Also, my previous modification of capturing the additional claims was not quite correct. I was re-creating the claims, thus changing the issuer, which the logout checks also did not like. CaptureExternalLoginContext method in the ExterlanLogin/Callback page now looks like:
// if the external login is OIDC-based, there are certain things we need to preserve to make logout work
// this will be different for WS-Fed, SAML2p or other protocols
private void CaptureExternalLoginContext(AuthenticateResult externalResult, List<Claim> localClaims, AuthenticationProperties localSignInProps)
{
// if the external system sent a session id claim, copy it over
// so we can use it for single sign-out
var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId);
if (sid != null)
{
localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value));
}
var nameIdentifierClaim = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
if (nameIdentifierClaim != null)
{
localClaims.Add(nameIdentifierClaim);
}
var logoutNameIdentifierClaim = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == "http://Sustainsys.se/Saml2/LogoutNameIdentifier");
if (logoutNameIdentifierClaim != null)
{
localClaims.Add(logoutNameIdentifierClaim);
}
var sessionIndexClaim = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == "http://Sustainsys.se/Saml2/SessionIndex");
if (sessionIndexClaim != null)
{
localClaims.Add(sessionIndexClaim);
}
// if the external provider issued an id_token, we'll keep it for signout
var idToken = externalResult.Properties.GetTokenValue("id_token");
if (idToken != null)
{
localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } });
}
}
Side note: I did NOT have to manually set all the properties on the IdentityProvider. Using LoadMetadata=true
caused them to be read correctly from the metadata xml.
Sustainsys.Saml2.AspNetCore2 v 2.9.1
I started from the DuendeDynamicProviders sample found here:
https://github.com/Sustainsys/Saml2.Sample
I am trying to get single signout working. After calling the Signout method in the Logout page, like so:
I see the following in the log:
I did some googling, and most solutions involved making sure the following claims were carried over from the external user to the local:
I accomplished this by modifying the CaptureExternalLoginContext method in the ExterlanLogin/Callback page, like so:
I also saw some people claiming you had to explicitly set certain fields on the Sustainsys.Saml2.IdentityProvider, so I modified DynamicProviderUtils.Saml2ConfigureOptions.cs line 47 like so:
I'm very new to identity management in general. Any ideas what to try next?