IdentityServer4 с WSFedration (ADFS) - как получить saml: NameIdentifier в токен доступа? - PullRequest
0 голосов
/ 26 октября 2018

Я тестирую IdentityServer4 (с Quickstart.UI) с ADFS для входа в систему.Я добавил WSFederation к IdentityServer.Пока это работает нормально, я могу войти в систему своих пользователей, используя их учетные записи AD, и получить код авторизации от IdentityServer.После этого я также могу запросить свои токены доступа и обновления у IdentityServer.

Я добавил специальный валидатор, чтобы посмотреть, какой ответ я получу от ADFS.В этом утверждении saml, которое я получаю, я могу найти поле saml:NameIdentifier с именем SAM-Account-Name (Username) в нем (в моем примере я создал пользователя с именем 'bob').

Что я хочусделать сейчас, это добавить это имя в качестве заявки в токен доступа и обновления.Я хочу добавить следующее в токен:

'name' : 'bob'

Я попытался добавить службу настраиваемого профиля, используя .AddProfileService<MyProfileService>().После этого я могу добавить утверждение 'name' к токену, но не могу найти, где хранится saml:NameIdentifier.

Где хранится эта информация из ответа SAML?Есть ли простой способ получить доступ к этой информации без необходимости написания специального валидатора, который сохраняет эту информацию?

Вот ответ SAML, который я получаю из ADFS:

<saml:Assertion MajorVersion="1" MinorVersion="1" AssertionID="_322db7c2-08d3-4b9e-9a72-78f9867590bb" Issuer="http://adfs.adfstest.ch/adfs/services/trust" IssueInstant="2018-10-26T07:00:31.277Z" 
xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
<saml:Conditions NotBefore="2018-10-26T07:00:31.268Z" NotOnOrAfter="2018-10-26T08:00:31.268Z">
    <saml:AudienceRestrictionCondition>
        <saml:Audience>https://localhost:44384/
        </saml:Audience>
    </saml:AudienceRestrictionCondition>
</saml:Conditions>
<saml:AttributeStatement>
    <saml:Subject>
        <saml:NameIdentifier>bob</saml:NameIdentifier>
        <saml:SubjectConfirmation>
            <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer
            </saml:ConfirmationMethod>
        </saml:SubjectConfirmation>
    </saml:Subject>
    <saml:Attribute AttributeName="name" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
        <saml:AttributeValue>bob
        </saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute AttributeName="subject" AttributeNamespace="http://schemas.microsoft.com/2012/12/certificatecontext/field">
        <saml:AttributeValue>bob
        </saml:AttributeValue>
    </saml:Attribute>
</saml:AttributeStatement>
<saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" AuthenticationInstant="2018-10-26T06:19:07.801Z">
    <saml:Subject>
        <saml:NameIdentifier>bob
        </saml:NameIdentifier>
        <saml:SubjectConfirmation>
            <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer
            </saml:ConfirmationMethod>
        </saml:SubjectConfirmation>
    </saml:Subject>
