[c#] 여러 JWT 베어러 인증 사용

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

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



답변

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

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이 일치 할 때까지 차례로 검사하여 발생 함을 볼 수 있습니다 . 이 오류는 일반적으로 무시할 수 있습니다.


답변

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


답변