Asp.net core 如何使Identity Server同时返回访问令牌和标识令牌?

Asp.net core 如何使Identity Server同时返回访问令牌和标识令牌?,asp.net-core,identityserver4,Asp.net Core,Identityserver4,我需要两者,因为我有很多声明,我想在客户端数据库中存储令牌,只使用没有声明的令牌(我想是identity one),在请求时,我将用大的替换小的(发送的,没有声明),这样请求就没有那么大了,我仍然可以使用声明进行API访问。当前仅返回访问令牌,标识令牌为空。以下是身份配置: public IdentityConfig(IConfiguration config) { ApiScopes = new List<ApiScope>(); Clien

我需要两者,因为我有很多声明,我想在客户端数据库中存储令牌,只使用没有声明的令牌(我想是identity one),在请求时,我将用大的替换小的(发送的,没有声明),这样请求就没有那么大了,我仍然可以使用声明进行API访问。当前仅返回访问令牌,标识令牌为空。以下是身份配置:

public IdentityConfig(IConfiguration config)
    {
        ApiScopes = new List<ApiScope>();
        Clients = new List<Client>();
        foreach (var apiScope in config.GetSection("IdentityConfig").GetSection("ApiScopes").GetChildren())
        {
            ApiScopes.Add(new ApiScope(apiScope.Value));
        }
        foreach (var client in config.GetSection("IdentityConfig").GetSection("Clients").GetChildren())
        {
            Clients.Add(new Client
            {
                ClientId = client["Id"],

                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,//can be moved to config
                ClientSecrets = { new Secret(client["Secret"].Sha256()) },//can be multiple
                AllowedScopes = new List<string> { IdentityServerConstants.StandardScopes.OpenId, "apiScope1", IdentityServerConstants.StandardScopes.Profile }//client.GetSection("AllowedScopes").GetChildren().Select(a => a.Value).ToList()
            });
        }
        Resources = new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
            new IdentityResources.Email()
        };
    }
我之所以编写自定义密码验证器,是因为我有一个遗留系统,它有自己的auth实现,不确定是否需要,但只是以防万一:

public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
    {
        try
        {
            var user = await _userRepository.FindByNameAsync(context.UserName);
            if (user != null)
            {
                if (!string.IsNullOrWhiteSpace(user.LegacyPasswordHash))
                {
                    var hashedPassword = GetLegacyHash(context.Password);
                    if (hashedPassword == user.LegacyPasswordHash)
                    {
                        context.Result = new GrantValidationResult(
                        subject: user.Id,
                        authenticationMethod: "custom",
                        claims: GetUserClaims(user));
                        return;
                    }
                }
                if (await _userRepository.CheckPasswordAsync(user, context.Password))
                {
                    context.Result = new GrantValidationResult(
                        subject: user.Id,
                        authenticationMethod: "custom",
                        claims: GetUserClaims(user));
                    return;
                }

                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Incorrect password");
                return;
            }
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "User does not exist.");
            return;
        }
        catch (Exception ex)
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid username or password");
        }
    }

很难在代码中看到它,但看起来您可能会混淆身份验证和授权。你说你使用声明进行API访问,这在我看来像是授权,你能详细说明一下你在访问令牌中提出了什么样的声明吗?是的,我需要它们进行授权。声明类似于“CanUseThisApi”,我在启动时这样定义它们:auth.AddPolicy(“CanUseThisApi”,policy=>policy.Requirecall(“CanUseThisApi”);并添加类似于上述API的内容:[Authorize(Policy=“CanUseThisApi”)]为什么要使用AllowedGrantTypes=GrantTypes.ResourceOwnerPassword?一个想法是,只有在使用代码流时才包含它?老实说,我尝试了不同的东西,而这一个看起来像是做了我想要的——它返回了令牌。我应该用什么?
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
    {
        try
        {
            var user = await _userRepository.FindByNameAsync(context.UserName);
            if (user != null)
            {
                if (!string.IsNullOrWhiteSpace(user.LegacyPasswordHash))
                {
                    var hashedPassword = GetLegacyHash(context.Password);
                    if (hashedPassword == user.LegacyPasswordHash)
                    {
                        context.Result = new GrantValidationResult(
                        subject: user.Id,
                        authenticationMethod: "custom",
                        claims: GetUserClaims(user));
                        return;
                    }
                }
                if (await _userRepository.CheckPasswordAsync(user, context.Password))
                {
                    context.Result = new GrantValidationResult(
                        subject: user.Id,
                        authenticationMethod: "custom",
                        claims: GetUserClaims(user));
                    return;
                }

                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Incorrect password");
                return;
            }
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "User does not exist.");
            return;
        }
        catch (Exception ex)
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid username or password");
        }
    }