private static CommandResult HandleRequest(UnbindResult unbindResult, IOptions options) { var request = Saml2LogoutRequest.FromXml(unbindResult.Data); var idp = options.IdentityProviders[request.Issuer]; if (options.SPOptions.SigningServiceCertificate == null) { throw new ConfigurationErrorsException(string.Format(CultureInfo.InvariantCulture, "Received a LogoutRequest from \"{0}\" but cannot reply because single logout responses " + "must be signed and there is no signing certificate configured. Looks like the idp is " + "configured for Single Logout despite Saml2 not exposing that functionality in the metadata.", request.Issuer.Id)); } if (idp.SingleLogoutServiceResponseUrl == null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Received a LogoutRequest from \"{0}\" but cannot reply because on logout endpoint is " + "configured on the idp. Set a SingleLogoutServiceUrl if the idp is configured manually, " + "or check that the idp metadata contains a SingleLogoutService endpoint.", idp.EntityId.Id)); } var response = new Saml2LogoutResponse(Saml2StatusCode.Success) { DestinationUrl = idp.SingleLogoutServiceResponseUrl, SigningCertificate = options.SPOptions.SigningServiceCertificate, SigningAlgorithm = idp.OutboundSigningAlgorithm, InResponseTo = request.Id, Issuer = options.SPOptions.EntityId, RelayState = unbindResult.RelayState }; options.SPOptions.Logger.WriteInformation("Got a logout request " + request.Id + ", responding with logout response " + response.Id); var result = Saml2Binding.Get(idp.SingleLogoutServiceBinding).Bind(response); result.TerminateLocalSession = true; return(result); }
public static CommandResult InitiateLogout(HttpRequestData request, Uri returnUrl, IOptions options, bool terminateLocalSession) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } string idpEntityId = null; Claim sessionIndexClaim = null; if (request.User != null) { idpEntityId = request.User.FindFirst(Saml2ClaimTypes.LogoutNameIdentifier)?.Issuer; sessionIndexClaim = request.User.FindFirst(Saml2ClaimTypes.SessionIndex); } var knownIdp = options.IdentityProviders.TryGetValue(new EntityId(idpEntityId), out IdentityProvider idp); options.SPOptions.Logger.WriteVerbose("Initiating logout, checking requirements for federated logout" + "\n Issuer of LogoutNameIdentifier claim (should be Idp entity id): " + idpEntityId + "\n Issuer is a known Idp: " + knownIdp + "\n Session index claim (should have a value): " + sessionIndexClaim + "\n Idp has SingleLogoutServiceUrl: " + idp?.SingleLogoutServiceUrl?.OriginalString + "\n There is a signingCertificate in SPOptions: " + (options.SPOptions.SigningServiceCertificate != null) + "\n Idp configured to DisableOutboundLogoutRequests (should be false): " + idp?.DisableOutboundLogoutRequests); CommandResult commandResult; if (idpEntityId != null && knownIdp && sessionIndexClaim != null && idp.SingleLogoutServiceUrl != null && options.SPOptions.SigningServiceCertificate != null && !idp.DisableOutboundLogoutRequests) { var logoutRequest = idp.CreateLogoutRequest(request.User); options.Notifications.LogoutRequestCreated(logoutRequest, request.User, idp); commandResult = Saml2Binding.Get(idp.SingleLogoutServiceBinding) .Bind(logoutRequest, options.SPOptions.Logger, options.Notifications.LogoutRequestXmlCreated); commandResult.RelayState = logoutRequest.RelayState; commandResult.RequestState = new StoredRequestState( idp.EntityId, returnUrl, logoutRequest.Id, null); if (!options.SPOptions.Compatibility.DisableLogoutStateCookie) { commandResult.SetCookieName = StoredRequestState.CookieNameBase + logoutRequest.RelayState; var urls = new Saml2Urls(request, options); commandResult.SetCookieSecureFlag = urls.LogoutUrl.IsHttps(); } commandResult.TerminateLocalSession = terminateLocalSession; options.SPOptions.Logger.WriteInformation("Sending logout request to " + idp.EntityId.Id); } else { commandResult = new CommandResult { HttpStatusCode = HttpStatusCode.SeeOther, Location = returnUrl, TerminateLocalSession = terminateLocalSession }; options.SPOptions.Logger.WriteInformation( "Federated logout not possible, redirecting to post-logout" + (terminateLocalSession ? " and clearing local session" : "")); } return(commandResult); }