Oprogramowanie pośredniczące uwierzytelniania ASP.NET Core 2.0

89

W przypadku Core 1.1 postępowałem zgodnie z radą @ blowdart i zaimplementowałem niestandardowe oprogramowanie pośredniczące:

https://stackoverflow.com/a/31465227/29821

Działało tak:

  1. Uruchomiono oprogramowanie pośredniczące. Pobrano token z nagłówków żądań.
  2. Zweryfikowano token i, jeśli jest prawidłowy, zbudowano tożsamość (ClaimsIdentity), która zawierała wiele oświadczeń, które następnie dodano za pośrednictwem HttpContext.User.AddIdentity ();
  3. W ConfigureServices using services.AddAuthorization dodałem zasadę wymagającą oświadczenia dostarczonego przez oprogramowanie pośredniczące.
  4. W kontrolerach / akcjach użyłbym wtedy [Authorize (Roles = "rola dodana przez oprogramowanie pośredniczące")]

To trochę działa z 2.0, z wyjątkiem tego, że jeśli token jest nieprawidłowy (krok 2 powyżej) i roszczenie nie zostanie dodane, otrzymuję komunikat „Nie określono schematu uwierzytelniania i nie znaleziono DefaultChallengeScheme”.

Więc teraz czytam, że autoryzacja zmieniła się w 2.0:

https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

Jaka jest właściwa ścieżka do zrobienia tego samego w ASP.NET Core 2.0? Nie widzę przykładu wykonania prawdziwie niestandardowego uwierzytelniania.

pbz
źródło
Wypróbuj ten link, mimo że mówi o 2 schematach, ale dałby ci znać
Mithun Pattankar
czy możesz dodać swój kod, żebyśmy mogli rzucić okiem? Wiem, że miałem problemy z JWT w core2.0 - chodziło o przeniesienie go w startupie
Webezine

Odpowiedzi:

194

Tak więc, po długim dniu prób rozwiązania tego problemu, w końcu zrozumiałem, w jaki sposób firma Microsoft chce, abyśmy stworzyli niestandardowe programy obsługi uwierzytelniania dla ich nowej konfiguracji pojedynczego oprogramowania pośredniego w rdzeniu 2.0.

Po przejrzeniu części dokumentacji na MSDN znalazłem klasę o nazwie, AuthenticationHandler<TOption>która implementuje IAuthenticationHandlerinterfejs.

Stamtąd znalazłem całą bazę kodów z istniejącymi schematami uwierzytelniania znajdującymi się pod adresem https://github.com/aspnet/Security

Wewnątrz jednego z nich pokazuje, jak firma Microsoft implementuje schemat uwierzytelniania JwtBearer. ( https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer )

Skopiowałem większość tego kodu do nowego folderu i wyczyściłem wszystkie rzeczy związane JwtBearer.

W JwtBearerHandlerklasie (która rozszerza AuthenticationHandler<>) istnieje przesłonięcie dlaTask<AuthenticateResult> HandleAuthenticateAsync()

Dodałem nasze stare oprogramowanie pośredniczące do konfigurowania roszczeń za pośrednictwem niestandardowego serwera tokenów i nadal napotykałem pewne problemy z uprawnieniami, po prostu wypluwając 200 OKzamiast a, 401 Unauthorizedgdy token był nieprawidłowy i nie skonfigurowano żadnych roszczeń.

Zdałem sobie sprawę, że nadpisałem, Task HandleChallengeAsync(AuthenticationProperties properties)który z jakiegokolwiek powodu jest używany do ustawiania uprawnień za pośrednictwem [Authorize(Roles="")]kontrolera.

Po usunięciu tego zastąpienia kod działał i pomyślnie wyrzucił komunikat, 401gdy uprawnienia nie pasowały.

Głównym wnioskiem jest to, że teraz nie możesz używać niestandardowego oprogramowania pośredniego, musisz go zaimplementować za pośrednictwem AuthenticationHandler<>i musisz ustawić DefaultAuthenticateSchemei DefaultChallengeSchemepodczas używania services.AddAuthentication(...).

Oto przykład tego, jak to wszystko powinno wyglądać:

W Startup.cs / ConfigureServices () dodaj:

services.AddAuthentication(options =>
{
    // the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...)
    options.DefaultAuthenticateScheme = "Custom Scheme";
    options.DefaultChallengeScheme = "Custom Scheme";
})
.AddCustomAuth(o => { });

W Startup.cs / Configure () dodaj:

app.UseAuthentication();

Utwórz nowy plik CustomAuthExtensions.cs

public static class CustomAuthExtensions
{
    public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
    {
        return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
    }
}

Utwórz nowy plik CustomAuthOptions.cs

public class CustomAuthOptions: AuthenticationSchemeOptions
{
    public CustomAuthOptions()
    {

    }
}

Utwórz nowy plik CustomAuthHandler.cs

internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
    public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
        // store custom services here...
    }
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // build the claims and put them in "Context"; you need to import the Microsoft.AspNetCore.Authentication package
        return AuthenticateResult.NoResult();
    }
}
Zac
źródło
1
świetny post, ale mam problemy ze skompilowaniem twojego kodu. Brakuje typów CustomAuthOptions i AuthenticateResult. Czy możesz je opublikować?
alexb
8
Czy chcesz podzielić się swoimi wnioskami w kodzie w repozytorium Github?
CSharper
2
Czy mógłbyś wyjaśnić DefaultAuthenticateSchemei DefaultChallengeScheme? Nie rozumiem, dlaczego oba są używane? i jakie są między nimi różnice.
Mohammed Noureldin
11
+1 dla „Stamtąd znalazłem całą bazę kodów z istniejącymi schematami uwierzytelniania znajdującymi się pod adresem github.com/aspnet/Security ”. Spójrz tylko, jak robi to zespół ASP.NET, podążając za tą (naprawdę doskonałą) odpowiedzią. Czy ktokolwiek z nas kiedykolwiek pomyślał, że pewnego dnia będziemy zadawać pytania dotyczące kodu i praktyk MS, a odpowiedź będzie brzmiała: „Wystarczy spojrzeć na ich kod źródłowy?”.
Marc L.
3
Dla innych, którzy przyjdą później, AuthExtensionmusisz znajdować się w Microsoft.Extensions.DependencyInjectionprzestrzeni nazw. Zobacz ten przykład: github.com/aspnet/Security/blob/rel/2.0.0/src/…
Garry Polley
4

Istnieją znaczne zmiany w Identity z Core 1.x do Core 2.0, jak wskazuje artykuł, do którego się odwołujesz. Główną zmianą jest odejście od podejścia do oprogramowania pośredniego i używanie iniekcji zależności do konfigurowania usług niestandardowych. Zapewnia to znacznie większą elastyczność w dostosowywaniu tożsamości dla bardziej złożonych implementacji. Chcesz więc uciec od wspomnianego powyżej podejścia do oprogramowania pośredniego i przejść do usług. Aby osiągnąć ten cel, wykonaj kroki migracji opisane w przywołanym artykule. Zacznij zastępując app.UseIdentity z app.UseAuthentication . UseIdentity jest przestarzałe i nie będzie obsługiwane w przyszłych wersjach. Kompletny przykład wstawiania niestandardowej transformacji oświadczeń i wykonywania autoryzacji w oświadczeniuwyświetl ten wpis na blogu .

Kevin Junghans
źródło
12
Czy jest przykład, jak z tego korzystać w aplikacji WebAPI?
alexb