private async Task <IActionResult> LogoutResponseAsync <T>(Saml2Configuration samlConfig, string inResponseTo, string relayState, string singleLogoutResponseUrl, Saml2Binding <T> binding, Saml2StatusCodes status, string sessionIndex) { binding.RelayState = relayState; var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig) { InResponseTo = new Saml2Id(inResponseTo), Status = status, Destination = new Uri(singleLogoutResponseUrl), SessionIndex = sessionIndex }; binding.Bind(saml2LogoutResponse); logger.ScopeTrace(() => $"SAML Single Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message); logger.ScopeTrace(() => $"Single logged out response URL '{singleLogoutResponseUrl}'."); logger.ScopeTrace(() => "Down, SAML Single Logout response.", triggerEvent: true); await sequenceLogic.RemoveSequenceDataAsync <SamlDownSequenceData>(); securityHeaderLogic.AddFormActionAllowAll(); if (binding is Saml2Binding <Saml2RedirectBinding> ) { return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync()); } if (binding is Saml2Binding <Saml2PostBinding> ) { return(await(binding as Saml2PostBinding).ToActionFormResultAsync()); } else { throw new NotSupportedException(); } }
private async Task <IActionResult> LogoutResponseAsync <T>(Saml2Configuration samlConfig, string inResponseTo, string relayState, string loggedOutUrl, Saml2Binding <T> binding, Saml2StatusCodes status, string sessionIndex = null) { binding.RelayState = relayState; var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig) { InResponseTo = new Saml2Id(inResponseTo), Status = status, Destination = new Uri(loggedOutUrl), SessionIndex = sessionIndex }; binding.Bind(saml2LogoutResponse); logger.ScopeTrace($"SAML Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'."); logger.ScopeTrace($"Logged out url '{loggedOutUrl}'."); logger.ScopeTrace("Down, SAML Logout response.", triggerEvent: true); await sequenceLogic.RemoveSequenceDataAsync <SamlDownSequenceData>(); await formActionLogic.RemoveFormActionSequenceDataAsync(); if (binding is Saml2Binding <Saml2RedirectBinding> ) { return(await Task.FromResult((binding as Saml2RedirectBinding).ToActionResult())); } if (binding is Saml2Binding <Saml2PostBinding> ) { return(await Task.FromResult((binding as Saml2PostBinding).ToActionResult())); } else { throw new NotSupportedException(); } }
private async Task <IActionResult> SingleLogoutRequestAsync <T>(SamlDownParty party, Saml2Binding <T> binding, IEnumerable <Claim> claims) { var samlConfig = saml2ConfigurationLogic.GetSamlDownConfig(party, true); claims = await claimTransformationsLogic.Transform(party.ClaimTransforms?.ConvertAll(t => (ClaimTransform)t), claims); var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig) { NameId = samlClaimsDownLogic.GetNameId(claims), Destination = new Uri(party.SingleLogoutUrl), SessionIndex = samlClaimsDownLogic.GetSessionIndex(claims) }; binding.RelayState = SequenceString; binding.Bind(saml2LogoutRequest); logger.ScopeTrace($"SAML Single Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'."); logger.ScopeTrace($"Single logged out URL '{party.SingleLogoutUrl}'."); logger.ScopeTrace("Down, SAML Single Logout request.", triggerEvent: true); securityHeaderLogic.AddFormAction(party.SingleLogoutUrl); if (binding is Saml2Binding <Saml2RedirectBinding> ) { return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync()); } if (binding is Saml2Binding <Saml2PostBinding> ) { return(await(binding as Saml2PostBinding).ToActionFormResultAsync()); } else { throw new NotSupportedException(); } }
private async Task <IActionResult> AuthnResponseAsync <T>(Saml2Configuration samlConfig, string inResponseTo, string relayState, string acsUrl, Saml2Binding <T> binding, Saml2StatusCodes status, SamlDownParty party = null, IEnumerable <Claim> claims = null) { binding.RelayState = relayState; var saml2AuthnResponse = new FoxIdsSaml2AuthnResponse(settings, samlConfig) { InResponseTo = new Saml2Id(inResponseTo), Status = status, Destination = new Uri(acsUrl), }; if (status == Saml2StatusCodes.Success && party != null && claims != null) { claims = await claimTransformationsLogic.Transform(party.ClaimTransformations?.ConvertAll(t => (ClaimTransformation)t), claims); saml2AuthnResponse.SessionIndex = claims.FindFirstValue(c => c.Type == Saml2ClaimTypes.SessionIndex); saml2AuthnResponse.NameId = GetNameId(claims); var tokenIssueTime = DateTimeOffset.UtcNow; var tokenDescriptor = saml2AuthnResponse.CreateTokenDescriptor(GetSubjectClaims(party, claims), party.Issuer, tokenIssueTime, party.IssuedTokenLifetime); var authnContext = claims.FindFirstValue(c => c.Type == ClaimTypes.AuthenticationMethod); var authenticationInstant = claims.FindFirstValue(c => c.Type == ClaimTypes.AuthenticationInstant); var authenticationStatement = saml2AuthnResponse.CreateAuthenticationStatement(authnContext, DateTime.Parse(authenticationInstant)); var subjectConfirmation = saml2AuthnResponse.CreateSubjectConfirmation(tokenIssueTime, party.SubjectConfirmationLifetime); await saml2AuthnResponse.CreateSecurityTokenAsync(tokenDescriptor, authenticationStatement, subjectConfirmation); } binding.Bind(saml2AuthnResponse); logger.ScopeTrace($"SAML Authn response '{saml2AuthnResponse.XmlDocument.OuterXml}'."); logger.ScopeTrace($"Acs url '{acsUrl}'."); logger.ScopeTrace("Down, SAML Authn response.", triggerEvent: true); await sequenceLogic.RemoveSequenceDataAsync <SamlDownSequenceData>(); await formActionLogic.RemoveFormActionSequenceDataAsync(); if (binding is Saml2Binding <Saml2RedirectBinding> ) { return(await Task.FromResult((binding as Saml2RedirectBinding).ToActionResult())); } else if (binding is Saml2Binding <Saml2PostBinding> ) { return(await Task.FromResult((binding as Saml2PostBinding).ToActionResult())); } else { throw new NotSupportedException(); } }
private async Task <IActionResult> AuthnRequestAsync <T>(SamlUpParty party, Saml2Binding <T> binding, SamlUpSequenceData samlUpSequenceData) { var samlConfig = await saml2ConfigurationLogic.GetSamlUpConfigAsync(party, includeSigningAndDecryptionCertificate : true); binding.RelayState = await sequenceLogic.CreateExternalSequenceIdAsync(); var saml2AuthnRequest = new Saml2AuthnRequest(samlConfig); switch (samlUpSequenceData.LoginAction) { case LoginAction.ReadSession: saml2AuthnRequest.IsPassive = true; break; case LoginAction.RequireLogin: saml2AuthnRequest.ForceAuthn = true; break; default: break; } if (party.AuthnContextClassReferences?.Count() > 0) { saml2AuthnRequest.RequestedAuthnContext = new RequestedAuthnContext { Comparison = party.AuthnContextComparison.HasValue ? (AuthnContextComparisonTypes)Enum.Parse(typeof(AuthnContextComparisonTypes), party.AuthnContextComparison.Value.ToString()) : null, AuthnContextClassRef = party.AuthnContextClassReferences, }; } binding.Bind(saml2AuthnRequest); logger.ScopeTrace(() => $"SAML Authn request '{saml2AuthnRequest.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message); logger.ScopeTrace(() => $"Authn URL '{samlConfig.SingleSignOnDestination?.OriginalString}'."); logger.ScopeTrace(() => "Up, Sending SAML Authn request.", triggerEvent: true); 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(); } }
private async Task <IActionResult> LogoutAsync <T>(SamlUpParty party, Saml2Binding <T> binding, LogoutRequest logoutRequest) { var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party, includeSigningCertificate: true); await formActionLogic.AddFormActionByUrlAsync(samlConfig.SingleLogoutDestination.OriginalString); binding.RelayState = SequenceString; var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig); saml2LogoutRequest.SessionIndex = logoutRequest.SessionId; var nameID = logoutRequest.Claims?.Where(c => c.Type == Saml2ClaimTypes.NameId).Select(c => c.Value).FirstOrDefault(); var nameIdFormat = logoutRequest.Claims?.Where(c => c.Type == Saml2ClaimTypes.NameIdFormat).Select(c => c.Value).FirstOrDefault(); if (!nameID.IsNullOrEmpty()) { 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}'."); logger.ScopeTrace($"Logout url '{samlConfig.SingleLogoutDestination?.OriginalString}'."); logger.ScopeTrace("Up, SAML Logout request.", triggerEvent: true); if (binding is Saml2Binding <Saml2RedirectBinding> ) { return(await Task.FromResult((binding as Saml2RedirectBinding).ToActionResult())); } if (binding is Saml2Binding <Saml2PostBinding> ) { return(await Task.FromResult((binding as Saml2PostBinding).ToActionResult())); } else { throw new NotSupportedException(); } }
private async Task <IActionResult> AuthnRequestAsync <T>(SamlUpParty party, Saml2Binding <T> binding, SamlUpSequenceData samlUpSequenceData) { var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party); binding.RelayState = SequenceString; var saml2AuthnRequest = new Saml2AuthnRequest(samlConfig); switch (samlUpSequenceData.LoginAction) { case LoginAction.ReadSession: saml2AuthnRequest.IsPassive = true; break; case LoginAction.RequireLogin: saml2AuthnRequest.ForceAuthn = true; break; default: break; } binding.Bind(saml2AuthnRequest); logger.ScopeTrace($"SAML Authn request '{saml2AuthnRequest.XmlDocument.OuterXml}'."); logger.ScopeTrace($"Authn URL '{samlConfig.SingleSignOnDestination?.OriginalString}'."); logger.ScopeTrace("Up, Sending SAML Authn request.", triggerEvent: true); 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(); } }
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(); } }