</saml:AuthenticationStatement>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
        <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
        <ds:Reference URI="#_322db7c2-08d3-4b9e-9a72-78f9867590bb">
            <ds:Transforms>
                <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>qVbZ8br3sxDrjJT6e0o7OResejoDXvKJ0u6pQkvuXww=
            </ds:DigestValue>
        </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>oYWxMewu1YuYN9/QtcaYw+hsy6ZsYtv2QIalFkU9qRW/YP0wImYfzxyuFQEHbz8M7ZjdZD8dTUdlSSF9hH1xsApqovJ/4YHNUv0aNiYWsLLM6hEaREcD0Ed6AOLvXEW+iYEu7nFLhUXshiLZMCTPnDFN+ggT0kQce3NA3MZVe2j+q1S3vK4BWoMC7yQGV27mlQ4Bgdgt2fJHRRbd7x6oUUP/EGAv5u9VTfp+F2MIHeltnkh6vTvSawSe/uVVZMAMRiQ5U4JOlxQNKgCoI8yjdC/oDuOCJHywGWXzfbV6OiiI5ODp5I7BfTJNeYoyje019KFBavOODyEj7e+SLkMzQw==</ds:SignatureValue>
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <X509Data>
            <X509Certificate>MIIC3DCCAcSgAwIBAgIQYJnK0wTILKND20jkNsv1rzANBgkqhkiG9w0BAQsFADAqMSgwJgYDVQQDEx9BREZTIFNpZ25pbmcgLSBhZGZzLmFkZnN0ZXN0LmNoMB4XDTE4MDkyNzEzNTMzMFoXDTE5MDkyNzEzNTMzMFowKjEoMCYGA1UEAxMfQURGUyBTaWduaW5nIC0gYWRmcy5hZGZzdGVzdC5jaDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALSLwYE30RO5luQpJbuN2E0UvSA8Anci9NTVIdyEkcN9bJ2E6qP+y+oSV7lLy9ReyJBJyZqjVyeqWusSBmkmJVoVPLZWGzqbCvxiOkjwUnBMZm92G1R/0EVxOocm6CAilfXPpMkeBknol/PAGJhWvzKQgon9eEuAyPww6KX8E9fVw3rJJ8V8wLsHjzvLuQvhp8Dy7SoMlm6QPLeUQx/O9HxliIUjNxpARYhPAdL3DLusiPCu3ebmafVjCg0a79VldvZY1n7ZLaRsbbB785MTTjm7RocgLwGITuzSU2DGkg99VWPEZ+2Q1vcS6tS7U0Yl2HilsyFVEUPd1jV28n+7HKcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAk4wGudZyhvi0ciXadUb4Qlb8Utb8o7fjyy4m/VmfYZudGwvtB/ikAeLzdrTjpkOTZ66zTEzBZJ+m31P2D6+AXDTLhI9IEXuILt6CnXVJ6I6NVKzbs1AkedTI+1IusFZ6VeEEKikYU6k92/cXX8/Xd4H7rR8qwoF3PqAcral0t036IH1QbLBYodcTwAgzcfdc0n4vYuR0Q3GDOXeeXxlk6IK+Ec2xjrojn6LDre1soimTqmXvuGHfRCkFclrfVC64cjd1EzYwHYFB/by9rqis8Pq+5H2bOp16SW8yuQ6d99D3dm4OIaSi9VTgJ0w46BQkhxl1QNEZD18d8cIBLxrtKQ==
            </X509Certificate>
        </X509Data>
    </KeyInfo>
</ds:Signature>

Вот мой Startup.cs из IdentityServer:

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddIdentityServer()
            .AddDeveloperSigningCredential() // AddSigningCredential(cert) for productive environment
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryClients(Config.GetClients())
            .AddInMemoryPersistedGrants()
            .AddTestUsers(Config.GetUsers())
            .AddProfileService<MyProfileService>();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
        })
            .AddCookie(options =>
            {
                options.Cookie.Name = "aspnetcorewsfed";
            })
            .AddWsFederation(options =>
            {
                options.Wtrealm = "https://localhost:44384/";
                options.MetadataAddress = "https://adfs.adfstest.ch/FederationMetadata/2007-06/FederationMetadata.xml";
                options.RequireHttpsMetadata = false;
                options.CallbackPath = "/";
                options.SkipUnrecognizedRequests = true;
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
            });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseIdentityServer();

        app.UseStaticFiles();
        app.UseMvcWithDefaultRoute();
    }
}

А вот и служба пользовательского профиля:

public class MyProfileService : IProfileService
{
    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var claims = new List<Claim>
        {
            new Claim("name", "SomeName"),
        };

        context.IssuedClaims.AddRange(claims);
        return Task.FromResult(0);
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        context.IsActive = true;

        return Task.FromResult(0);
    }
}

Теперь полезная нагрузка токена выглядит следующим образом:

jwt.io токена

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...