.NET Core Identity Server 4 Uwierzytelnianie VS Identity Authentication

92

Próbuję zrozumieć właściwy sposób uwierzytelniania w ASP.NET Core. Przejrzałem kilka zasobów (z których większość jest nieaktualna).

Niektóre osoby oferują alternatywne rozwiązania, które wymagają korzystania z rozwiązania opartego na chmurze, takiego jak Azure AD, lub używania IdentityServer4 i hostowania własnego serwera tokenów.

W starszej wersji .Net jedną z prostszych form uwierzytelniania byłoby utworzenie niestandardowej zasady I i przechowywanie w niej dodatkowych danych uwierzytelniających użytkownika.

public interface ICustomPrincipal : System.Security.Principal.IPrincipal
{
    string FirstName { get; set; }

    string LastName { get; set; }
}

public class CustomPrincipal : ICustomPrincipal
{
    public IIdentity Identity { get; private set; }

    public CustomPrincipal(string username)
    {
        this.Identity = new GenericIdentity(username);
    }

    public bool IsInRole(string role)
    {
        return Identity != null && Identity.IsAuthenticated && 
           !string.IsNullOrWhiteSpace(role) && Roles.IsUserInRole(Identity.Name, role);
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName { get { return FirstName + " " + LastName; } }
}

public class CustomPrincipalSerializedModel
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}

Następnie możesz serializować swoje dane do pliku cookie i zwrócić je z powrotem do klienta.

public void CreateAuthenticationTicket(string username) {     

    var authUser = Repository.Find(u => u.Username == username);  
    CustomPrincipalSerializedModel serializeModel = new CustomPrincipalSerializedModel();

    serializeModel.FirstName = authUser.FirstName;
    serializeModel.LastName = authUser.LastName;
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    string userData = serializer.Serialize(serializeModel);

    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
    1,username,DateTime.Now,DateTime.Now.AddHours(8),false,userData);
    string encTicket = FormsAuthentication.Encrypt(authTicket);
    HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
    Response.Cookies.Add(faCookie);
}

Moje pytania to:

  1. Jak mogę uwierzytelnić podobnie jak w poprzednich wersjach .Net, czy stary sposób nadal działa lub czy jest nowsza wersja.

  2. Jakie są zalety i wady używania własnego serwera tokenów w porównaniu do tworzenia własnych niestandardowych zasad?

  3. Korzystając z rozwiązania opartego na chmurze lub oddzielnego serwera tokenów, jak zintegrowałbyś to z obecną aplikacją, czy nadal potrzebowałbym tabeli użytkowników w mojej aplikacji.

  4. Ponieważ istnieje tak wiele różnych rozwiązań, w jaki sposób mogę utworzyć aplikację dla przedsiębiorstw, aby umożliwić logowanie za pośrednictwem Gmaila / Facebooka, jednocześnie będąc w stanie rozszerzyć na inne SSO

  5. Jakie są proste implementacje tych technologii?
johnny 5
źródło
To pytanie jest zbyt szerokie, a także mocno opiniotwórcze. Możliwych odpowiedzi jest zbyt wiele lub dobre odpowiedzi byłyby zbyt długie dla tego formatu. Dodaj szczegóły, aby zawęzić zestaw odpowiedzi lub wyodrębnić problem, na który można odpowiedzieć w kilku akapitach. Wiele dobrych pytań generuje pewien stopień opinii w oparciu o doświadczenie ekspertów, ale odpowiedzi na to pytanie będą prawie całkowicie oparte na opiniach, a nie na faktach, referencjach lub konkretnej wiedzy.
Nkosi
@Nkosi przepraszam, że fraza była taka. Wyjaśniłem to bardziej szczegółowo
johnny 5

Odpowiedzi:

145

TL; DR

IdentityServer = usługi szyfrowania i weryfikacji tokenów za pośrednictwem OAuth 2.0 / OpenId-Connect

ASP.NET Identity = aktualna strategia zarządzania tożsamością w ASP.NET

