AuthenticationResponseGrant является нулевым после успешного входа в систему от SAML Identity Provider? - PullRequest
0 голосов
/ 02 марта 2020

Я добавляю аутентификацию SAML2 в приложение ASP. NET MVC5, которое использует OWIN. Я интегрировал Sustainsys.Saml2.Owin в приложение, я правильно перенаправлен в сконфигурированный Identity Provider для входа в систему, и Identity Provider возвращает правильный ответ (проверено с помощью SAML-Tracer), но однажды /Account/ExternalLoginCallback вызывается в приложении ( у провайдера идентификации есть, что в качестве URL-адреса ACS) объект AuthenticationResponseGrant имеет значение NULL, и аутентификационный код ie никогда не генерируется.

Startup.cs код:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using Sustainsys.Saml2;
using Sustainsys.Saml2.Configuration;
using Sustainsys.Saml2.Metadata;
using Sustainsys.Saml2.Owin;
using Sustainsys.Saml2.WebSso;
using System;
using System.Security.Cryptography.X509Certificates;
using System.Web.Hosting;
using TestAuthCMPC.WebSite.Models;

namespace TestAuthCMPC.WebSite
{
    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });

            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            app.UseSaml2Authentication(GetSamlOptions());
        }

        private static Saml2AuthenticationOptions GetSamlOptions()
        {
            var provider_options = GetServiceProviderOptions();
            var options = new Saml2AuthenticationOptions(false)
            {
                SPOptions = provider_options
            };
            var idp = GetIDP(
                "ENTITY_ID_OMITTED", 
                providerOptions, 
                new Uri("SSO_URL_OMITTED"), 
                "~/App_Data/saml_cert.crt");
            options.IdentityProviders.Add(idp);
            new Federation("http://localhost:64484/Federation", true, options);
            return options;
        }

        private static IdentityProvider GetIDP(string entityId, SPOptions providerOptions, Uri ssoUri, string certificatePath)
        {
            var idp = new IdentityProvider(new EntityId(entityId), providerOptions)
            {
                AllowUnsolicitedAuthnResponse = true,
                Binding = Saml2BindingType.HttpRedirect,
                SingleSignOnServiceUrl = ssoUri
            };
            var cert_path = HostingEnvironment.MapPath(certificatePath);
            var certificate = new X509Certificate2(cert_path);
            idp.SigningKeys.AddConfiguredKey(certificate);
            return idp;
        }

        private static SPOptions GetServiceProviderOptions()
        {
            var options = new SPOptions
            {
                EntityId = new EntityId("ENTITY_ID_OMITTED"),
                ReturnUrl = new Uri("http://localhost:64484/Account/ExternalLoginCallback"),
            };
            var attribute_consuming_service = new AttributeConsumingService
            {
                IsDefault = true,
                ServiceNames = { new LocalizedName("Saml2", "en") }
            };
            var requested_attr = new RequestedAttribute("urn:someName")
            {
                FriendlyName = "Some Name",
                IsRequired = true,
                NameFormat = RequestedAttribute.AttributeNameFormatUri
            };
            attribute_consuming_service.RequestedAttributes.Add(requested_attr);
            options.AttributeConsumingServices.Add(attribute_consuming_service);
            return options;
        }
    }
}

