Birden çok JWT Taşıyıcı Kimlik Doğrulaması kullan


89

ASP.NET Core 2'de birden çok JWT Token vericisini desteklemek mümkün müdür? Harici hizmet için bir API sağlamak istiyorum ve iki JWT jeton kaynağı kullanmam gerekiyor: Firebase ve özel JWT jetonu verenler. ASP.NET çekirdeğinde, Taşıyıcı kimlik doğrulama şeması için JWT kimlik doğrulamasını ayarlayabilirim, ancak yalnızca bir Yetki için:

  services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://securetoken.google.com/my-firebase-project"
            options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidIssuer = "my-firebase-project"
                    ValidateAudience = true,
                    ValidAudience = "my-firebase-project"
                    ValidateLifetime = true
                };
        }

Birden fazla yayıncı ve izleyiciye sahip olabilirim, ancak birkaç Yetki belirleyemiyorum.


1
AFAIK, bir JWT'ye istediğiniz sayıda özellik ekleyebilirsiniz. Yani, sizi bir JWT'ye iki yayıncı adını kaydetmekten alıkoyan hiçbir şey yoktur. Sorun, her yayıncı imzalamak için farklı bir anahtar kullanıyorsa, uygulamanızın her iki anahtarı da bilmesi gerekeceğinden kaynaklanmaktadır.
Tim Biegeleisen

Yanıtlar:


196

İstediğini tamamen başarabilirsin:

services
    .AddAuthentication()
    .AddJwtBearer("Firebase", options =>
    {
        options.Authority = "https://securetoken.google.com/my-firebase-project"
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = "my-firebase-project"
            ValidateAudience = true,
            ValidAudience = "my-firebase-project"
            ValidateLifetime = true
        };
    })
    .AddJwtBearer("Custom", options =>
    {
        // Configuration for your custom
        // JWT tokens here
    });

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();
    });

Kodunuz ile bunun arasındaki farkları gözden geçirelim.

AddAuthentication parametresi yok

Varsayılan bir kimlik doğrulama şeması ayarlarsanız, her bir istekte kimlik doğrulama ara yazılımı, varsayılan kimlik doğrulama şemasıyla ilişkili kimlik doğrulama işleyicisini çalıştırmayı deneyecektir. Artık iki opssible kimlik doğrulama şemasına sahip olduğumuz için, bunlardan birini çalıştırmanın bir anlamı yok.

Başka bir aşırı yükleme kullanın AddJwtBearer

AddXXXBir kimlik doğrulama eklemek için her bir yöntemin birkaç aşırı yüklemesi vardır:

Şimdi, aynı kimlik doğrulama yöntemini iki kez kullandığınızdan, ancak kimlik doğrulama şemalarının benzersiz olması gerektiğinden, ikinci aşırı yüklemeyi kullanmanız gerekir.

Varsayılan politikayı güncelleyin

İstekler artık otomatik olarak doğrulanmayacağından [Authorize], bazı eylemlere öznitelikler koymak , isteklerin reddedilmesine neden olacak ve bir HTTP 401verilecektir.

Biz doğrulama işleyicileri isteği doğrulamak için bir şans vermek istiyoruz, çünkü bizim istediğimiz olmadığı için, biz de belirterek yetkilendirme sisteminin varsayılan politikasını değiştirmesi Firebaseve Customkimlik doğrulama düzenleri edilmelidir çalıştı isteği doğrulamak için.

Bu, bazı eylemlerde daha kısıtlayıcı olmanızı engellemez; [Authorize]özniteliği vardır AuthenticationSchemessen şemaları geçerli olan kimlik doğrulama geçersiz kılmak için izin verir özelliği.

Daha karmaşık senaryolarınız varsa, ilke tabanlı yetkilendirmeden yararlanabilirsiniz . Resmi belgelerin harika olduğunu düşünüyorum.

Bazı işlemlerin yalnızca Firebase tarafından verilen JWT jetonları için geçerli olduğunu ve belirli bir değere sahip bir hak talebinin olması gerektiğini varsayalım; bunu şu şekilde yapabilirsin:

// Authentication code omitted for brevity

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();

        options.AddPolicy("FirebaseAdministrators", new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase")
            .RequireClaim("role", "admin")
            .Build());
    });

