Примеры OpenIddict - добавьте уникальное имя в id_token - PullRequest
0 голосов
/ 24 июня 2019

Я играю с образцом RefreshFlow OpenIddict-Samples.Работает отлично.Я заметил, что в Angular-моделях есть ProfileModel, который заполняется из JWT_Decode id_token:

export interface ProfileModel {
sub: string;
jti: string;
useage: string;
at_hash: string;
nbf: number;
exp: number;
iat: number;
iss: string;

unique_name: string;
email_confirmed: boolean;
role: string[];

}

Я не вижу, где на сервере заполняется уникальное имя,У меня есть требование для этого поля, и я попытался применить значение здесь:

        [HttpPost("~/connect/token"), Produces("application/json")]
    public async Task<IActionResult> Exchange([ModelBinder(typeof(OpenIddictMvcBinder))] OpenIdConnectRequest request)
    {
        if (request.IsPasswordGrantType())
        {
            var user = await _userManager.FindByNameAsync(request.Username);
            if (user == null)
            {
                return BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username/password couple is invalid."
                });
            }

            // Validate the username/password parameters and ensure the account is not locked out.
            var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password, lockoutOnFailure: true);
            if (!result.Succeeded)
            {
                return BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username/password couple is invalid."
                });
            }

            var properties = new AuthenticationProperties(new Dictionary<string, string>
            {
                { "unique_name", "hello World!" }
            });

            // Create a new authentication ticket.
            var ticket = await CreateTicketAsync(request, user, properties);

            return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
        }

Это где мне нужно добавить его?Ранее я прокрутил свой собственный создатель токенов, используя JwtSecureDataFormat: ISecureDataFormat, и добавил поле в качестве свойства.

Как я могу добавить его с помощью OpenIddict / ASOS?

Спасибо!

1 Ответ

0 голосов
/ 30 июня 2019

Так что я понял, как добиться в основном того, чего хотел !!

Мне действительно не нужно было специально добавлять «уникальное_имя» к токену, а просто добавить больше утверждений, чем то, что стандартная среда Identity добавляет для вас.

Вот как я это сделал:

Создание пользовательского SignInManager:

public class OpenIdictSignInManager<TUser> : SignInManager<TUser> where TUser : IdentityUser
{
    public OpenIdictSignInManager(
        UserManager<TUser> userManager,
        IHttpContextAccessor contextAccessor,
        IUserClaimsPrincipalFactory<TUser> claimsFactory,
        IOptions<IdentityOptions> optionsAccessor,
        ILogger<SignInManager<TUser>> logger,
        IAuthenticationSchemeProvider schemes) : base(userManager,
                                                        contextAccessor, 
                                                        claimsFactory, 
                                                        optionsAccessor, 
                                                        logger, 
                                                        schemes)
    {
    }

    public override async Task<ClaimsPrincipal> CreateUserPrincipalAsync(TUser user)
    {
        var principal = await base.CreateUserPrincipalAsync(user);

        var identity = (ClaimsIdentity)principal.Identity;

        identity.AddClaim(new Claim(OpenIdConnectConstants.Claims.EmailVerified, user.EmailConfirmed.ToString().ToLower()));

        return principal;
    }
}

Затем применил новый SignInManager к конфигурации startup.cs:

        // Register the Identity services.
        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders()
            .AddSignInManager<OpenIdictSignInManager<ApplicationUser>>();

Затем добавлен пункт назначения заявки при создании заявки в AuthorizationController:

        // Note: by default, claims are NOT automatically included in the access and identity tokens.
        // To allow OpenIddict to serialize them, you must attach them a destination, that specifies
        // whether they should be included in access tokens, in identity tokens or in both.
        foreach (var claim in ticket.Principal.Claims)
        {
            // Never include the security stamp in the access and identity tokens, as it's a secret value.
            if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType)
            {
                continue;
            }

            var destinations = new List<string>();

            // Identity Token destinations only
            if (new List<string>
            {
                OpenIdConnectConstants.Claims.EmailVerified
            }.Contains(claim.Type))
            {
                destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken);
                claim.SetDestinations(destinations);
                continue;
            }

            destinations.Add(OpenIdConnectConstants.Destinations.AccessToken);

            // Only add the iterated claim to the id_token if the corresponding scope was granted to the client application.
            // The other claims will only be added to the access_token, which is encrypted when using the default format.
            if ((claim.Type == OpenIdConnectConstants.Claims.Name && ticket.HasScope(OpenIdConnectConstants.Scopes.Profile)) ||
                (claim.Type == OpenIdConnectConstants.Claims.Email && ticket.HasScope(OpenIdConnectConstants.Scopes.Email)) ||
                (claim.Type == OpenIdConnectConstants.Claims.Role && ticket.HasScope(OpenIddictConstants.Claims.Roles)))
            {
                destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken);
            }

            claim.SetDestinations(destinations);
        }

Мне понадобилось несколько дней, чтобы покопаться в коде и поискать в Google, чтобы придумать этот подход, поэтому я подумал, что поделюсь им и надеюсь, что это поможет кому-то еще:)

...