Jak mogę uwierzytelnić podobnie jak w poprzednich wersjach .Net, czy stary sposób nadal działa lub czy jest nowsza wersja.

Nie widzę powodu, dla którego nie można było osiągnąć starego sposobu w ASP.NET Core, ale ogólnie ta strategia została zastąpiona przez ASP.NET Identity, a ASP.NET Identity działa i dobrze działa w ASP.NET Core.

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity

ASP.NET Identity wykorzystuje magazyn zapasowy, taki jak SQL Server, do przechowywania informacji o użytkowniku, takich jak nazwa użytkownika, hasło (zakodowane), adres e-mail, telefon i można go łatwo rozszerzyć o imię, nazwisko lub cokolwiek innego. Tak więc naprawdę nie ma powodu, aby szyfrować informacje o użytkowniku w pliku cookie i przekazywać je tam iz powrotem z klienta na serwer. Obsługuje pojęcia takie jak oświadczenia użytkowników, tokeny użytkowników, role użytkowników i logowania zewnętrzne. Oto jednostki w ASP.NET Identity:

  • AspNetUsers
  • AspNetUserRoles
  • AspNetUserClaims
  • AspNetUserLogins (do łączenia zewnętrznych dostawców tożsamości, takich jak Google, AAD)
  • AspNetUserTokens (do przechowywania rzeczy, takich jak access_tokens i refresh_tokens zgromadzonych przez użytkownika)

Jakie są zalety i wady używania własnego serwera tokenów w porównaniu do tworzenia własnych niestandardowych zasad?

Serwer tokenów to system, który generuje prostą strukturę danych zawierającą informacje o autoryzacji i / lub uwierzytelnieniu. Autoryzacja zwykle wymaga tokenu o nazwie access_token . Byłyby to, że tak powiem, „klucze do domu”, pozwalające przejść przez drzwi do miejsca zamieszkania chronionego zasobu, zwykle interfejsu API sieci Web. W przypadku uwierzytelniania id_tokenzawiera unikalny identyfikator użytkownika / osoby. Chociaż często umieszcza się taki identyfikator w access_token, istnieje teraz dedykowany protokół do tego: OpenID-Connect .

Powodem posiadania własnej usługi tokenu zabezpieczającego (STS) byłaby ochrona zasobów informacyjnych za pośrednictwem kryptografii i kontrolowanie, którzy klienci (aplikacje) mają dostęp do tych zasobów. Ponadto standardy kontroli tożsamości istnieją teraz w specyfikacjach OpenID-Connect. IdentityServer to przykład serwera autoryzacji OAuth 2.0 w połączeniu z serwerem uwierzytelniania OpenID-Connect.

Ale nic z tego nie jest konieczne, jeśli chcesz mieć tylko tabelę użytkowników w swojej aplikacji. Nie potrzebujesz serwera tokenów - po prostu użyj ASP.NET Identity. ASP.NET Identity mapuje użytkownika na obiekt ClaimsIdentity na serwerze - nie ma potrzeby stosowania niestandardowej klasy IPrincipal.

Korzystając z rozwiązania opartego na chmurze lub oddzielnego serwera tokenów, jak zintegrowałbyś to z obecną aplikacją, czy nadal potrzebowałbym tabeli użytkowników w mojej aplikacji.

Zobacz te samouczki dotyczące integracji oddzielnych rozwiązań do obsługi tożsamości z aplikacją: https://identityserver4.readthedocs.io/en/latest/quickstarts/0_overview.html https://auth0.com/docs/quickstart/webapp/aspnet-core

Jako minimum potrzebna byłaby tabela z dwiema kolumnami, mapująca nazwę użytkownika na identyfikator użytkownika zewnętrznego dostawcy. To właśnie robi tabela AspNetUserLogins w ASP.NET Identity. Jednak wiersze w tej tabeli zależą od tego, czy rekord użytkownika jest w AspNetUsers.