Daha sonra [Authorize(Policy = "FirebaseAdministrators")]bazı eylemlerde kullanabilirsiniz .

Unutulmaması gereken son bir nokta: AuthenticationFailedOlayları yakalıyorsanız ve ilk AddJwtBearerpolitikadan başka herhangi bir şey kullanıyorsanız , IDX10501: Signature validation failed. Unable to match key...bunun nedeni sistemin AddJwtBearerbir eşleşme elde edene kadar her birini sırayla kontrol etmesi olduğunu görebilirsiniz . Hata genellikle göz ardı edilebilir.


4
Bu, başlık değerinin firebase'den veya özel çözümden değiştirilmesini gerektiriyor mu? yani. bunun yerine örneğin Authorization : Bearer <token>başlık olabilir Authorization : Firebase <token>mi? Bu çözümü denediğimde şu hatayı aldım: "'Taşıyıcı' şeması için hiçbir kimlik doğrulama işleyicisi kayıtlı değil."
Rush Frisby

4
Hayır, başlıkların değişmesine gerek yok. Hata mesajı, var olmayan bir kimlik doğrulama şemasından (Taşıyıcı) bahsettiğinizi gösterir. Örneklerimizde, iki kayıtlı şema, .AddJwtBeareryöntem çağrılarının ilk argümanları olan Firebase ve Custom'dır .
Mickaël Derriey

6
Selam. Sadece bu çözümü arıyordum. Maalesef "AuthenticChallengeScheme belirtilmedi ve DefaultChallengeScheme bulunamadı" istisnası alıyorum. options.DefaultPolicy ayarlandı. Herhangi bir fikir?
terjetyl

13
Bu son derece yararlı bir cevaptı ve gördüklerimin çoğunu her yerde parçalar halinde bir araya getirdi.
Aron W.

2
@TylerOhlsen bu doğru değil; tarif ettiğiniz durumda kullanılacak olsa da, tek değil. Uç nokta düzeyinde bir yetkilendirme gereksinimi belirtmezseniz, ancak MVC denetleyicilerini ve / veya eylemlerini boş bir [Authorize]öznitelikle dekore ederseniz de kullanılır .
Mickaël Derriey

5

Bu, Mickaël Derriey'in cevabının bir uzantısıdır.

Uygulamamızın dahili bir kaynaktan çözdüğümüz özel bir yetkilendirme gereksinimi vardır. Auth0 kullanıyorduk ancak OpenID kullanarak Microsoft Hesabı kimlik doğrulamasına geçiyoruz. İşte ASP.Net Core 2.1 Başlangıcımızdan biraz düzenlenmiş kod. Gelecekteki okuyucular için bu, belirtilen sürümler için bu yazı itibariyle çalışır. Arayan, bir Taşıyıcı belirteci olarak iletilen gelen isteklerde OpenID'den id_token'ı kullanır. Umarım bu soru ve cevabın bana yardımcı olduğu kadar kimlik otoritesini dönüştürmeye çalışan başka birine yardımcı olur.

const string Auth0 = nameof(Auth0);
const string MsaOpenId = nameof(MsaOpenId);

string domain = "https://myAuth0App.auth0.com/";
services.AddAuthentication()
        .AddJwtBearer(Auth0, options =>
            {
                options.Authority = domain;
                options.Audience = "https://myAuth0Audience.com";
            })
        .AddJwtBearer(MsaOpenId, options =>
            {
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateAudience = true,
                    ValidAudience = "00000000-0000-0000-0000-000000000000",

                    ValidateIssuer = true,
                    ValidIssuer = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0",

                    ValidateIssuerSigningKey = true,
                    RequireExpirationTime = true,
                    ValidateLifetime = true,
                    RequireSignedTokens = true,
                    ClockSkew = TimeSpan.FromMinutes(10),
                };
                options.MetadataAddress = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0/.well-known/openid-configuration";
            }
        );

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes( Auth0, MsaOpenId )
        .Build();

    var approvedPolicyBuilder =  new AuthorizationPolicyBuilder()
           .RequireAuthenticatedUser()
           .AddAuthenticationSchemes(Auth0, MsaOpenId)
           ;

    approvedPolicyBuilder.Requirements.Add(new HasApprovedRequirement(domain));

    options.AddPolicy("approved", approvedPolicyBuilder.Build());
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.