여러 JWT 베어러 인증 사용


89

ASP.NET Core 2에서 여러 JWT 토큰 발급자를 지원할 수 있습니까? 외부 서비스 용 API를 제공하고 싶습니다. 두 가지 JWT 토큰 소스 (Firebase 및 사용자 지정 JWT 토큰 발급자)를 사용해야합니다. ASP.NET core에서 Bearer 인증 체계에 대한 JWT 인증을 설정할 수 있지만 하나의 기관에 대해서만 설정할 수 있습니다.

  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
                };
        }

여러 발급자와 청중을 가질 수 있지만 여러 기관을 설정할 수 없습니다.


1
AFAIK는 JWT에 여러 속성을 추가 할 수 있습니다. 따라서 JWT에 두 개의 발급자 이름을 기록하는 것을 막을 수는 없습니다. 문제는 각 발급자가 다른 키를 사용하여 서명하는 경우 애플리케이션이 두 키를 모두 알아야한다는 점입니다.
Tim Biegeleisen

답변:


196

원하는 것을 완전히 얻을 수 있습니다.

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();
    });

코드와 그 코드의 차이점을 살펴 보겠습니다.

AddAuthentication 매개 변수가 없습니다

기본 인증 체계를 설정하면 모든 단일 요청에서 인증 미들웨어가 기본 인증 체계와 관련된 인증 처리기를 실행하려고합니다. 이제 두 가지 가능한 인증 체계가 있으므로 그중 하나를 실행할 필요가 없습니다.

다른 과부하 사용 AddJwtBearer

AddXXX인증을 추가하는 모든 단일 방법에는 여러 가지 오버로드가 있습니다.

이제 동일한 인증 방법을 두 번 사용하지만 인증 체계는 고유해야하므로 두 번째 오버로드를 사용해야합니다.

기본 정책 업데이트

요청이 더 이상 자동으로 인증되지 않으므로 [Authorize]일부 작업 에 속성을 추가하면 요청이 거부되고이 HTTP 401발행됩니다.

인증 처리기에 요청을 인증 할 수있는 기회를주고 싶기 때문에 이것이 우리가 원하는 것이 아니기 때문에 요청을 인증하기 위해 FirebaseCustom인증 체계를 모두 시도 해야 함 을 표시하여 권한 부여 시스템의 기본 정책을 변경합니다 .

그렇다고해서 어떤 행동을 더 제한하는 것을 막지는 않습니다. [Authorize]속성은 가지고 AuthenticationSchemes당신이 계획이 유효하는 인증을 무시할 수 있습니다 속성을.

더 복잡한 시나리오가있는 경우 정책 기반 권한을 사용할 수 있습니다 . 공식 문서가 훌륭하다고 생각합니다.

일부 작업은 Firebase에서 발급 한 JWT 토큰에서만 사용할 수 있으며 특정 값을 가진 클레임이 있어야합니다. 다음과 같이 할 수 있습니다.

// 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());
    });

그런 다음 [Authorize(Policy = "FirebaseAdministrators")]일부 작업에 사용할 수 있습니다 .

마지막으로 참고할 사항 : AuthenticationFailed이벤트 를 포착 하고 첫 번째 AddJwtBearer정책이 아닌 다른 것을 사용 IDX10501: Signature validation failed. Unable to match key...하는 경우 이는 시스템 AddJwtBearer이 일치 할 때까지 차례로 검사하여 발생 함을 볼 수 있습니다 . 이 오류는 일반적으로 무시할 수 있습니다.


4
헤더 값을 Firebase 또는 커스텀 솔루션에서 변경해야하나요? 즉. 그 대신 Authorization : Bearer <token>헤더가 Authorization : Firebase <token>예를 들어? 이 솔루션을 시도했을 때 " 'Bearer'체계에 대해 등록 된 인증 처리기가 없습니다."라는 오류가 발생했습니다.
Rush Frisby

4
아니요, 헤더는 변경할 필요가 없습니다. 오류 메시지는 존재하지 않는 인증 체계 (Bearer)를 참조하고 있음을 나타냅니다. 이 예에서 등록 된 두 스키마는 .AddJwtBearer메서드 호출 의 첫 번째 인수 인 Firebase와 Custom 입니다.
Mickaël Derriey

6
안녕. 이 솔루션을 찾고있었습니다. 불행히도 "No authenticationScheme이 (가) 지정되지 않았고 DefaultChallengeScheme을 찾을 수 없습니다"예외가 발생했습니다. options.DefaultPolicy가 정상적으로 설정되었습니다. 어떤 아이디어?
terjetyl

13
이것은 매우 도움이되는 답변이었고, 내가 본 많은 것을 곳곳에 모아 놓았습니다.
Aron W.

2
@TylerOhlsen이 올바르지 않습니다. 설명하는 경우에 사용되지만 유일한 것은 아닙니다. 엔드 포인트 수준에서 인증 요구 사항을 지정하지 않고 MVC 컨트롤러 및 / 또는 작업을 빈 [Authorize]속성으로 장식하는 경우에도 사용됩니다 .
Mickaël Derriey

5

이것은 Mickaël Derriey의 대답의 확장입니다.

앱에는 내부 소스에서 해결하는 사용자 지정 권한 부여 요구 사항이 있습니다. Auth0을 사용했지만 OpenID를 사용하는 Microsoft 계정 인증으로 전환하고 있습니다. 다음은 ASP.Net Core 2.1 Startup에서 약간 편집 된 코드입니다. 미래의 독자를 위해, 이것은 지정된 버전에 대해이 글을 쓰는 시점에서 작동합니다. 호출자는 Bearer 토큰으로 전달 된 수신 요청에서 OpenID의 id_token을 사용합니다. 이 질문과 답변이 저에게 도움이 된만큼 다른 사람이 신원 권한 변환을 시도하는 데 도움이되기를 바랍니다.

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());
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.