Ответ SAML от провайдера идентификации:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                ID="_9ee7823f-88e5-400b-8ae2-9abd48c39a94"
                Version="2.0"
                IssueInstant="2020-03-02T15:18:50.813Z"
                Destination="https://www.google.cl"
                >
    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">ENTITY_ID_OMITTED</saml:Issuer>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <Reference URI="#_9ee7823f-88e5-400b-8ae2-9abd48c39a94">
                <Transforms>
                    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"
                                             PrefixList="#default samlp saml ds xs xsi"
                                             />
                    </Transform>
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <DigestValue>oqed0BjPY97IykUdJznlrlb57J0=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>Hc2x/xLMtAnxfQIbs/lVXODsH6D1vfkghWQMsUXooy2TEcXQiJUYiU8T80ciCU70rMB/CBVwjjE7ArHh4l4UknmcS2ZNznyeIqdHM+JocOrH0TSzcd/BBznjAYDcI6PuzlSPFQEyaHtGqHm0Ya7JPibYLE3W8MIXo06lF9cWW9kBXu+YjBcANoplTz4K9so3fuclxOBQ/uPbJf11x7yYFcRIdZW6BJ6tcLxb5gI2/wT9wtEGZ1VaLPPXmnIou/avZmE0Jg/GLE12asssHlcqbCKQZCm6imi8xnuXUNhqiPmt342Icy0DidZSJGIo0GaRukMRyahoS64ZZdkSwfGKkQ==</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>MIID7zCCAtegAwIBAgIUWJQQ8iGfhdHnm/2zx49/8FQEu+owDQYJKoZIhvcNAQELBQAwgYYxCzAJBgNVBAYTAkNMMRYwFAYDVQQIDA1NZXRyb3BvbGl0YW5hMREwDwYDVQQHDAhTYW50aWFnbzESMBAGA1UECgwJQ01QQyBTLkEuMRQwEgYDVQQLDAtHZXJlbmNpYSBUSTEiMCAGCSqGSIb3DQEJARYTY2FybG9zLnNhZXpAY21wYy5jbDAeFw0yMDAyMjUwMjU1MTFaFw0yMTAyMjQwMjU1MTFaMIGGMQswCQYDVQQGEwJDTDEWMBQGA1UECAwNTWV0cm9wb2xpdGFuYTERMA8GA1UEBwwIU2FudGlhZ28xEjAQBgNVBAoMCUNNUEMgUy5BLjEUMBIGA1UECwwLR2VyZW5jaWEgVEkxIjAgBgkqhkiG9w0BCQEWE2Nhcmxvcy5zYWV6QGNtcGMuY2wwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCv5KqzSNTBRk0VRzdqPcc4mKJ6RPYO2IPH1T8wSkfuqYFJLHONk+qkbQuROyj9c6vXx1L4KNSc/hov8bdg5WCK0uiuc7GDPuoRRrQYPBZGzM9NJMnQYHXRvXNNyriodhdvVRLyBGkxodtWvhaOUZxaC5C+P3fqhEeYAsggKblyajYwLzFR890rYk029jTnEXFCFDfoFv+7dWp8zbgp8txXkFsA79I+bh/rrLl6n2+rVaKE+Gy9sWpI516j4bO8yuWMYaQfJGtrm/bo2ahJ+2+H06j1ICcFZdbgF04WPpuM6BYHKV1D2BlVKB69mU1jvgc/lthMa0vTx71MzweP3cNHAgMBAAGjUzBRMB0GA1UdDgQWBBRFtzc0KgnQMl1D/ho2ZI+GIeDK6DAfBgNVHSMEGDAWgBRFtzc0KgnQMl1D/ho2ZI+GIeDK6DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCIPjjJzjnc4koyUH0IK8P/c5cs82QyU2vpOIrQPxHyypqgbibNu20GFTQrIMA1mi+CQKa5K0AJNF7B88CkuBv1FmeJoxh4ppc+PeYJ3gt3bG6XZYBWoyluZ2afy4EcWxoqWEzdLmYF0hvWSZfwp+JgBriH5QLfzQCBFAymHcBaPGGZMTbF900TcOL8Rb0r3yfMy7ib1k7kLcSP7PB1mYE3ihqisPkS3vc9VxnzICAkxcm3H4Rap9GEu1fupi4dPxQEQSh7gq/bdDydDZpb1t6ijarr3uDA94HAPsCqNKzi6+ENxxaOi/I9xJOjLOq5acYIIVaiOZcQgNJ1rJrX76wv</X509Certificate>
            </X509Data>
        </KeyInfo>
    </Signature>
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    </samlp:Status>
    <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
                    Version="2.0"
                    ID="_cd6fc633-b1bc-43d2-a2e4-2a46fbe1b4c2"
                    IssueInstant="2020-03-02T15:18:50.86Z"
                    >
        <saml:Issuer>ENTITY_ID_OMITTED</saml:Issuer>
        <saml:Subject>
            <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">NAME@DOMAIN.COM</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData Recipient="http://localhost:64484/Account/ExternalLoginCallback" />
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions NotBefore="2020-03-02T15:18:50.86Z"
                         NotOnOrAfter="2020-03-02T15:48:50.86Z"
                         >
            <saml:AudienceRestriction>
                <saml:Audience>https://www.google.cl</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AuthnStatement AuthnInstant="2020-03-02T15:18:50.86Z">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
        <saml:AttributeStatement>
            <saml:Attribute Name="Names">
                <saml:AttributeValue>NAME</saml:AttributeValue>
            </saml:Attribute>
            <saml:Attribute Name="Lastname">
                <saml:AttributeValue>LASTNAME</saml:AttributeValue>
            </saml:Attribute>
            <saml:Attribute Name="SecondLastname">
                <saml:AttributeValue>SECONDLASTNAME</saml:AttributeValue>
            </saml:Attribute>
        </saml:AttributeStatement>
    </saml:Assertion>
</samlp:Response>

1 Ответ

1 голос
/ 03 марта 2020

Похоже, ваша конфигурация неверна. IdentityProvider должен отправлять ответ в / Saml2 / Acs, который является конечной точкой, где ответ обрабатывается и проверяется. Именно здесь создается AuthenticationResponseGrant, что приводит к установке внешнего входа в систему ie.

После этого промежуточное ПО Saml2 перенаправляет на /Account/ExternalLoginCallback.

Кроме того, вы должны удалить объект Federation из вашей конфигурации. Он создает больше IdentityProviders в фоновом режиме, то, что вам не нужно в такой настройке.

...