Czy można obsługiwać wielu wystawców tokenów JWT w ASP.NET Core 2? Chcę zapewnić interfejs API dla usługi zewnętrznej i muszę korzystać z dwóch źródeł tokenów JWT - Firebase i niestandardowych wydawców tokenów JWT. W ASP.NET core mogę ustawić uwierzytelnianie JWT dla schematu autoryzacji okaziciela, ale tylko dla jednego organu:
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
};
}
Mogę mieć wielu wydawców i odbiorców, ale nie mogę ustawić kilku organów.
Odpowiedzi:
Możesz całkowicie osiągnąć to, czego chcesz:
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(); });
Przyjrzyjmy się różnicom między twoim kodem a tym.
AddAuthentication
nie ma parametruJeśli ustawisz domyślny schemat uwierzytelniania, przy każdym żądaniu oprogramowanie pośredniczące uwierzytelniania spróbuje uruchomić procedurę obsługi uwierzytelniania skojarzoną z domyślnym schematem uwierzytelniania. Ponieważ mamy teraz dwa możliwe schematy uwierzytelniania, nie ma sensu uruchamiać jednego z nich.
Użyj innego przeciążenia
AddJwtBearer
Każda
AddXXX
metoda dodawania uwierzytelniania ma kilka przeciążeń:Teraz, ponieważ dwukrotnie używasz tej samej metody uwierzytelniania, ale schematy uwierzytelniania muszą być unikatowe, musisz użyć drugiego przeciążenia.
Zaktualizuj zasady domyślne
Ponieważ żądania nie będą już automatycznie uwierzytelniane, nadanie
[Authorize]
atrybutów niektórym akcjom spowoduje odrzucenie żądań i wystawienieHTTP 401
ich.Ponieważ nie jest to, co chcemy, ponieważ chcemy dać przewodnicy uwierzytelnianie szansę uwierzytelnienia żądania, możemy zmienić domyślną politykę autoryzacji systemu, wskazując zarówno
Firebase
iCustom
uwierzytelniania schematy powinny być próbował uwierzytelnić prośbę.To nie przeszkadza ci być bardziej restrykcyjnymi w niektórych działaniach;
[Authorize]
atrybut maAuthenticationSchemes
właściwość, która pozwala zastąpić systemy uwierzytelniania, które są ważne.Jeśli masz bardziej złożone scenariusze, możesz skorzystać z autoryzacji opartej na zasadach . Uważam, że oficjalna dokumentacja jest świetna.
Wyobraźmy sobie, że niektóre akcje są dostępne tylko dla tokenów JWT wydanych przez Firebase i muszą mieć roszczenie o określonej wartości; możesz to zrobić w ten sposób:
// 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()); });
Możesz następnie użyć
[Authorize(Policy = "FirebaseAdministrators")]
do niektórych działań.Ostatnia uwaga: jeśli przechwytujesz
AuthenticationFailed
zdarzenia i używasz czegoś innego niż pierwszaAddJwtBearer
zasada, możesz zobaczyć.IDX10501: Signature validation failed. Unable to match key...
Jest to spowodowane tym, że system sprawdza każdąAddJwtBearer
z nich po kolei, aż uzyska dopasowanie. Błąd można zwykle zignorować.źródło
Authorization : Bearer <token>
tego nagłówek będzieAuthorization : Firebase <token>
na przykład? Kiedy wypróbowałem to rozwiązanie, otrzymałem błąd: „Żaden program obsługi uwierzytelniania nie jest zarejestrowany dla schematu 'Nośnik'.”.AddJwtBearer
wywołań metod.[Authorize]
atrybutem.To jest rozszerzenie odpowiedzi Mickaëla Derrieya.
Nasza aplikacja ma niestandardowy wymóg autoryzacji, który rozwiązujemy z wewnętrznego źródła. Używaliśmy Auth0, ale przechodzimy na uwierzytelnianie konta Microsoft przy użyciu OpenID. Oto nieco zmieniony kod z naszego uruchomienia ASP.Net Core 2.1. Dla przyszłych czytelników działa to od chwili pisania dla określonych wersji. Obiekt wywołujący używa id_token z OpenID w przychodzących żądaniach przekazywanych jako token okaziciela. Mam nadzieję, że pomoże to komuś innemu, próbującemu dokonać konwersji autorytetu tożsamości, tak samo jak to pytanie i odpowiedź pomogły mi.
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()); });
źródło