繁体   English   中英

oidcSecurityService checkAuth 方法在使用 Identity Server 进行身份验证时返回 false

[英]oidcSecurityService checkAuth method returns false when authenticated with Identity Server

我正在使用 Identity Server 4 和 ADFS 3 运行 Angular (v9) 应用程序。在我的 app.component 中,我调用 oidcSecurityService.checkAuth() ,它在到达站点时重定向到 Identity Server 并关闭到 ADFS - 有两个工作流

  • 用户输入 ADFS 的用户/密码进行身份验证,然后返回 Angular,所有内容都经过身份验证(填充令牌并且存在.AspNetCore.Cookies)
  • where the ADFS login is automated and returns back to Angular via callback to Identity Server and a redirect to Angular - the.AspNetCore.Cookies is present but fails the oidcSecurityService.checkAuth(), because the token is null

我的问题是身份服务器 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM