private async Task <IActionResult> SingleLogoutResponseAsync <T>(SamlDownParty party, Saml2Binding <T> binding) { var samlConfig = await saml2ConfigurationLogic.GetSamlDownConfigAsync(party); var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig); binding.ReadSamlResponse(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse); logger.ScopeTrace(() => $"SAML Single Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message); ValidateLogoutResponse(party, saml2LogoutResponse); await sequenceLogic.ValidateExternalSequenceIdAsync(binding.RelayState); try { binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse); logger.ScopeTrace(() => "Down, SAML Single Logout response accepted.", triggerEvent: true); } catch (Exception ex) { var isex = saml2ConfigurationLogic.GetInvalidSignatureValidationCertificateException(samlConfig, ex); if (isex != null) { throw isex; } throw; } return(await singleLogoutDownLogic.HandleSingleLogoutAsync()); }
private async Task <IActionResult> SingleLogoutResponseAsync <T>(SamlDownParty party, Saml2Binding <T> binding) { var samlConfig = saml2ConfigurationLogic.GetSamlDownConfig(party); var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig); binding.ReadSamlResponse(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse); logger.ScopeTrace($"SAML Single Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'."); ValidateLogoutResponse(party, saml2LogoutResponse); await sequenceLogic.ValidateSequenceAsync(binding.RelayState); binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse); logger.ScopeTrace("Down, SAML Single Logout response accepted.", triggerEvent: true); return(await singleLogoutDownLogic.HandleSingleLogoutAsync()); }
private async Task <IActionResult> LogoutResponseAsync <T>(SamlUpParty party, Saml2Binding <T> binding) { var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party); var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig); binding.ReadSamlResponse(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse); await sequenceLogic.ValidateSequenceAsync(binding.RelayState); var sequenceData = await sequenceLogic.GetSequenceDataAsync <SamlUpSequenceData>(); try { logger.ScopeTrace($"SAML Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'."); logger.SetScopeProperty("status", saml2LogoutResponse.Status.ToString()); logger.ScopeTrace("Up, SAML Logout response.", triggerEvent: true); if (saml2LogoutResponse.Status != Saml2StatusCodes.Success) { throw new SamlRequestException("Unsuccessful Logout response.") { RouteBinding = RouteBinding, Status = saml2LogoutResponse.Status }; } binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse); logger.ScopeTrace("Up, Successful SAML Logout response.", triggerEvent: true); return(await LogoutResponseDownAsync(sequenceData, saml2LogoutResponse.Status, saml2LogoutResponse.SessionIndex)); } catch (SamlRequestException ex) { logger.Error(ex); return(await LogoutResponseDownAsync(sequenceData, ex.Status)); } catch (Exception ex) { logger.Error(ex); return(await LogoutResponseDownAsync(sequenceData, Saml2StatusCodes.Responder)); } }
private string ReadRelyingPartyFromLogoutResponse <T>(Saml2Binding <T> binding) { return(binding.ReadSamlResponse(Request.ToGenericHttpRequest(), new Saml2LogoutResponse(saml2Config))?.Issuer); }
private async Task <IActionResult> AuthnResponseAsync <T>(SamlUpParty party, Saml2Binding <T> binding) { var request = HttpContext.Request; var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party); var saml2AuthnResponse = new Saml2AuthnResponse(samlConfig); binding.ReadSamlResponse(request.ToGenericHttpRequest(), saml2AuthnResponse); await sequenceLogic.ValidateSequenceAsync(binding.RelayState); var sequenceData = await sequenceLogic.GetSequenceDataAsync <SamlUpSequenceData>(); try { logger.ScopeTrace($"SAML Authn response '{saml2AuthnResponse.XmlDocument.OuterXml}'."); logger.SetScopeProperty("status", saml2AuthnResponse.Status.ToString()); logger.ScopeTrace("Up, SAML Authn response.", triggerEvent: true); if (saml2AuthnResponse.Status != Saml2StatusCodes.Success) { throw new SamlRequestException("Unsuccessful Authn response.") { RouteBinding = RouteBinding, Status = saml2AuthnResponse.Status }; } binding.Unbind(request.ToGenericHttpRequest(), saml2AuthnResponse); logger.ScopeTrace("Up, Successful SAML Authn response.", triggerEvent: true); var claims = saml2AuthnResponse.ClaimsIdentity?.Claims; if (saml2AuthnResponse.ClaimsIdentity?.Claims?.Count() <= 0) { throw new SamlRequestException("Empty claims collection.") { RouteBinding = RouteBinding, Status = Saml2StatusCodes.Responder }; } if (!claims.Any(c => c.Type == ClaimTypes.NameIdentifier)) { claims = AddNameIdClaim(claims); } claims = await claimTransformationsLogic.Transform(party.ClaimTransformations?.ConvertAll(t => (ClaimTransformation)t), claims); claims = ValidateClaims(party, claims); return(await AuthnResponseDownAsync(sequenceData, saml2AuthnResponse.Status, claims)); } catch (SamlRequestException ex) { logger.Error(ex); return(await AuthnResponseDownAsync(sequenceData, ex.Status)); } catch (Exception ex) { logger.Error(ex); return(await AuthnResponseDownAsync(sequenceData, Saml2StatusCodes.Responder)); } }
private async Task <IActionResult> AuthnResponseAsync <T>(SamlUpParty party, Saml2Binding <T> binding) { var request = HttpContext.Request; var samlConfig = await saml2ConfigurationLogic.GetSamlUpConfigAsync(party, includeSigningAndDecryptionCertificate : true); var saml2AuthnResponse = new Saml2AuthnResponse(samlConfig); try { binding.ReadSamlResponse(request.ToGenericHttpRequest(), saml2AuthnResponse); } catch (Exception ex) { if (samlConfig.SecondaryDecryptionCertificate != null && binding is Saml2PostBinding && ex.Source.Contains("cryptography", StringComparison.OrdinalIgnoreCase)) { samlConfig.DecryptionCertificate = samlConfig.SecondaryDecryptionCertificate; saml2AuthnResponse = new Saml2AuthnResponse(samlConfig); binding.ReadSamlResponse(request.ToGenericHttpRequest(), saml2AuthnResponse); logger.ScopeTrace(() => $"SAML Authn response decrypted with secondary certificate.", traceType: TraceTypes.Message); } else { throw; } } if (binding.RelayState.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(binding.RelayState), binding.GetTypeName()); } await sequenceLogic.ValidateExternalSequenceIdAsync(binding.RelayState); var sequenceData = await sequenceLogic.GetSequenceDataAsync <SamlUpSequenceData>(); try { logger.ScopeTrace(() => $"SAML Authn response '{saml2AuthnResponse.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message); logger.SetScopeProperty(Constants.Logs.UpPartyStatus, saml2AuthnResponse.Status.ToString()); logger.ScopeTrace(() => "Up, SAML Authn response.", triggerEvent: true); if (saml2AuthnResponse.Status != Saml2StatusCodes.Success) { throw new SamlRequestException("Unsuccessful Authn response.") { RouteBinding = RouteBinding, Status = saml2AuthnResponse.Status }; } try { binding.Unbind(request.ToGenericHttpRequest(), saml2AuthnResponse); logger.ScopeTrace(() => "Up, Successful SAML Authn response.", triggerEvent: true); } catch (Exception ex) { var isex = saml2ConfigurationLogic.GetInvalidSignatureValidationCertificateException(samlConfig, ex); if (isex != null) { throw isex; } throw; } if (saml2AuthnResponse.ClaimsIdentity?.Claims?.Count() <= 0) { throw new SamlRequestException("Empty claims collection.") { RouteBinding = RouteBinding, Status = Saml2StatusCodes.Responder }; } var claims = new List <Claim>(saml2AuthnResponse.ClaimsIdentity.Claims.Where(c => c.Type != ClaimTypes.NameIdentifier)); var nameIdClaim = GetNameIdClaim(party.Name, saml2AuthnResponse.ClaimsIdentity.Claims); if (nameIdClaim != null) { claims.Add(nameIdClaim); } logger.ScopeTrace(() => $"Up, SAML Authn received SAML claims '{claims.ToFormattedString()}'", traceType: TraceTypes.Claim); var externalSessionId = claims.FindFirstValue(c => c.Type == Saml2ClaimTypes.SessionIndex); externalSessionId.ValidateMaxLength(IdentityConstants.MessageLength.SessionIdMax, nameof(externalSessionId), "Session index claim"); claims = claims.Where(c => c.Type != Saml2ClaimTypes.SessionIndex && c.Type != Constants.SamlClaimTypes.UpParty && c.Type != Constants.SamlClaimTypes.UpPartyType).ToList(); claims.AddClaim(Constants.SamlClaimTypes.UpParty, party.Name); claims.AddClaim(Constants.SamlClaimTypes.UpPartyType, party.Type.ToString().ToLower()); var transformedClaims = await claimTransformLogic.Transform(party.ClaimTransforms?.ConvertAll(t => (ClaimTransform)t), claims); var validClaims = ValidateClaims(party, transformedClaims); logger.ScopeTrace(() => $"Up, SAML Authn output SAML claims '{validClaims.ToFormattedString()}'", traceType: TraceTypes.Claim); var jwtValidClaims = await claimsDownLogic.FromSamlToJwtClaimsAsync(validClaims); var sessionId = await sessionUpPartyLogic.CreateOrUpdateSessionAsync(party, party.DisableSingleLogout?null : sequenceData.DownPartyLink, jwtValidClaims, externalSessionId); if (!sessionId.IsNullOrEmpty()) { jwtValidClaims.AddClaim(JwtClaimTypes.SessionId, sessionId); } logger.ScopeTrace(() => $"Up, SAML Authn output JWT claims '{jwtValidClaims.ToFormattedString()}'", traceType: TraceTypes.Claim); return(await AuthnResponseDownAsync(sequenceData, saml2AuthnResponse.Status, jwtValidClaims)); } catch (StopSequenceException) { throw; } catch (SamlRequestException ex) { logger.Error(ex); return(await AuthnResponseDownAsync(sequenceData, ex.Status)); } catch (Exception ex) { logger.Error(ex); return(await AuthnResponseDownAsync(sequenceData, Saml2StatusCodes.Responder)); } }
private async Task <IActionResult> LogoutResponseAsync <T>(SamlUpParty party, Saml2Binding <T> binding) { var samlConfig = await saml2ConfigurationLogic.GetSamlUpConfigAsync(party); var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig); binding.ReadSamlResponse(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse); await sequenceLogic.ValidateExternalSequenceIdAsync(binding.RelayState); var sequenceData = await sequenceLogic.GetSequenceDataAsync <SamlUpSequenceData>(remove : party.DisableSingleLogout); try { logger.ScopeTrace(() => $"SAML Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message); logger.SetScopeProperty(Constants.Logs.Status, saml2LogoutResponse.Status.ToString()); logger.ScopeTrace(() => "Up, SAML Logout response.", triggerEvent: true); if (saml2LogoutResponse.Status != Saml2StatusCodes.Success) { throw new SamlRequestException("Unsuccessful Logout response.") { RouteBinding = RouteBinding, Status = saml2LogoutResponse.Status }; } try { binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse); logger.ScopeTrace(() => "Up, Successful SAML Logout response.", triggerEvent: true); } catch (Exception ex) { var isex = saml2ConfigurationLogic.GetInvalidSignatureValidationCertificateException(samlConfig, ex); if (isex != null) { throw isex; } throw; } if (party.DisableSingleLogout) { return(await LogoutResponseDownAsync(sequenceData)); } else { (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, sequenceData.DownPartyLink, sequenceData.SessionDownPartyLinks, sequenceData.SessionClaims); if (doSingleLogout) { return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData)); } else { await sequenceLogic.RemoveSequenceDataAsync <SamlUpSequenceData>(); return(await LogoutResponseDownAsync(sequenceData)); } } } catch (StopSequenceException) { throw; } catch (SamlRequestException ex) { logger.Error(ex); return(await LogoutResponseDownAsync(sequenceData, status : ex.Status)); } catch (Exception ex) { logger.Error(ex); return(await LogoutResponseDownAsync(sequenceData, status : Saml2StatusCodes.Responder)); } }
private async Task <IActionResult> AuthnResponseAsync <T>(SamlUpParty party, Saml2Binding <T> binding) { var request = HttpContext.Request; var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party); var saml2AuthnResponse = new Saml2AuthnResponse(samlConfig); binding.ReadSamlResponse(request.ToGenericHttpRequest(), saml2AuthnResponse); if (binding.RelayState.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(binding.RelayState), binding.GetTypeName()); } await sequenceLogic.ValidateSequenceAsync(binding.RelayState); var sequenceData = await sequenceLogic.GetSequenceDataAsync <SamlUpSequenceData>(); try { logger.ScopeTrace($"SAML Authn response '{saml2AuthnResponse.XmlDocument.OuterXml}'."); logger.SetScopeProperty("upPartyStatus", saml2AuthnResponse.Status.ToString()); logger.ScopeTrace("Up, SAML Authn response.", triggerEvent: true); if (saml2AuthnResponse.Status != Saml2StatusCodes.Success) { throw new SamlRequestException("Unsuccessful Authn response.") { RouteBinding = RouteBinding, Status = saml2AuthnResponse.Status }; } binding.Unbind(request.ToGenericHttpRequest(), saml2AuthnResponse); logger.ScopeTrace("Up, Successful SAML Authn response.", triggerEvent: true); if (saml2AuthnResponse.ClaimsIdentity?.Claims?.Count() <= 0) { throw new SamlRequestException("Empty claims collection.") { RouteBinding = RouteBinding, Status = Saml2StatusCodes.Responder }; } var claims = new List <Claim>(saml2AuthnResponse.ClaimsIdentity.Claims.Where(c => c.Type != ClaimTypes.NameIdentifier)); var nameIdClaim = GetNameIdClaim(party.Name, saml2AuthnResponse.ClaimsIdentity.Claims); if (nameIdClaim != null) { claims.Add(nameIdClaim); } var externalSessionId = claims.FindFirstValue(c => c.Type == Saml2ClaimTypes.SessionIndex); externalSessionId.ValidateMaxLength(IdentityConstants.MessageLength.SessionIdMax, nameof(externalSessionId), "Session index claim"); claims = claims.Where(c => c.Type != Saml2ClaimTypes.SessionIndex && c.Type != Constants.SamlClaimTypes.UpPary && c.Type != Constants.SamlClaimTypes.UpParyType).ToList(); claims.AddClaim(Constants.SamlClaimTypes.UpPary, party.Name); claims.AddClaim(Constants.SamlClaimTypes.UpParyType, party.Type.ToString().ToLower()); var transformedClaims = await claimTransformationsLogic.Transform(party.ClaimTransforms?.ConvertAll(t => (ClaimTransform)t), claims); var validClaims = ValidateClaims(party, transformedClaims); var jwtValidClaims = await claimsDownLogic.FromSamlToJwtClaimsAsync(validClaims); var sessionId = await sessionUpPartyLogic.CreateOrUpdateSessionAsync(party, party.DisableSingleLogout?null : sequenceData.DownPartyLink, jwtValidClaims, externalSessionId); if (!sessionId.IsNullOrEmpty()) { jwtValidClaims.AddClaim(JwtClaimTypes.SessionId, sessionId); } return(await AuthnResponseDownAsync(sequenceData, saml2AuthnResponse.Status, jwtValidClaims)); } catch (StopSequenceException) { throw; } catch (SamlRequestException ex) { logger.Error(ex); return(await AuthnResponseDownAsync(sequenceData, ex.Status)); } catch (Exception ex) { logger.Error(ex); return(await AuthnResponseDownAsync(sequenceData, Saml2StatusCodes.Responder)); } }