ASP.NET Identity obsługuje dostawców zewnętrznych, takich jak Google, Microsoft, Facebook, dowolny dostawca OpenID-Connect, usługa Azure AD już tam jest. (Google i Microsoft wdrożyły już protokół OpenID-Connect, więc nie potrzebujesz również ich niestandardowych pakietów integracyjnych, takich jak na przykład ten). Ponadto usługi ADFS nie są jeszcze dostępne w ASP.NET Core Identity.

Zobacz ten dokument, aby rozpocząć pracę z dostawcami zewnętrznymi w ASP.NET Identity:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/

Ponieważ istnieje tak wiele różnych rozwiązań, w jaki sposób mogę utworzyć aplikację dla przedsiębiorstw, aby umożliwić logowanie za pośrednictwem Gmaila / Facebooka, jednocześnie będąc w stanie rozszerzyć na inne SSO

Jak wyjaśniono powyżej, ASP.NET Identity już to robi. Utworzenie tabeli „Dostawcy zewnętrzni” jest dość łatwe, a dane napędzają proces logowania na zewnątrz. Kiedy więc pojawi się nowe „logowanie jednokrotne”, po prostu dodaj nowy wiersz z właściwościami, takimi jak adres URL dostawcy, identyfikator klienta i sekret, który Ci podają. ASP.NET Identity ma już wbudowany interfejs użytkownika szablonów Visual Studio, ale zobacz Logowanie społecznościowe dla fajniejszych przycisków.

Podsumowanie

Jeśli potrzebujesz tylko tabeli użytkowników z możliwościami logowania się za pomocą hasła i profilem użytkownika, ASP.NET Identity jest idealny. Nie ma potrzeby angażowania władz zewnętrznych. Ale jeśli masz wiele aplikacji wymagających dostępu do wielu interfejsów API, niezależny organ zabezpieczający i weryfikujący tożsamość oraz tokeny dostępu ma sens. IdentityServer jest dobrym rozwiązaniem lub zobacz openiddict-core lub Auth0 w przypadku rozwiązania chmurowego.

Przepraszam, że to nie trafia w sedno lub jest zbyt wstępne. Zachęcamy do interakcji, aby dotrzeć do celu, którego szukasz.

Dodatek: Uwierzytelnianie plików cookie

Aby wykonać uwierzytelnianie gołe kości za pomocą plików cookie, wykonaj następujące kroki. Ale, o ile mi wiadomo, niestandardowy podmiot oświadczeń nie jest obsługiwany. Aby osiągnąć ten sam efekt, skorzystaj z listy roszczeń ClaimPrincipalobiektu.

Utwórz nową aplikację sieci Web ASP.NET Core 1.1 w programie Visual Studio 2015/2017, wybierając opcję „Brak uwierzytelniania” w oknie dialogowym. Następnie dodaj pakiet:

Microsoft.AspNetCore.Authentication.Cookies

Zgodnie z Configurezastosowaną metodą Startup.csto (wcześniej app.UseMvc):

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationScheme = "MyCookieMiddlewareInstance",
    LoginPath = new PathString("/Controller/Login/"),
    AutomaticAuthenticate = true,
    AutomaticChallenge = true
});

Następnie utwórz interfejs użytkownika logowania i prześlij formularz html do metody akcji w następujący sposób:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(String username, String password, String returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        // check user's password hash in database
        // retrieve user info

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, username),
            new Claim("FirstName", "Alice"),
            new Claim("LastName", "Smith")
        };

        var identity = new ClaimsIdentity(claims, "Password");

        var principal = new ClaimsPrincipal(identity);

        await HttpContext.Authentication.SignInAsync("MyCookieMiddlewareInstance", principal);

        return RedirectToLocal(returnUrl);
    }

    ModelState.AddModelError(String.Empty, "Invalid login attempt.");

    return View();
}

Obiekt HttpContext.User powinien mieć niestandardowe oświadczenia i można je łatwo pobrać z kolekcji List ClaimPrincipal.

Mam nadzieję, że to wystarczy, ponieważ pełne rozwiązanie / projekt wydaje się trochę za dużo dla postu StackOverflow.

