protected virtual async Task <RelyingPartyAggregate> CheckRelyingParty(AuthnRequestType authnRequest, CancellationToken cancellationToken) { var relyingParty = await _relyingPartyRepository.Get(authnRequest.Issuer.Value, cancellationToken); if (relyingParty == null) { throw new SamlException(HttpStatusCode.NotFound, Saml.Constants.StatusCodes.Requester, string.Format(Global.UnknownIssuer, nameof(authnRequest.Issuer.Value))); } if (await relyingParty.GetAuthnRequestsSigned(_entityDescriptorStore, cancellationToken)) { var certificates = await relyingParty.GetSigningCertificates(_entityDescriptorStore, cancellationToken); foreach (var certificate in certificates) { if (SignatureHelper.CheckSignature(authnRequest.SerializeToXmlElement(), certificate)) { return(relyingParty); } } throw new SamlException(HttpStatusCode.BadRequest, Saml.Constants.StatusCodes.Requester, Global.BadAuthnRequestSignature); } if ((await relyingParty.GetAssertionLocation(_entityDescriptorStore, Saml.Constants.Bindings.HttpRedirect, cancellationToken)) == null) { throw new SamlException(HttpStatusCode.BadRequest, Saml.Constants.StatusCodes.UnsupportedBinding, Global.BadSPAssertionLocation); } return(relyingParty); }
public void When_Build_And_Sign_AuthnRequest() { var payload = File.ReadAllBytes(Path.Combine(Directory.GetCurrentDirectory(), "localhost.pfx")); var certificate = new X509Certificate2(payload, "password"); // https://en.wikipedia.org/wiki/SAML_2.0 // https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf // https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf // https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf // https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf // http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml2-holder-of-key-cs-02.html // https://developers.onelogin.com/saml/examples/authnrequest : explains how to sign AuthnRequest // https://dtservices.bosa.be/sites/default/files/content/download/files/fas_saml_integration_guide_v0.51_1.pdf // ARRANGE var builder = AuthnRequestBuilder.New("SP") .SetIssuer(Constants.NameIdentifierFormats.EntityIdentifier, "urn:sp"); // ACT var authnRequest = builder.SignAndBuild(certificate, SignatureAlgorithms.RSASHA256, CanonicalizationMethods.C14); // ASSERT Assert.True(SignatureHelper.CheckSignature(authnRequest, certificate)); }
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); } } }