Использование. NET промежуточного программного обеспечения JWT для проверки пользовательских токенов, а также Azure токенов - PullRequest
1 голос
/ 30 марта 2020

В настоящее время я использую стандартную аутентификацию NET с промежуточным программным обеспечением JWT для аутентификации пользователей. Azure AD является эмитентом токена. Так что мой Startup.cs выглядит примерно так:

            var authentication = new AuthenticationOptions();
            configuration.Bind("AzureAd", authentication);

            services
                .AddAuthentication(options =>
                {
                    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(options =>
                {
                    options.Authority = $"{authentication.Instance}{authentication.TenantId}";
                    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidAudience = $"{authentication.ClientId}",
                        ValidIssuer = $"{authentication.Instance}{authentication.TenantId}/v2.0"
                    };
                });

И я использую тег [Authorize] для защиты конечных точек. Теперь я хочу создать пользовательский JWT для пользователя, который уже вошел в систему. Для этого у меня есть следующий код:

            var username = User.Claims.FirstOrDefault(x => x.Type == "name").Value;
            var email = User.Claims.FirstOrDefault(x => x.Type == "preferred_username").Value;

            var authentication = new AuthenticationOptions
            {
                My client and tenant credentials
            };

            var mySecret = "someSecret";
            var mySecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(mySecret));

            var tokenHandler = new JwtSecurityTokenHandler();
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                {
                    new Claim("name", username),
                    new Claim("preferred_username", email)
                }),
                Issuer = $"{authentication.Instance}{authentication.TenantId}/v2.0",
                Audience = $"{authentication.ClientId}",
                SigningCredentials = new SigningCredentials(mySecurityKey, SecurityAlgorithms.HmacSha256Signature),
            };

            var tokenPlainText = tokenHandler.CreateToken(tokenDescriptor);
            var token = tokenHandler.WriteToken(tokenPlainText);

            return token;

Я хотел бы использовать [Authorize] тег для проверки как токенов, выданных Azure AD при входе пользователя в систему, так и пользовательского JWT, созданного моим кодом. Проблема в том (я предполагаю), что Azure подписывает токены закрытым ключом, к которому у меня нет доступа.

Можно ли включить, например, несколько параметров проверки в .AddJwtBearer, чтобы он проверял оба возможных способа подтверждения пользователя и предоставлял доступ в случае прохождения любого из них? Или есть способ создать собственный токен, который пройдет проверку уже на месте? Или, может быть, способ добавить еще один тег в конечную точку, чтобы он стал похож на [Authorize] || [CustomAuthorize], и если один из них пройдет, пользователь получит доступ?

1 Ответ

1 голос
/ 30 марта 2020

Не используется пользовательский токен JWT

Я не вижу необходимости в том, чтобы вам нужно было создавать свои собственные токены. AAD довольно хорошо справляется с управлением пользователями и их статусом входа в систему. В качестве возможной альтернативы вы также можете оценить cook ie аутентификация для этих вошедших в систему пользователей. Создание ваших собственных токенов JWT звучит слишком усиленно и, возможно, менее безопасно.

Проверка токенов из разных источников

Вы можете связать .AddJwtBearer вызовы, чтобы установить несколько источников токенов. Вы должны дать второму имя другой схемы. При этом вам необходимо выполнить специальную обработку после UseAuthentication, чтобы также проверить эту схему. Это, вероятно, самое чистое решение, которое также ближе всего к тому, что вы описываете.

services.AddAuthentication(options =>
{
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions =>
{
    //...
}).AddJwtBearer(_FallbackScheme, jwtOptions =>
{
    //...
});


// ...

app.UseAuthentication();
// https://github.com/aspnet/Security/issues/1847
app.Use(async (context, next) => {
    if (!context.User.Identity.IsAuthenticated)
    {
        var result = await context.AuthenticateAsync(_FallbackScheme);
        if (result.Succeeded)
        {
            context.User = result.Principal;
        }
    }
    await next();
});

Расширение утверждений

Если вы просто хотите добавить пару дополнительных утверждений во время выполнения, оно также может быть в порядке, чтобы сделать это во время выполнения. Однако это будет происходить при каждом вызове API, поэтому вам следует помнить об этом.

https://joonasw.net/view/adding-custom-claims-aspnet-core-2

...