travis.js
źródło
1
Proszę pokazać przykład implementacji uwierzytelniania w rdzeniu
johnny 5
2
Dokumentacja ASP.NET Core przedstawia przykład kanoniczny: docs.microsoft.com/en-us/aspnet/core/security/authentication/… .
travis.js
Jeśli możesz, prześlij prosty przykład uwierzytelnienia. Bez linku, aby ludzie mieli dostęp do zasobów, opublikuję dogłębną odpowiedź na temat konfigurowania IdentityServer4
johnny 5
Czy w przypadku IdentityServer jest to przykład, którego szukasz: identityserver4.readthedocs.io/en/dev/quickstarts/… ?
travis.js
W przypadku ASP.NET Identity nie ma tego przykładu, czy to, co mówisz, jest nieaktualne? docs.microsoft.com/en-us/aspnet/core/security/authentication/ ...
travis.js
11

TL; DR

Naprawdę chciałbym pokazać pełny post o tym, jak prawidłowo zaimplementować IdentityServer4, ale próbowałem dopasować cały tekst, ale było to poza tym, co akceptuje StackOverflow, więc zamiast tego poprawię kilka wskazówek i rzeczy, których się nauczyłem.

Jakie są zalety korzystania z tożsamości ASP w porównaniu z serwerem tokenów?

Serwer z tokenami ma wiele zalet, ale nie jest odpowiedni dla wszystkich. Jeśli wdrażasz rozwiązanie podobne do przedsiębiorstwa, w którym chcesz, aby wielu klientów mogło się zalogować, najlepszym rozwiązaniem jest serwer tokenów, ale jeśli tworzysz tylko prostą witrynę internetową, która chce obsługiwać logowanie zewnętrzne, możesz odejść dzięki tożsamości ASP i niektóre oprogramowanie pośredniczące.

4 wskazówki dotyczące serwera tożsamości

Identity server 4 jest całkiem dobrze udokumentowany w porównaniu z wieloma innymi frameworkami, które widziałem, ale trudno jest zacząć od zera i zobaczyć cały obraz.

Moim pierwszym błędem była próba użycia OAuth jako uwierzytelniania.Tak, są na to sposoby, ale OAuth służy do autoryzacji, a nie uwierzytelniania, jeśli chcesz uwierzytelnić, użyj OpenIdConnect (OIDC)

W moim przypadku chciałem stworzyć klienta javascript, który łączy się z internetowym interfejsem API. Przyjrzałem się wielu rozwiązaniom, ale początkowo próbowałem użyć webapi do wywołania uwierzytelniania na serwerze tożsamości i zamierzałem po prostu zachować ten token, ponieważ został zweryfikowany na serwerze. Ten przepływ może potencjalnie działać, ale ma wiele wad.

Wreszcie właściwy przepływ, gdy znalazłem próbkę klienta JavaScript, uzyskałem właściwy przepływ. Klient loguje się i ustawia token. Następnie Twój internetowy interfejs API korzysta z klienta OIdc, który zweryfikuje Twój token dostępu względem IdentityServer.

Łączenie się ze sklepami i migracjami Na początku miałem wiele nieporozumień dotyczących migracji. Miałem wrażenie, że przeprowadzanie migracji generuje kod SQL z biblioteki dll wewnętrznie, zamiast używać skonfigurowanego kontekstu, aby dowiedzieć się, jak utworzyć SQL.

Istnieją dwie składnie migracji, wiedząc, która z nich jest ważna:

dotnet ef migrations add InitialIdentityServerMigration -c ApplicationDbContext

Add-Migration InitialIdentityServerDbMigration -c ApplicationDbContext

Myślę, że parametr po migracji to nazwa, dlaczego potrzebujesz nazwy, nie jestem pewien, ApplicationDbContextjest to Code-First DbContext, w którym chcesz utworzyć.

