Я тестирую 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 токена