public async Task <IActionResult> EndSessionRequestAsync(string partyId) { logger.ScopeTrace("Up, OIDC End session request."); var oidcUpSequenceData = await sequenceLogic.GetSequenceDataAsync <OidcUpSequenceData>(remove : false); if (!oidcUpSequenceData.UpPartyId.Equals(partyId, StringComparison.Ordinal)) { throw new Exception("Invalid up-party id."); } logger.SetScopeProperty("upPartyId", oidcUpSequenceData.UpPartyId); var party = await tenantRepository.GetAsync <OidcUpParty>(oidcUpSequenceData.UpPartyId); logger.SetScopeProperty("upPartyClientId", party.Client.ClientId); ValidatePartyLogoutSupport(party); var postLogoutRedirectUrl = HttpContext.GetUpPartyUrl(party.Name, Constants.Routes.OAuthController, Constants.Endpoints.EndSessionResponse, partyBindingPattern: party.PartyBindingPattern); var rpInitiatedLogoutRequest = new RpInitiatedLogoutRequest { PostLogoutRedirectUri = postLogoutRedirectUrl, State = SequenceString }; var session = await sessionUpPartyLogic.GetSessionAsync(party); if (session != null) { try { if (!oidcUpSequenceData.SessionId.Equals(session.SessionId, StringComparison.Ordinal)) { throw new Exception("Requested session ID do not match up-party session ID."); } } catch (Exception ex) { logger.Warning(ex); } rpInitiatedLogoutRequest.IdTokenHint = session.IdToken; oidcUpSequenceData.SessionDownPartyLinks = session.DownPartyLinks; oidcUpSequenceData.SessionClaims = session.Claims; await sequenceLogic.SaveSequenceDataAsync(oidcUpSequenceData); } logger.ScopeTrace($"Up, End session request '{rpInitiatedLogoutRequest.ToJsonIndented()}'."); _ = await sessionUpPartyLogic.DeleteSessionAsync(session); await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantsAsync(oidcUpSequenceData.SessionId); securityHeaderLogic.AddFormActionAllowAll(); var nameValueCollection = rpInitiatedLogoutRequest.ToDictionary(); logger.ScopeTrace($"Up, End session request URL '{party.Client.EndSessionUrl}'."); logger.ScopeTrace("Up, Sending OIDC End session request.", triggerEvent: true); return(await nameValueCollection.ToRedirectResultAsync(party.Client.EndSessionUrl)); }
private async Task <IActionResult> LogoutRequestAsync <T>(SamlUpParty party, Saml2Binding <T> binding, SamlUpSequenceData samlUpSequenceData) { var samlConfig = await saml2ConfigurationLogic.GetSamlUpConfigAsync(party, includeSigningAndDecryptionCertificate : true); binding.RelayState = await sequenceLogic.CreateExternalSequenceIdAsync(); var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig); var session = await sessionUpPartyLogic.GetSessionAsync(party); if (session == null) { return(await LogoutResponseDownAsync(samlUpSequenceData)); } try { if (!samlUpSequenceData.SessionId.Equals(session.SessionId, StringComparison.Ordinal)) { throw new Exception("Requested session ID do not match up-party session ID."); } } catch (Exception ex) { logger.Warning(ex); } saml2LogoutRequest.SessionIndex = session.ExternalSessionId; samlUpSequenceData.SessionDownPartyLinks = session.DownPartyLinks; samlUpSequenceData.SessionClaims = session.Claims; await sequenceLogic.SaveSequenceDataAsync(samlUpSequenceData); var jwtClaims = samlUpSequenceData.SessionClaims.ToClaimList(); var nameID = jwtClaims?.Where(c => c.Type == JwtClaimTypes.Subject).Select(c => c.Value).FirstOrDefault(); var nameIdFormat = jwtClaims?.Where(c => c.Type == Constants.JwtClaimTypes.SubFormat).Select(c => c.Value).FirstOrDefault(); if (!nameID.IsNullOrEmpty()) { var prePartyName = $"{party.Name}|"; if (nameID.StartsWith(prePartyName, StringComparison.Ordinal)) { nameID = nameID.Remove(0, prePartyName.Length); } if (nameIdFormat.IsNullOrEmpty()) { saml2LogoutRequest.NameId = new Saml2NameIdentifier(nameID); } else { saml2LogoutRequest.NameId = new Saml2NameIdentifier(nameID, new Uri(nameIdFormat)); } } binding.Bind(saml2LogoutRequest); logger.ScopeTrace(() => $"SAML Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message); logger.ScopeTrace(() => $"Logout URL '{samlConfig.SingleLogoutDestination?.OriginalString}'."); logger.ScopeTrace(() => "Up, SAML Logout request.", triggerEvent: true); _ = await sessionUpPartyLogic.DeleteSessionAsync(party, session); await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantsAsync(samlUpSequenceData.SessionId); securityHeaderLogic.AddFormActionAllowAll(); if (binding is Saml2Binding <Saml2RedirectBinding> ) { return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync()); } else if (binding is Saml2Binding <Saml2PostBinding> ) { return(await(binding as Saml2PostBinding).ToActionFormResultAsync()); } else { throw new NotSupportedException(); } }
public async Task <IActionResult> FrontChannelLogoutAsync(string partyId) { logger.ScopeTrace(() => "Up, OIDC Front channel logout."); logger.SetScopeProperty(Constants.Logs.UpPartyId, partyId); var party = await tenantRepository.GetAsync <OidcUpParty>(partyId); logger.SetScopeProperty(Constants.Logs.UpPartyClientId, party.Client.ClientId); if (party.Client.DisableFrontChannelLogout) { return(new BadRequestResult()); } var queryDictionary = HttpContext.Request.Query.ToDictionary(); var frontChannelLogoutRequest = queryDictionary.ToObject <FrontChannelLogoutRequest>(); logger.ScopeTrace(() => $"Up, Front channel logout request '{frontChannelLogoutRequest.ToJsonIndented()}'.", traceType: TraceTypes.Message); frontChannelLogoutRequest.Validate(); if (party.Client.FrontChannelLogoutSessionRequired) { if (frontChannelLogoutRequest.SessionId.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(frontChannelLogoutRequest.SessionId), frontChannelLogoutRequest.GetTypeName()); } } var session = await sessionUpPartyLogic.GetSessionAsync(party); logger.ScopeTrace(() => "Up, Successful OIDC Front channel logout request.", triggerEvent: true); if (session != null) { if (party.Client.FrontChannelLogoutSessionRequired) { if (!party.Issuers.Where(i => i == frontChannelLogoutRequest.Issuer).Any()) { throw new Exception("Incorrect issuer."); } if (session.ExternalSessionId != frontChannelLogoutRequest.SessionId) { throw new Exception("Incorrect session id."); } } var _ = await sessionUpPartyLogic.DeleteSessionAsync(party, session); await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantsAsync(session.SessionId); if (!party.DisableSingleLogout) { var allowIframeOnDomains = new List <string>().ConcatOnce(party.Client.AuthorizeUrl?.UrlToDomain()).ConcatOnce(party.Client.EndSessionUrl?.UrlToDomain()).ConcatOnce(party.Client.TokenUrl?.UrlToDomain()); (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, null, session.DownPartyLinks, session.Claims, allowIframeOnDomains, hostedInIframe : true); if (doSingleLogout) { return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData)); } } } return(new OkResult()); }
public async Task <IActionResult> FrontChannelLogoutAsync(string partyId) { logger.ScopeTrace("Up, OIDC Front channel logout."); logger.SetScopeProperty("upPartyId", partyId); var party = await tenantRepository.GetAsync <OidcUpParty>(partyId); logger.SetScopeProperty("upPartyClientId", party.Client.ClientId); if (party.Client.DisableFrontChannelLogout) { return(new BadRequestResult()); } var queryDictionary = HttpContext.Request.Query.ToDictionary(); var frontChannelLogoutRequest = queryDictionary.ToObject <FrontChannelLogoutRequest>(); logger.ScopeTrace($"Up, Front channel logout request '{frontChannelLogoutRequest.ToJsonIndented()}'."); frontChannelLogoutRequest.Validate(); if (party.Client.FrontChannelLogoutSessionRequired) { if (frontChannelLogoutRequest.SessionId.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(frontChannelLogoutRequest.SessionId), frontChannelLogoutRequest.GetTypeName()); } } var session = await sessionUpPartyLogic.GetSessionAsync(party); logger.ScopeTrace("Up, Successful OIDC Front channel logout request.", triggerEvent: true); if (session != null) { if (party.Client.FrontChannelLogoutSessionRequired) { if (!session.Claims.Where(c => c.Claim == JwtClaimTypes.Issuer && c.Values.Where(v => v == frontChannelLogoutRequest.Issuer).Any()).Any()) { throw new Exception("Incorrect issuer."); } if (session.ExternalSessionId != frontChannelLogoutRequest.SessionId) { throw new Exception("Incorrect session id."); } } var _ = await sessionUpPartyLogic.DeleteSessionAsync(session); await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantsAsync(session.SessionId); if (!party.DisableSingleLogout) { (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, null, session.DownPartyLinks, session.Claims, redirectAfterLogout : false); if (doSingleLogout) { securityHeaderLogic.AddAllowIframeOnUrls(new [] { party.Client.AuthorizeUrl, party.Client.EndSessionUrl }); return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData)); } } } return(new OkResult()); }