Migracje używają auto-magii, aby znaleźć ciąg połączenia na podstawie konfiguracji twojego uruchamiania, po prostu założyłem, że używało połączenia z Eksploratora serwera.

Jeśli masz wiele projektów, upewnij się, że masz projekt z ustawionym ApplicationDbContext jako startem.

Podczas wdrażania autoryzacji i uwierzytelniania jest wiele ruchomych części. Mam nadzieję, że ten post komuś pomoże. Najłatwiejszym sposobem pełnego zrozumienia uwierzytelnień jest rozebranie ich przykładów, aby poskładać wszystko w całość i upewnić się, że przeczytałeś dokumentację

johnny 5
źródło
nazwa po migracji dodatku to odniesienie związane z wersją / wprowadzonymi zmianami. ta sama nazwa zostanie użyta do dodania skryptu migracji Up & Down.
Jay
@Jay Dzięki za to wyjaśnienie
johnny 5
Kontekst bazy danych konfiguracji serwera tożsamości nadal nie jest tak dobry jak IdentityDbContext. tworzenie niestandardowych implementacji jest uciążliwe. Identityserver 4 wydaje się teraz mało aktywny, aby wydawać nowe aktualizacje po aktualizacjach .core.
Jay
3

ASP.NET Identity - jest to kompilacja w celu uwierzytelnienia Twojej aplikacji, czy to Bearer, czy Basic Authentication, daje nam gotowy kod do rejestracji użytkownika, logowania, zmiany hasła i wszystkiego.

Rozważmy teraz, że mamy 10 różnych aplikacji i nie jest możliwe zrobienie tego samego we wszystkich 10 aplikacjach. ta bardzo delikatna i bardzo zła praktyka.

Aby rozwiązać ten problem, możemy scentralizować nasze uwierzytelnianie i autoryzację, aby każda zmiana w tym zakresie nie wpłynęła na wszystkie nasze 10 aplikacji.

Serwer tożsamości zapewnia taką samą możliwość. możemy stworzyć jedną przykładową aplikację internetową, która będzie używana tylko jako usługa tożsamości, a ona zweryfikuje Twojego użytkownika i dostarczy token dostępu JWT.

Amol Aher
źródło
2

Zawsze korzystałem z wbudowanej autoryzacji / uwierzytelniania ASP.NET Identity (i wcześniej Membership), niedawno zaimplementowałem Auth0 ( https://auth0.com ) i polecam to jako coś innego do wypróbowania.

Mark Redman
źródło
Przykład rdzenia Auth0 .net jest dość szybki i prosty do zaimplementowania, ale korzystanie ze wszystkich funkcji wymaga sporo pracy, zaimplementowałem Auth0 integrując wiele funkcji i działa dobrze, ale jak wszystkie te rzeczy, jego potrzeby są trochę pracy i trochę frustracji.
Mark Redman
Kiedy jedno uwierzytelnienie będzie działało dobrze, opublikuję szczegółową odpowiedź na jego temat. Właśnie pracowałem nad uwierzytelnianiem w zeszłym tygodniu. I nic nie jest tak proste, jak powinno być
johnny 5
0

Loginy społecznościowe nie są trudne do wdrożenia w Identity, ale wymaga to wstępnej konfiguracji, a czasami kroki, które znajdziesz online w dokumentach, nie są identyczne, zwykle możesz znaleźć pomoc w tej kwestii w sekcji programistów platformy, którą próbujesz skonfigurować loginy społecznościowe dla. Tożsamość to zastąpienie starej funkcji członkostwa, którą można znaleźć w starszych wersjach platformy .net. Zaskakujące jest to, że przypadki użycia krawędzi, takie jak przekazanie tokena jwt, który już masz, do interfejsu API sieci Web, nie są omówione w żadnym miejscu w przykładach online nawet w przypadku liczby mnogiej, jestem pewien, że nie potrzebujesz do tego własnego tokena, ale nie znalazłem ani jednego przykładu przekazywania danych w pobieraniu lub poście, który nie dotyczy hostowanego samodzielnie serwera.

webdev8183
źródło