从配置文件服务添加的声明未包含在asp.net,使用Duende Identity Server进行核心6身份验证

oknwwptz  于 2023-04-08  发布在  .NET
关注(0)|答案(1)|浏览(118)

我有下面的配置

public static IEnumerable<IdentityResource> GetIdentityResources=>
     new List<IdentityResource>
        {
            new IdentityResources.Profile(),
            new IdentityResources.OpenId(),
            new IdentityResources.Email(),
        };
    

    public static IEnumerable<ApiResource> ApiResources=>
        new List<ApiResource>
        {
            new ApiResource(AuthorizePolicy.apiScope, "Falcon Api")
        };
    

    public static IEnumerable<Client> Clients(IConfiguration configuration) =>
        new Client[]
        {
            new Client
            {
                ClientId = "Falcon_Identity_Server",
                ClientName = "FalconIdentityServer",
                AllowedCorsOrigins = CorsUris(configuration),
                AllowedGrantTypes = GrantTypes.Code,
                AllowAccessTokensViaBrowser = bool.Parse(configuration.GetSection("IdentityServer:Client:AllowAccessTokensViaBrowser").Value),
                IdentityTokenLifetime = Int32.Parse(configuration.GetSection("IdentityServer:Client:IdentityTokenLifetime").Value),
                AccessTokenLifetime = Int32.Parse(configuration.GetSection("IdentityServer:Client:AccessTokenLifetime").Value),
                RequireConsent = bool.Parse(configuration.GetSection("IdentityServer:Client:RequireConsent").Value),
                UpdateAccessTokenClaimsOnRefresh = bool.Parse(configuration.GetSection("IdentityServer:Client:UpdateAccessTokenClaimsOnRefresh").Value),
                RedirectUris = LocalRedirectUris(configuration),
                PostLogoutRedirectUris = LocalRedirectUris(configuration),
                AllowedScopes = AllowedScopes(),
                AllowOfflineAccess = bool.Parse(configuration.GetSection("IdentityServer:Client:AllowOfflineAccess").Value),
                AccessTokenType = AccessTokenType.Jwt,
                RequireClientSecret = bool.Parse(configuration.GetSection("IdentityServer:Client:RequireClientSecret").Value),
                RequirePkce = bool.Parse(configuration.GetSection("IdentityServer:Client:RequirePkce").Value),
                //AllowRememberConsent = true
            }
        };
    
    private static ICollection<string> AllowedScopes()
    {
        return new List<string>
        {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            IdentityServerConstants.StandardScopes.Email,
            AuthorizePolicy.apiScope
        };
    }
    
    // API scopes represent values that describe scope of access and can be requested by the scope parameter (OAuth)
    public static readonly IEnumerable<ApiScope> ApiScopes =
        new[]
        {
            new ApiScope(IdentityServerConstants.StandardScopes.OpenId),
            new ApiScope(IdentityServerConstants.StandardScopes.Profile),
            new ApiScope(IdentityServerConstants.StandardScopes.Email),
            new ApiScope(AuthorizePolicy.apiScope),
        };

配置文件服务

public class ProfileService : IProfileService
        {
            private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
            private readonly UserManager<ApplicationUser> _userManager;
            private readonly ILogger<ProfileService> Logger;
    
            public ProfileService(UserManager<ApplicationUser> userManager,
                IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,
                ILogger<ProfileService> logger)
            {
                _userManager = userManager;
                _claimsFactory = claimsFactory;
                Logger = logger;
            }
    
            public async Task GetProfileDataAsync(ProfileDataRequestContext context)
            {
                var sub = context.Subject?.GetSubjectId();
                if (sub == null) throw new Exception("No sub claim present");
    
                var user = await _userManager.FindByIdAsync(sub);
                if (user == null)
                {
                    Logger?.LogWarning("No user found matching subject Id: {0}", sub);
                }
                else
                {
                    var principal = await _claimsFactory.CreateAsync(user);
                    if (principal == null) throw new Exception("ClaimsFactory failed to create a principal");
                    context.IssuedClaims.AddRange(principal.Claims);
                }
                
            }
    
            public async Task IsActiveAsync(IsActiveContext context)
            {
                var sub = context.Subject?.GetSubjectId();
                if (sub == null) throw new Exception("No subject Id claim present");
    
                var user = await _userManager.FindByIdAsync(sub);
                if (user == null)
                {
                    Logger?.LogWarning("No user found matching subject Id: {0}", sub);
                }
    
                context.IsActive = user != null;
            }
        }

AuthorizationHandler中访问声明时,用户具有以下声明

然而,在令牌上它有更多的主张

{
  "iss": "https://localhost:5001",
  "nbf": 1651829483,
  "iat": 1651829483,
  "exp": 1651829683,
  "scope": [
    "openid",
    "profile",
    "email"
  ],
  "amr": [
    "pwd"
  ],
  "client_id": "Falcon_Identity_Server",
  "sub": "9717a359-f83b-43b3-97b3-2f04f1148988",
  "auth_time": 1651828196,
  "idp": "local",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "9717a359-f83b-43b3-97b3-2f04f1148988",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin@local.com",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "admin@local.com",
  "AspNet.Identity.SecurityStamp": "1999ca9c-398d-4ffe-907a-b1f1b5e8cbfe",
  "identityserver": "owner",
  "fb_product": "owner",
  "fb_order": "owner",
  "fb_payment": "owner",
  "sid": "215A4703E0D026F660C44D0BB7235EDA",
  "jti": "D5989213C1F6D659141D57D07AC2EFDF"
}

注册以下jwt

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // base-address of your identityserver
        options.Authority = "https://localhost:5001";

        // audience is optional, make sure you read the following paragraphs
        // to understand your options
        options.TokenValidationParameters.ValidateAudience = false;

        // it's recommended to check the type header to avoid "JWT confusion" attacks
        options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
    });

经办人

public class IdentityServerUserClaimHandler : AuthorizationHandler<IdentityServerUserClaimRequirement>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
            IdentityServerUserClaimRequirement requirement)
        {
            if (context.User.HasClaim(c => c.Type == requirement.ClaimType &&
                                           c.Value == requirement.ClaimValue))
                context.Succeed(requirement);
            return Task.CompletedTask;
        }
    }
q3qa4bjr

q3qa4bjr1#

默认情况下,ASP.NET不会将令牌中的所有声明传递给User(claimsPrincipal),因为它们中的大多数是内部OpenID-Connect声明。
要将声明放入User对象,则需要使用以下代码手动Map它们:

options.ClaimActions.MapUniqueJsonKey("website", "website");
options.ClaimActions.MapUniqueJsonKey("gender", "gender");
options.ClaimActions.MapUniqueJsonKey("birthdate", "birthdate");

(In AddJwtBearer或AddOpenIdconnect)
为了补充这个答案,我写了一篇博客文章,更详细地介绍了这个主题:Debugging OpenID Connect claim problems in ASP.NET Core

相关问题