ASP.NET Core 1.0. Токен на предъявителя, не может получить доступ к пользовательским утверждениям

Я пытаюсь настроить аутентификацию Bearer для SPA с использованием ASP.NET Core 1.0. У меня почти получилось, что он работает для JwtToken с OpenIdConnect Server, но есть проблема, что мои пользовательские утверждения не возвращаются с токеном.

Моя логика Startup.cs для аутентификации следующая:

private void ConfigureAuthentication(IApplicationBuilder app)
{
    app.UseJwtBearerAuthentication(options =>
    {
        options.AutomaticAuthenticate = true;
        options.Authority = "http://localhost:53844";
        options.Audience = "http://localhost:53844";
        options.RequireHttpsMetadata = false;
    });

    app.UseOpenIdConnectServer(options =>
    {
        options.TokenEndpointPath = "/api/v1/token";
        options.AllowInsecureHttp = true;
        options.AuthorizationEndpointPath = PathString.Empty;
        options.Provider = new OpenIdConnectServerProvider
        {
            OnValidateClientAuthentication = context =>
            {
                context.Skipped();
                return Task.FromResult<Object>(null);
            },
            OnGrantResourceOwnerCredentials = async context =>
            {
                var usersService = app.ApplicationServices.GetService<IUsersService>();

                User user = usersService.getUser(context.Username, context.Password);

                var identity = new ClaimsIdentity(new List<Claim>(), OpenIdConnectServerDefaults.AuthenticationScheme);
                identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()));
                identity.AddClaim(new Claim(ClaimTypes.Name, user.Id.ToString()));
                identity.AddClaim(new Claim("myclaim", "4815162342"));

                var ticket = new AuthenticationTicket(
                    new ClaimsPrincipal(identity),
                    new AuthenticationProperties(),
                    context.Options.AuthenticationScheme);

                ticket.SetResources(new[] { "http://localhost:53844" });
                ticket.SetAudiences(new [] {"http://localhost:53844"});
                ticket.SetScopes(new [] {"email", "offline_access" });
                context.Validated(ticket);
            }
        };
    });
}

И access_token, и refresh_token генерируются успешно, и при передаче access_token в системе заголовков авторизации запрос считается авторизованным.

Единственная проблема заключается в том, что все претензии, кроме NameIdentifier, не передаются.

Я использую следующий код, чтобы получить свои требования для аутентифицированного запроса:

public class WebUserContext : IUserContext
{
    private readonly IHttpContextAccessor contextAccessor;

    public WebUserContext(IHttpContextAccessor contextAccessor)
    {
        this.contextAccessor = contextAccessor;
    }

    public long UserId
    {
        get
        {
            ClaimsIdentity identity = Principal?.Identity as ClaimsIdentity;

            if (identity == null)
            {
                return -1;
            }

            Claim claim = identity.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name); // There is no such claim in claims collection
            return long.Parse(claim.Value);
        }
    }

    private ClaimsPrincipal Principal => contextAccessor.HttpContext.User as ClaimsPrincipal;
}

В чем причина, по которой мои претензии не были переданы или извлечены из токена?

1 ответ

Решение

В чем причина, по которой мои претензии не были переданы или извлечены из токена?

Безопасность.

В отличие от OAuthAuthorizationServerMiddleware ASOS не предполагает, что токены доступа всегда используются вашими собственными серверами ресурсов (хотя я согласен, что это распространенный сценарий) и отказывается сериализировать заявки, в которых явно не указано "место назначения", чтобы избежать утечки конфиденциальных данных неавторизованным сторонам.

Поскольку JWT является форматом по умолчанию в бета-версии ASOS ( но не в следующей бета-версии), вы также должны помнить, что даже клиентские приложения (или пользователи) могут читать ваши маркеры доступа.

По этой причине вы должны явно прикрепить "пункт назначения" к своим претензиям:

identity.AddClaim(ClaimTypes.Name, "Pinpoint", destination: "id_token token");

Уточнить id_token сериализовать претензию в идентификационный токен, token сериализовать его в токене доступа или в обоих, чтобы сериализовать его в обоих токенах (нет эквивалента для кодов авторизации или токенов обновления, поскольку они всегда зашифрованы и читаются только самим сервером авторизации)

Другие вопросы по тегам