public void Saml2Response_Validate_FalseOnReplayedInResponseTo() { var idp = IdentityProvider.ConfiguredIdentityProviders.First().Value; var request = idp.CreateAuthenticateRequest(); var responseXML = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" ID = ""Saml2Response_Validate_TrueOnCorrectInResponseTo"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"" InResponseTo = """ + request.Id + @"""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" /> </saml2p:Status> </saml2p:Response>"; responseXML = SignedXmlHelper.SignXml(responseXML); var response = Saml2Response.Read(responseXML); response.Validate(SignedXmlHelper.TestCert).Should().BeTrue(); response = Saml2Response.Read(responseXML); response.Validate(SignedXmlHelper.TestCert).Should().BeFalse(); }
public void Saml2Response_Read_ThrowsWrongRootNamespace() { Action a = () => Saml2Response.Read("<saml2p:Response xmlns:saml2p=\"something\" /> "); a.ShouldThrow <XmlException>() .WithMessage("Expected a SAML2 assertion document"); }
public void Saml2Response_GetClaims_ThrowsOnNotValidated() { var response = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" ID = ""Saml2Response_GetClaims_ThrowsOnNotValidated"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" /> </saml2p:Status> <saml2:Assertion Version=""2.0"" ID=""Saml2Response_GetClaims_ThrowsOnNotValidated_Assertion"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> </saml2:Assertion> </saml2p:Response>"; Action a = () => Saml2Response.Read(response).GetClaims(); a.ShouldThrow <InvalidOperationException>() .WithMessage("The Saml2Response must be validated first."); }
public void Saml2Response_Read_BasicParams() { string response = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" ID = ""Saml2Response_Read_BasicParams"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"" InResponseTo = ""InResponseToId"" Destination=""http://destination.example.com""> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" /> </saml2p:Status> </saml2p:Response>"; var expected = new { Id = new Saml2Id("Saml2Response_Read_BasicParams"), IssueInstant = new DateTime(2013, 01, 01, 0, 0, 0, DateTimeKind.Utc), Status = Saml2StatusCode.Requester, Issuer = (string)null, DestinationUri = new Uri("http://destination.example.com"), MessageName = "SAMLResponse", InResponseTo = new Saml2Id("InResponseToId"), }; Saml2Response.Read(response).ShouldBeEquivalentTo(expected, opt => opt.Excluding(s => s.XmlDocument)); }
public void Saml2Response_Validate_FalseOnAssertionInjectionWithAssertionSignature() { var response = @"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" ID = ""Saml2Response_Validate_FalseOnAssertionInjectionWithAssertionSignature"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" /> </saml2p:Status> {0} {1} </saml2p:Response>"; var assertion1 = @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" Version=""2.0"" ID=""Saml2Response_Validate_FalseOnAssertionInjectionWithAssertionSignature_Assertion1"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" /> </saml2:Assertion>"; var assertionToInject = @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" Version=""2.0"" ID=""Saml2Response_Validate_FalseOnAssertionInjectionWithAssertionSignature_Assertion2"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser2</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" /> </saml2:Assertion>"; var signedAssertion1 = SignedXmlHelper.SignXml(assertion1); var signedAssertion1Doc = new XmlDocument { PreserveWhitespace = true }; signedAssertion1Doc.LoadXml(signedAssertion1); var signatureToCopy = signedAssertion1Doc.DocumentElement["Signature", SignedXml.XmlDsigNamespaceUrl]; var assertionToInjectDoc = new XmlDocument { PreserveWhitespace = true }; assertionToInjectDoc.LoadXml(assertionToInject); assertionToInjectDoc.DocumentElement.AppendChild(assertionToInjectDoc.ImportNode(signatureToCopy, true)); var signedAssertionToInject = assertionToInjectDoc.OuterXml; var signedResponse = string.Format(response, signedAssertion1, signedAssertionToInject); Saml2Response.Read(signedResponse).Validate(SignedXmlHelper.TestCert).Should().BeFalse(); }
public void Saml2Response_Validate_FalseOnTamperedAssertionWithMessageSignature() { var response = @"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" ID = ""Saml2Response_Validate_FalseOnTamperedAssertionWithMessageSignature"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" /> </saml2p:Status> <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" Version=""2.0"" ID=""Saml2Response_Validate_FalseOnTamperedAssertionWithMessageSignature_Assertion1"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" /> </saml2:Assertion> </saml2p:Response>"; var signedResponse = SignedXmlHelper.SignXml(response).Replace("SomeUser", "SomeOtherUser"); Saml2Response.Read(signedResponse).Validate(SignedXmlHelper.TestCert).Should().BeFalse(); }
public void Saml2Response_Validate_TrueOnCorrectSignedSingleAssertionInResponseMessage() { var response = @"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" ID = ""Saml2Response_Validate_TrueOnCorrectSignedSingleAssertionInResponseMessage"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" /> </saml2p:Status> {0} </saml2p:Response>"; var assertion = @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" Version=""2.0"" ID=""Saml2Response_Validate_TrueOnCorrectSignedSingleAssertionInResponseMessagee_Assertion1"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" /> </saml2:Assertion>"; var signedAssertion = SignedXmlHelper.SignXml(assertion); var signedResponse = string.Format(response, signedAssertion); Saml2Response.Read(signedResponse).Validate(SignedXmlHelper.TestCert).Should().BeTrue(); }
public void Saml2Response_Validate_FalseOnMissingSignatureInResponseAndAnyAssertion() { var response = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" ID = ""Saml2Response_Validates_FalseOnMissingSignatureInResponseAndAnyAssertion"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" /> </saml2p:Status> <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" Version=""2.0"" ID=""Saml2Response_Validates_FalseOnMissingSignatureInResponseAndAnyAssertion_Assertion1"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" /> </saml2:Assertion> <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" Version=""2.0"" ID=""Saml2Response_Validates_FalseOnMissingSignatureInResponseAndAnyAssertion_Assertion2"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" /> </saml2:Assertion> </saml2p:Response>"; Saml2Response.Read(response).Validate(null).Should().BeFalse(); }
public void Saml2Response_Validate_TrueOnMissingInResponseTo_IfAllowed() { KentorAuthServicesSection.Current.IdentityProviders.First().AllowConfigEdit(true); KentorAuthServicesSection.Current.IdentityProviders.First().AllowUnsolicitedAuthnResponse = true; KentorAuthServicesSection.Current.IdentityProviders.First().AllowConfigEdit(false); var idp = IdentityProvider.ConfiguredIdentityProviders.First().Value; var request = idp.CreateAuthenticateRequest(); var responseXML = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" ID = ""Saml2Response_Validate_TrueOnCorrectInResponseTo"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" /> </saml2p:Status> </saml2p:Response>"; responseXML = SignedXmlHelper.SignXml(responseXML); var response = Saml2Response.Read(responseXML); response.Validate(SignedXmlHelper.TestCert).Should().BeTrue(); }
public void Saml2Response_Validate_FalseOnReplyFromWrongIdp() { // A valid response is received, but it is not from the idp that we // did send the AuthnRequest to. var idp = IdentityProvider.ConfiguredIdentityProviders.First().Value; var request = idp.CreateAuthenticateRequest(); var responseXML = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" ID = ""Saml2Response_Validate_TrueOnCorrectInResponseTo"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"" InResponseTo = """ + request.Id + @"""> <saml2p:Issuer>https://idp.anotheridp.com</saml2p:Issuer> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" /> </saml2p:Status> </saml2p:Response>"; responseXML = SignedXmlHelper.SignXml(responseXML); var response = Saml2Response.Read(responseXML); response.Validate(SignedXmlHelper.TestCert).Should().BeFalse(); }
public void Saml2Response_GetClaims_ThrowsOnExpired() { var response = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" ID = ""Saml2Response_GetClaims_ThrowsOnExpired"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"" Issuer = ""https://some.issuer.example.com""> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" /> </saml2p:Status> <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" Version=""2.0"" ID=""Saml2Response_GetClaims_ThrowsOnExpired_Assertion"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> <saml2:Conditions NotOnOrAfter=""2013-06-30T08:00:00Z"" /> </saml2:Assertion> </saml2p:Response>"; response = SignedXmlHelper.SignXml(response); var r = Saml2Response.Read(response); r.Validate(SignedXmlHelper.TestCert); Action a = () => r.GetClaims(); a.ShouldThrow <SecurityTokenExpiredException>(); }
public void Saml2Response_Read_ThrowsOnNonXml() { Action a = () => Saml2Response.Read("not xml"); a.ShouldThrow <XmlException>() .WithMessage("Data at the root level is invalid. Line 1, position 1."); }
public void Saml2Response_Read_ThrowsWrongRootNodeName() { Action a = () => Saml2Response.Read("<saml2p:NotResponse xmlns:saml2p=\"urn:oasis:names:tc:SAML:2.0:protocol\" />"); a.ShouldThrow <XmlException>() .WithMessage("Expected a SAML2 assertion document"); }
public void Saml2Response_GetClaims_ThrowsOnResponseNotValid() { var response = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" ID = ""Saml2Response_GetClaims_ThrowsOnResponseNotValid"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"" Issuer = ""https://some.issuer.example.com""> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" /> </saml2p:Status> <saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion"" Version=""2.0"" ID=""Saml2Response_GetClaims_ThrowsOnResponseNotValid_Assertion"" IssueInstant=""2013-09-25T00:00:00Z""> <saml2:Issuer>https://idp.example.com</saml2:Issuer> <saml2:Subject> <saml2:NameID>SomeUser</saml2:NameID> <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" /> </saml2:Subject> </saml2:Assertion> </saml2p:Response>"; response = SignedXmlHelper.SignXml(response); response = response.Replace("2013-09-25", "2013-09-26"); var r = Saml2Response.Read(response); r.Validate(SignedXmlHelper.TestCert); Action a = () => r.GetClaims(); a.ShouldThrow <InvalidOperationException>() .WithMessage("The Saml2Response didn't pass validation"); }
private static CommandResult ProcessResponse( IOptions options, Saml2Response samlResponse, StoredRequestState storedRequestState) { var principal = new ClaimsPrincipal(samlResponse.GetClaims(options)); principal = options.SPOptions.SystemIdentityModelIdentityConfiguration .ClaimsAuthenticationManager.Authenticate(null, principal); if (options.SPOptions.ReturnUrl == null) { if (storedRequestState == null) { throw new ConfigurationErrorsException(UnsolicitedMissingReturnUrlMessage); } if (storedRequestState.ReturnUrl == null) { throw new ConfigurationErrorsException(SpInitiatedMissingReturnUrl); } } return(new CommandResult() { HttpStatusCode = HttpStatusCode.SeeOther, Location = storedRequestState == null?null:storedRequestState.ReturnUrl ?? options.SPOptions.ReturnUrl, Principal = principal, RelayData = storedRequestState == null?null:storedRequestState.RelayData }); }
public void Saml2Response_Xml_FromData_ContainsBasicData() { var issuer = "http://idp.example.com"; var nameId = "JohnDoe"; var destination = "http://destination.example.com/"; var identity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.NameIdentifier, nameId) }); // Grab current time both before and after generating the response // to avoid heisenbugs if the second counter is updated while creating // the response. string before = DateTime.UtcNow.ToSaml2DateTimeString(); var response = new Saml2Response(issuer, SignedXmlHelper.TestCert, new Uri(destination), identity); string after = DateTime.UtcNow.ToSaml2DateTimeString(); var xml = response.XmlDocument; xml.FirstChild.OuterXml.Should().StartWith("<?xml version=\"1.0\""); xml.DocumentElement["Issuer", Saml2Namespaces.Saml2Name].InnerText.Should().Be(issuer); xml.DocumentElement["Assertion", Saml2Namespaces.Saml2Name] ["Subject", Saml2Namespaces.Saml2Name]["NameID", Saml2Namespaces.Saml2Name] .InnerText.Should().Be(nameId); xml.DocumentElement.GetAttribute("Destination").Should().Be(destination); xml.DocumentElement.GetAttribute("ID").Should().NotBeBlank(); xml.DocumentElement.GetAttribute("Version").Should().Be("2.0"); xml.DocumentElement.GetAttribute("IssueInstant").Should().Match( i => i == before || i == after); }
private static CommandResult ProcessResponse( IOptions options, Saml2Response samlResponse, StoredRequestState storedRequestState) { var principal = new ClaimsPrincipal(samlResponse.GetClaims(options, storedRequestState?.RelayData)); if (options.SPOptions.ReturnUrl == null) { if (storedRequestState == null) { throw new ConfigurationErrorsException(UnsolicitedMissingReturnUrlMessage); } if (storedRequestState.ReturnUrl == null) { throw new ConfigurationErrorsException(SpInitiatedMissingReturnUrl); } } options.SPOptions.Logger.WriteInformation("Successfully processed SAML response " + samlResponse.Id + " and authenticated " + principal.FindFirst(ClaimTypes.NameIdentifier)?.Value); return(new CommandResult() { HttpStatusCode = HttpStatusCode.SeeOther, Location = storedRequestState?.ReturnUrl ?? options.SPOptions.ReturnUrl, Principal = principal, RelayData = storedRequestState?.RelayData, SessionNotOnOrAfter = samlResponse.SessionNotOnOrAfter }); }
public CommandResult Run(HttpRequestData request, IOptions options) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } var binding = Saml2Binding.Get(request); if (binding != null) { UnbindResult unbindResult = null; try { unbindResult = binding.Unbind(request, options); var samlResponse = new Saml2Response(unbindResult.Data, request.StoredRequestState?.MessageId); var result = ProcessResponse(options, samlResponse, request.StoredRequestState); if (unbindResult.RelayState != null) { result.ClearCookieName = "Kentor." + unbindResult.RelayState; } return(result); } catch (FormatException ex) { throw new BadFormatSamlResponseException( "The SAML Response did not contain valid BASE64 encoded data.", ex); } catch (XmlException ex) { var newEx = new BadFormatSamlResponseException( "The SAML response contains incorrect XML", ex); // Add the payload to the exception if (unbindResult != null) { newEx.Data["Saml2Response"] = unbindResult.Data.OuterXml; } throw newEx; } catch (Exception ex) { if (unbindResult != null) { // Add the payload to the existing exception ex.Data["Saml2Response"] = unbindResult.Data.OuterXml; } throw; } } throw new NoSamlResponseFoundException(); }
private User GetUserByName(Saml2Response samlResponse) { var user = _entities.Get <User>() .EagerLoad(_entities, _loadUser) .ByName(samlResponse.EduPersonPrincipalName); return(user); }
public void Saml2Response_ToXml() { string response = @"<?xml version=""1.0"" encoding=""UTF-8""?><saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" ID=""Saml2Response_ToXml"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""><saml2p:Status><saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" /></saml2p:Status></saml2p:Response>"; var subject = Saml2Response.Read(response).ToXml(); subject.Should().Be(response); }
private User GetUserByEduPersonTargetedId(Saml2Response samlResponse) { var user = _entities.Get <User>() .EagerLoad(_entities, _loadUser) .ByEduPersonTargetedId(samlResponse.EduPersonTargetedId); return(user); }
public void Saml2Response_Read_ThrowsOnWrongVersion() { Action a = () => Saml2Response.Read("<saml2p:Response xmlns:saml2p=\"" + Saml2Namespaces.Saml2P + "\" Version=\"wrong\" />"); a.ShouldThrow <XmlException>() .WithMessage("Wrong or unsupported SAML2 version"); }
private static void VerifySignature(Saml2Response response) { if (response.IsSigned && !response.VerifySignature()) { throw new InvalidOperationException(string.Format( "SAML 2 response signature for '{0}' failed to verify.", response.IssuerNameIdentifier)); } }
/// <summary> /// Delete the current Federated Authentication Session. /// </summary> public static bool DeleteSession(this Saml2Response saml2Response) { if (saml2Response.Status == Saml2StatusCodes.Success) { FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie(); FederatedAuthentication.SessionAuthenticationModule.SignOut(); return(true); } return(false); }
public static Saml2AuthResponse Create(string samlResponse, Saml2Id responseToId, EntityId issuer, X509Certificate2 idpCert, X509Certificate2 serviceCertificate, EntityId serviceId) { var decoded = DecodeBase64(samlResponse); var xmlDoc = new XmlDocument(); xmlDoc.PreserveWhitespace = true; xmlDoc.LoadXml(decoded); var response = new Saml2Response(xmlDoc.DocumentElement, responseToId); if (response.Status != Saml2StatusCode.Success) { log.LogWarning("SAML authentication error: " + response.Status + " (" + response.StatusMessage + ")"); return(new Saml2AuthResponse(false) { Status = response.Status }); } var spOptions = new SPOptions(); spOptions.EntityId = serviceId; spOptions.ServiceCertificates.Add(serviceCertificate); var options = new Options(spOptions); var idp = new IdentityProvider(issuer, spOptions); idp.SigningKeys.AddConfiguredKey(idpCert); options.IdentityProviders.Add(idp); var identities = response.GetClaims(options)?.ToArray(); if (identities == null || identities.Length == 0) { return(new Saml2AuthResponse(false)); } var identity = identities.First(); var firstName = identity.FindFirstValue(AttributeNames.GivenName); var lastName = identity.FindFirstValue(AttributeNames.Sn); var ssn = identity.FindFirstValue(AttributeNames.NationalIdentificationNumber); var nameId = identity.FindFirstValue(AttributeNames.NameIdentifier); var sessionId = identity.FindFirstValue(AttributeNames.SessionIndex); return(new Saml2AuthResponse(true) { FirstName = firstName, LastName = lastName, SSN = ssn, RelayState = response.RelayState, NameIdentifier = nameId, SessionIndex = sessionId }); }
public void Saml2Response_Ctor_FromData() { var issuer = "http://idp.example.com"; var identity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.NameIdentifier, "JohnDoe") }); var response = new Saml2Response(issuer, null, null, identity); response.Issuer.Should().Be(issuer); response.GetClaims().Single().ShouldBeEquivalentTo(identity); }
public static IEnumerable <ClaimsIdentity> GetClaimsIdentities(Saml2Response token) { try { return(token.GetClaims(samlOptions)); } catch (Saml2ResponseFailedValidationException exception) { Debug.WriteLine(exception.Message); throw new HttpException(401, exception.Message); } }
public XmlDocument GetDecodedSamlResponse(Saml2Response saml2Response) { var doc = new XmlDocument { XmlResolver = null, PreserveWhitespace = true }; var base64SamlResponse = saml2Response.Response; var samlResponse = Encoding.UTF8.GetString(Convert.FromBase64String(base64SamlResponse)); doc.LoadXml(samlResponse); return(doc); }
private Person GetPerson(Saml2Response samlResponse) { Person person = null; // first, look up person by mail attribute (if present) var mails = samlResponse.Mails; if (mails != null && mails.Any()) { foreach (var mail in mails) { person = GetPersonByEmail(mail); if (person != null) { break; } } } // next, look for person by person principal name if (person == null) { person = GetPersonByEmail(samlResponse.EduPersonPrincipalName); } // need to create person if they do not exist if (person == null) { person = new Person { DisplayName = samlResponse.CommonName ?? samlResponse.DisplayName ?? samlResponse.EduPersonPrincipalName, FirstName = samlResponse.GivenName, LastName = samlResponse.SurName, }; } // make sure there is not a user with person principal name var user = GetUserByName(samlResponse); if (user != null && user.Person != person) { throw new InvalidOperationException(string.Format( "The user account '{0}' does not match expected person '{1}'.", user.Name, person.DisplayName)); } return(person); }
public void Saml2Response_Validate_FalseOnMissingSignature() { var response = @"<?xml version=""1.0"" encoding=""UTF-8""?> <saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol"" ID = ""Saml2Response_Validates_FalseOnMissingSignature"" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"" Issuer = ""https://some.issuer.example.com""> <saml2p:Status> <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Requester"" /> </saml2p:Status> </saml2p:Response>"; Saml2Response.Read(response).Validate(null).Should().BeFalse(); }
public void Saml2Response_MessageName() { var subject = new Saml2Response("issuer", null, null); subject.MessageName.Should().Be("SAMLResponse"); }
public void Saml2Response_Xml_FromData_IsSigned() { var issuer = "http://idp.example.com"; var nameId = "JohnDoe"; var identity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.NameIdentifier, nameId) }); var response = new Saml2Response(issuer, SignedXmlHelper.TestCert, null, claimsIdentities: identity); var xml = response.XmlDocument; var signedXml = new SignedXml(xml); var signature = xml.DocumentElement["Signature", SignedXml.XmlDsigNamespaceUrl]; signedXml.LoadXml(signature); signature.Should().NotBeNull(); signedXml.CheckSignature(SignedXmlHelper.TestCert, true).Should().BeTrue(); }
public void Saml2Response_Xml_FromData_ContainsStatus_Success() { var identity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.NameIdentifier, "JohnDoe") }); var response = new Saml2Response("issuer", SignedXmlHelper.TestCert, new Uri("http://destination.example.com"), identity); var xml = response.XmlDocument; var subject = xml.DocumentElement["Status", Saml2Namespaces.Saml2PName]; subject["StatusCode", Saml2Namespaces.Saml2PName].GetAttribute("Value") .Should().Be("urn:oasis:names:tc:SAML:2.0:status:Success"); }
public Saml2PostBinding Bind(Saml2Response saml2Response, X509Certificate2 signingCertificate = null) { return BindInternal(saml2Response as Saml2Request, Saml2Constants.Message.SamlResponse, signingCertificate); }
public Saml2Response Unbind(HttpRequestBase request, Saml2Response saml2Response, X509Certificate2 signatureValidationCertificate) { return UnbindInternal(request, saml2Response as Saml2Request, Saml2Constants.Message.SamlResponse, signatureValidationCertificate) as Saml2Response; }
public void Saml2Response_Xml_FromData_ContainsInResponseTo() { var identity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.NameIdentifier, "JohnDoe") }); var response = new Saml2Response("issuer", SignedXmlHelper.TestCert, new Uri("http://destination.example.com"), "InResponseToID", identity); var xml = response.XmlDocument; xml.DocumentElement.GetAttribute("InResponseTo").Should().Be("InResponseToID"); }