protected override async Task <HandleRequestResult> HandleRemoteAuthenticateAsync() { SAMLResponseDto samlResponse = null; if (Request.Method == "GET") { samlResponse = SAMLResponseDto.Build(Request.Query.ToDictionary(k => k.Key, k => k.Value.First())); } else { samlResponse = SAMLResponseDto.Build(Request.Form.ToDictionary(k => k.Key, k => k.Value.First())); } try { var properties = Options.StateDataFormat.Unprotect(samlResponse.RelayState); if (properties == null) { return(HandleRequestResult.Fail("The state was missing or invalid.")); } var assertion = await Validate(samlResponse, CancellationToken.None); var claimsIdentity = new ClaimsIdentity(BuildClaims(assertion), Scheme.Name); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); var ticket = new AuthenticationTicket(claimsPrincipal, properties, Options.SignInScheme); return(HandleRequestResult.Success(ticket)); } catch (SamlException ex) { return(HandleRequestResult.Fail(ex)); } }
public async virtual Task <AssertionType> Validate(SAMLResponseDto samlResponse, CancellationToken cancellationToken) { var certificates = await CheckEntityDescriptor(cancellationToken); var response = CheckSamlResponse(samlResponse); CheckSignature(samlResponse, response, certificates); return(response.Content.Items.First(i => i is AssertionType) as AssertionType); }
protected virtual SAMLValidatorResult <ResponseType> CheckSamlResponse(SAMLResponseDto samlResponse) { var response = SAMLValidator.CheckSaml <ResponseType>(samlResponse.SAMLResponse, samlResponse.RelayState); var assertion = response.Content.Items.FirstOrDefault(i => i is AssertionType) as AssertionType; if (assertion == null) { throw new SamlException(System.Net.HttpStatusCode.BadRequest, Saml.Constants.StatusCodes.Responder, Global.MissingAssertion); } return(response); }
protected virtual void CheckSignature(SAMLResponseDto samlResponse, SAMLValidatorResult <ResponseType> response, IEnumerable <X509Certificate2> certificates) { if (string.IsNullOrWhiteSpace(samlResponse.SAMLResponse)) { throw new SamlException(System.Net.HttpStatusCode.BadRequest, Saml.Constants.StatusCodes.Responder, string.Format(Global.MissingParameter, "SAMLResponse")); } if (Options.WantsResponseSigned) { if (!certificates.Any(certificate => SignatureHelper.CheckSignature(response.Document.DocumentElement, certificate))) { throw new SamlException(System.Net.HttpStatusCode.BadRequest, Saml.Constants.StatusCodes.Responder, Global.BadSamlResponseSignature); } } if (Options.WantAssertionSigned) { var assertion = response.Document.GetElementsByTagName("Assertion", "urn:oasis:names:tc:SAML:2.0:assertion"); if (!certificates.Any(certificate => SignatureHelper.CheckSignature(assertion[0] as XmlElement, certificate))) { throw new SamlException(System.Net.HttpStatusCode.BadRequest, Saml.Constants.StatusCodes.Responder, Global.BadAssertionSignature); } } if (!string.IsNullOrWhiteSpace(samlResponse.SigAlg)) { var query = samlResponse.ToQuery(false); var sig = Constants.MappingStrToSignature[samlResponse.SigAlg]; var hashed = Hash.Compute(query, sig); if (!certificates.Any(certificate => { var rsa = certificate.GetRSAPublicKey(); return(rsa.VerifyHash(hashed, Convert.FromBase64String(samlResponse.Signature), Constants.MappingSignatureAlgToHash[sig], RSASignaturePadding.Pkcs1)); })) { throw new SamlException(System.Net.HttpStatusCode.BadRequest, Saml.Constants.StatusCodes.Responder, Global.BadSignature); } } }