![](/img/trans.png)
[英]How to unit testing OidcSecurityService.checkAuth function with Jasmine?
[英]oidcSecurityService checkAuth method returns false when authenticated with Identity Server
我正在使用 Identity Server 4 和 ADFS 3 运行 Angular (v9) 应用程序。在我的 app.component 中,我调用 oidcSecurityService.checkAuth() ,它在到达站点时重定向到 Identity Server 并关闭到 ADFS - 有两个工作流
我的问题是身份服务器 cookie 是如何存在而令牌为空白的 - 我不确定一个没有另一个的存在的顺序
任何想法都将不胜感激
更新 1
执行摘要
app.component.ts
this.sub$ = this.oidcSecurityService
.checkAuth()
.subscribe((isAuthenticated) => {
if (!isAuthenticated) {
//navigate to route that executes oidcSecurityService.authorize();
this.router.navigate(['/autologin']);
}
}
...然后将其发送到 Identity Server 4,然后再发送到 ADFS
Startup.cs如下
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
}
)
.AddWsFederation(options =>
{
options.MetadataAddress = "https://fed.my-adfs.com/federationmetadata/2007-06/federationmetadata.xml";
options.Wtrealm = "https://auth.my-identity-server.com";
options.SaveTokens = true;
options.Events.OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.Wct = DateTimeOffset.UtcNow.ToString();
context.ProtocolMessage.Whr = "http://auth.header.com/IdSrv";
context.ProtocolMessage.Wtrealm = "https://auth.my-identity-server.com";
return Task.CompletedTask;
};
})
.AddCookie(options =>
{
options.Cookie.Path = "/";
options.Cookie.Name = ".AspNetCore.Cookies";
options.Cookie.Expiration = new TimeSpan(DateTime.Now.AddHours(1).Ticks);
});
请求被发送到 ADFS,ADFS 以消息响应 ExternalLogin
AccountController.cs
[HttpGet]
public async Task<IActionResult> ExternalLogin(string provider, string returnUrl)
{
// start challenge and roundtrip the return URL and
var props = new AuthenticationProperties()
{
RedirectUri = Url.Action("ExternalLoginCallback"),
Items =
{
{ "returnUrl", returnUrl },
{ "scheme", provider },
}
};
return Challenge(props, provider);
}
[HttpGet]
public async Task<IActionResult> ExternalLoginCallback()
{
// read external identity from the temporary cookie
//var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
// lookup our user and external provider info
var (user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
if (user == null)
{
// this might be where you might initiate a custom workflow for user registration
// in this sample we don't show how that would be done, as our sample implementation
// simply auto-provisions new external user
claims = result.Principal.Claims.ToList();
//var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
//if (userIdClaim == null)
//{
// userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
//}
//if (userIdClaim == null)
// user = AutoProvisionUser(provider, providerUserId, claims);
//else
// user = AutoProvisionUser(userIdClaim.Issuer, userIdClaim.Value, claims);
}
// this allows us to collect any additonal claims or properties
// for the specific prtotocols used and store them in the local auth cookie.
// this is typically used to store data needed for signout from those protocols.
List<Claim> additionalLocalClaims = claims; //new List<Claim>();
var localSignInProps = new AuthenticationProperties();
//ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
//ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
//ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);
// issue authentication cookie for user
await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username));
//await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, localSignInProps, additionalLocalClaims.ToArray());
// issue authentication cookie for user
var identityServerUser = new IdentityServerUser(user.SubjectId)
{
DisplayName = user.Username,
IdentityProvider = provider,
AdditionalClaims = additionalLocalClaims
};
await HttpContext.SignInAsync(identityServerUser, result.Properties);
// delete temporary cookie used during external authentication
//await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
// validate return URL and redirect back to authorization endpoint or a local page
var returnUrl = result.Properties.Items["returnUrl"];
if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return new RedirectResult(returnUrl);
}
关于授权服务器上的日志,这些非常冗长,因为问题在于客户端正在发生的事情,我不确定它们是否提供有关策略的更多细节 - 换句话说,我认为问题更多的是上面提到的策略 - 即虽然上述方法生成了所需的 cookie,但这如何转化为 oidcSecurityService 能够检查的令牌
更新 2
(还在 ExternalLoginCallback 方法中添加了代码)
我在身份服务器日志中收到以下条目
AuthenticationScheme:Identity.Application 已成功通过身份验证。
...但是,当代码到达 ExternalLogin 时,我得到了
AuthenticationScheme:Identity.Application 未通过身份验证。
它是如何在工作流程的早期通过身份验证但后来却不是 - 因此,当执行 ExternalLoginCallback 代码时,它会尝试根据 ExternalCookieAuthenticationScheme 对用户进行身份验证,如下所示:-
var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
...这失败了,因为用户不再经过身份验证
更新 3
[14:23:56 DBG] Persisted Grants Request Options: Microsoft.Azure.Documents.Client.RequestOptions
[14:23:56 DBG] Ensure Persisted Grants (ID:PersistedGrants) collection exists...
[14:23:56 DBG] PersistedGrants Creation Results: OK
[14:23:56 INF] Executing action method MI.ParentReporting.AuthorizationServer.Controllers.AccountController.ExternalLoginCallback (MI.ParentReporting.AuthorizationServer) with arguments (null) - ModelState is Valid
[14:23:56 DBG] AuthenticationScheme: Cookies was successfully authenticated.
...
[14:23:56 INF] FindUserFromExternalProvider-claim-type: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
[14:23:56 INF] FindUserFromExternalProvider-claim-value: xxxxNamexxxx
[14:23:56 INF] FindUserFromExternalProvider-claim-type: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/applicationid
[14:23:56 INF] FindUserFromExternalProvider-claim-value: xxxxAppIdxxxx
[14:23:56 INF] FindUserFromExternalProvider-claim-type: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/applicationname
[14:23:56 INF] FindUserFromExternalProvider-claim-value: xxxxAppNamexxxx
[14:23:56 INF] FindUserFromExternalProvider-claim-type: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role
[14:23:56 INF] FindUserFromExternalProvider-claim-value: xxxxRolexxxx
[14:23:56 INF] FindUserFromExternalProvider-claim-type: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/username
[14:23:56 INF] FindUserFromExternalProvider-claim-value: xxxxUsernamexxxx
[14:23:56 INF] FindUserFromExternalProvider-claim-type: http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod
[14:23:56 INF] FindUserFromExternalProvider-claim-value: urn:oasis:names:tc:SAML:1.0:am:password
[14:23:56 INF] FindUserFromExternalProvider-claim-type: http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant
[14:23:56 INF] FindUserFromExternalProvider-claim-value: 2020-08-16T14:23:49.956Z
[14:23:56 ERR] An unhandled exception has occurred: Unknown userid
System.Exception: Unknown userid
at MI.ParentReporting.AuthorizationServer.Controllers.AccountController.FindUserFromExternalProvider(AuthenticateResult result) in c:\Builds\6\s\MI.ParentReporting.AuthorizationServer\Controllers\AccountController.cs:line 492
at MI.ParentReporting.AuthorizationServer.Controllers.AccountController.ExternalLoginCallback() in c:\Builds\6\s\MI.ParentReporting.AuthorizationServer\Controllers\AccountController.cs:line 327
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.Invoke(HttpContext context)
at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.Invoke(HttpContext context)
at NWebsec.AspNetCore.Middleware.Middleware.MiddlewareBase.Invoke(HttpContext context)
at NWebsec.AspNetCore.Middleware.Middleware.MiddlewareBase.Invoke(HttpContext context)
at NWebsec.AspNetCore.Middleware.Middleware.MiddlewareBase.Invoke(HttpContext context)
at NWebsec.AspNetCore.Middleware.Middleware.MiddlewareBase.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
更新 4
以下是对 idpinitiatedsignon 的调用返回的令牌(wresult)(您会注意到 applicationid 和 userid 声明是 Guid)
<?xml version="1.0" encoding="UTF-8"?>
<trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:RequestSecurityTokenResponse Context="14a9edee-4545-6767-8989-f056689bbba9">
<trust:Lifetime>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2020-08-17T06:43:10.785Z</wsu:Created>
<wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2020-08-17T07:43:10.785Z</wsu:Expires>
</trust:Lifetime>
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>http://fed.my-adfs.com/adfs/services/trust</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<trust:RequestedSecurityToken>
<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_d56a3e1b-4545-6767-8989-0412df22d292" IssueInstant="2020-08-17T06:43:10.785Z" Version="2.0">
<Issuer>http://auth.header.com/IdSrv</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/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#_d56a3e1b-4545-6767-8989-0412df22d292">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>wzdbJxxxxxxxxxxxxxxxxxxxxxxxxxxxxxigSBSqq5c=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>geh3N+ag846uxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxkgV2gVrybPg==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIIvTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxG14YZl9</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<Subject>
<NameID>xxxxMyNameIdxxxx</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer" />
</Subject>
<Conditions NotBefore="2020-08-17T06:43:10.785Z" NotOnOrAfter="2020-08-17T07:43:10.785Z">
<AudienceRestriction>
<Audience>http://fed.my-adfs.com/adfs/services/trust</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/username">
<AttributeValue>xxxxMyUserNamexxxx</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role">
<AttributeValue>xxxxMyRolexxxx</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/applicationid">
<AttributeValue>7df29e67-4545-6767-8989-4463eafca398</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/applicationname">
<AttributeValue>xxxxMyAppNamexxxx</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/userid">
<AttributeValue>5b00eedc-4545-6767-8989-c6586a377ffd</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/lastactivitydate">
<AttributeValue>8/17/2020 2:42:54 AM</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/profileid">
<AttributeValue>33333</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sessiondatetime">
<AttributeValue>8/17/2020 2:42:54 AM</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/userfirstname">
<AttributeValue>xxxxMyFirstNamexxxx</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/userlastname">
<AttributeValue>xxxxMyLastNamexxxx</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
<AttributeValue>xxxxMyNamexxxx</AttributeValue>
</Attribute>
</AttributeStatement>
<AuthnStatement AuthnInstant="2020-08-17T06:42:57.203Z">
<AuthnContext>
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
</trust:RequestedSecurityToken>
<trust:RequestedAttachedReference>
<SecurityTokenReference xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:d4p1="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" d4p1:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0">
<KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID">_d56a3e1b-4545-6767-8989-0412df22d292</KeyIdentifier>
</SecurityTokenReference>
</trust:RequestedAttachedReference>
<trust:RequestedUnattachedReference>
<SecurityTokenReference xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:d4p1="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" d4p1:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0">
<KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID">_d56a3e1b-4545-6767-8989-0412df22d292</KeyIdentifier>
</SecurityTokenReference>
</trust:RequestedUnattachedReference>
<trust:TokenType>urn:oasis:names:tc:SAML:2.0:assertion</trust:TokenType>
<trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>
<trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
</trust:RequestSecurityTokenResponse>
</trust:RequestSecurityTokenResponseCollection>
以下是对 signin-wsfed 的调用返回的结果(看起来 applicationid 声明已被翻译,而 userid 声明已被删除)
<?xml version="1.0" encoding="UTF-8"?>
<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:Lifetime>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2020-08-17T06:43:11.046Z</wsu:Created>
<wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2020-08-17T07:43:11.046Z</wsu:Expires>
</t:Lifetime>
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>https://auth.my-identity-server.com</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<t:RequestedSecurityToken>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" MajorVersion="1" MinorVersion="1" AssertionID="_42406433-4545-6767-8989-be94f93d551c" Issuer="http://fed.my-adfs.com/adfs/services/trust" IssueInstant="2020-08-17T06:43:11.061Z">
<saml:Conditions NotBefore="2020-08-17T06:43:11.046Z" NotOnOrAfter="2020-08-17T07:43:11.046Z">
<saml:AudienceRestrictionCondition>
<saml:Audience>https://auth.my-identity-server.com</saml:Audience>
</saml:AudienceRestrictionCondition>
</saml:Conditions>
<saml:AttributeStatement>
<saml:Subject>
<saml:SubjectConfirmation>
<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Attribute xmlns:a="http://schemas.xmlsoap.org/ws/2009/09/identity/claims" AttributeName="name" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims" a:OriginalIssuer="http://auth.header.com/IdSrv">
<saml:AttributeValue>xxxxMyNamexxxx</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute AttributeName="applicationid" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
<saml:AttributeValue>xxxxMyAppIdxxxx</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute AttributeName="applicationname" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
<saml:AttributeValue>xxxxMyAppNamexxxx</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute xmlns:a="http://schemas.xmlsoap.org/ws/2009/09/identity/claims" AttributeName="role" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims" a:OriginalIssuer="http://auth.header.com/IdSrv">
<saml:AttributeValue>xxxxMyRolexxxx</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute xmlns:a="http://schemas.xmlsoap.org/ws/2009/09/identity/claims" AttributeName="username" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims" a:OriginalIssuer="http://auth.header.com/IdSrv">
<saml:AttributeValue>xxxxMyUserNamexxxx</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute xmlns:a="http://schemas.xmlsoap.org/ws/2009/09/identity/claims" AttributeName="userlastname" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims" a:OriginalIssuer="http://auth.header.com/IdSrv">
<saml:AttributeValue>xxxxMyFirstNamexxxx</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute xmlns:a="http://schemas.xmlsoap.org/ws/2009/09/identity/claims" AttributeName="userfirstname" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims" a:OriginalIssuer="http://auth.header.com/IdSrv">
<saml:AttributeValue>xxxxMyLastNamexxxx</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
<saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password" AuthenticationInstant="2020-08-17T06:42:57.203Z">
<saml:Subject>
<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="#_42406433-4545-6767-8989-be94f93d551c">
<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>mwWAxixxxxxxxxxxxxxxxxxxxxxxxxxxxFAt7xen8VE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>30xaIbQ9SxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxhINHESWbg==</ds:SignatureValue>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>MIIC2jCCAcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlMQB80pi/zJZeo=</X509Certificate>
</X509Data>
</KeyInfo>
</ds:Signature>
</saml:Assertion>
</t:RequestedSecurityToken>
<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
</t:RequestSecurityTokenResponse>
我假设“sub”(以及 sid、idp 等)声明也应该在这些声明中 - 如果是这样,配置的最终结果看起来不像包括这些(sub、sid、idp 等) -这很奇怪,因为我收到了一些声明,例如“http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod”和“http://schemas.microsoft.com/ws/2008” /06/identity/claims/authenticationinstant”以及一些属性,如“.AuthScheme”
更新 5
如上所述,我已经针对 ADFS 进行了身份验证,并且我拥有我需要的所有自定义声明 - 因为我缺少一些细节(子等)我在 ExternalLoginCallback 中创建了代码,围绕创建具有所需细节的新用户(新生成的subjectId 和 id_token)
[HttpGet]
public async Task<IActionResult> ExternalLoginCallback()
{
var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
// lookup our user and external provider info
var (user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
if (user == null)
{
// this might be where you might initiate a custom workflow for user registration
// in this sample we don't show how that would be done, as our sample implementation
// simply auto-provisions new external user
claims = result.Principal.Claims.ToList();
var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
if (userIdClaim == null)
{
userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
}
if (userIdClaim == null)
user = AutoProvisionUser(provider, providerUserId, claims);
else
user = AutoProvisionUser(userIdClaim.Issuer, userIdClaim.Value, claims);
}
// this allows us to collect any additonal claims or properties
// for the specific prtotocols used and store them in the local auth cookie.
// this is typically used to store data needed for signout from those protocols.
List<Claim> additionalLocalClaims = claims; //new List<Claim>();
var localSignInProps = new AuthenticationProperties();
ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
//ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
//ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("rlyaKithdrYVl6Z80ODU350md")); //Secret
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken("https://auth.my-identity-server.com",
"https://client.my-angular-application.com",
claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
var generatedToken = new
{
access_token = new JwtSecurityTokenHandler().WriteToken(token),
expires_in = 600000,
token_type = "bearer"
};
var id_token = JsonConvert.SerializeObject(generatedToken, new JsonSerializerSettings {Formatting = Formatting.Indented});
localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = id_token } });
//issue authentication cookie for user
await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username));
await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, localSignInProps, additionalLocalClaims.ToArray());
// delete temporary cookie used during external authentication
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return new RedirectResult("https://client.my-angular-application.com/");
}
全部成功运行 - 我看到我添加到新用户的所有字段并且新用户已登录(我在 Identity Server 日志中看到消息“AuthenticationScheme:Identity.Application 已登录”)。 但是,当我重定向到我的 Angular(客户端)应用程序时,我仍然没有进行身份验证(使用 oidcSecurityService.checkAuth),(因此看不到声明等)。 我在 Identity Server 4 网站中看到了 cookie - 我错过了在 Angular 网站进行身份验证时应该如何看到它
任何想法都非常感谢
在您的 ExternalLoginCallback 方法中,您不应该使用 IdentityServer 登录外部用户,因此它可以向客户端(Angular?)发出自己的访问令牌
包括像这样的代码
// issue authentication cookie for user
var isuser = new IdentityServerUser(user.SubjectId)
{
DisplayName = user.Username,
IdentityProvider = provider,
AdditionalClaims = additionalLocalClaims
};
await HttpContext.SignInAsync(isuser, localSignInProps);
否则,你为什么只在该方法中进行重定向?
这是一个相当不寻常的案例,主要是由于(如前所述)一些声明在使用 ADFS 进行身份验证后没有出现(至关重要的是 sub 声明) - 在我针对 ADFS 进行身份验证并创建身份服务器身份验证 cookie 之后的问题是逻辑在 Identity Server ProfileService 中需要调整以首先将其标记为活动(更改搜索以查找用户名 [我正在返回] 而不是子用户名),然后当它获得声明时,获取正在填充到 ExternalLoginCallback 中的声明 - 我的在用户级别而不是 ClaimsPrincipal 级别
我必须说我花了一段时间才了解 OidcSecurityService 和 IdentityServer4 之间的交互以及我处理 ADFS 3(而不是支持 OpenId 的 ADFS 4)的其他边缘情况
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.