Authentification .NET Core Identity Server 4 VS Authentification d'identité


93

J'essaie de comprendre la bonne façon de faire l'authentification dans ASP.NET Core. J'ai examiné plusieurs ressources (dont la plupart sont obsolètes).

Certaines personnes fournissent des solutions alternatives indiquant d'utiliser une solution cloud telle qu'Azure AD, ou d'utiliser IdentityServer4 et d'héberger mon propre serveur de jetons.

Dans l'ancienne version de .Net, l'une des formes d'authentification les plus simples consisterait à créer un principe personnalisé et à stocker des données utilisateur d'authentification supplémentaires à l'intérieur.

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

Ensuite, vous sérialiseriez vos données dans un cookie et le renverriez au client.

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

Mes questions sont:

  1. Comment puis-je m'authentifier de la même manière que dans les versions précédentes de .Net, l'ancienne méthode fonctionne-t-elle toujours ou existe-t-il une version plus récente.

  2. Quels sont les avantages et les inconvénients de l'utilisation de vos propres versets de serveur de jetons pour créer votre propre principe personnalisé?

  3. Lorsque vous utilisez une solution basée sur le cloud ou un serveur de jetons séparé, comment intégriez-vous cela à votre application actuelle, aurais-je toujours besoin d'une table d'utilisateurs dans mon application, comment associeriez-vous les deux?

  4. Étant donné qu'il existe tellement de solutions différentes, comment puis-je créer une application d'entreprise, pour permettre la connexion via Gmail / Facebook tout en étant capable de s'étendre à d'autres SSO

  5. Quelles sont quelques implémentations simples de ces technologies?

Cette question est trop large et aussi fortement basée sur l'opinion. Il y a soit trop de réponses possibles, soit de bonnes réponses seraient trop longues pour ce format. Veuillez ajouter des détails pour restreindre l'ensemble de réponses ou pour isoler un problème auquel il est possible de répondre en quelques paragraphes. De nombreuses bonnes questions génèrent un certain degré d'opinion basé sur l'expérience d'experts, mais les réponses à cette question auront tendance à être presque entièrement basées sur des opinions plutôt que sur des faits, des références ou une expertise spécifique.
Nkosi

@Nkosi désolé la phrase était comme ça. J'ai clarifié cela pour être plus précis
johnny 5

Réponses:


146

TL; DR

IdentityServer = services de chiffrement et de validation de jetons via OAuth 2.0 / OpenId-Connect

Identité ASP.NET = stratégie actuelle de gestion des identités dans ASP.NET

Comment puis-je m'authentifier de la même manière que dans les versions précédentes de .Net, l'ancienne méthode fonctionne-t-elle toujours ou existe-t-il une version plus récente.

Je ne vois aucune raison pour laquelle vous ne pourriez pas atteindre l'ancienne méthode dans ASP.NET Core, mais en général, cette stratégie a été remplacée par ASP.NET Identity et ASP.NET Identity est bien vivante dans ASP.NET Core.

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

ASP.NET Identity utilise un magasin de stockage comme SQL Server pour contenir des informations utilisateur telles que le nom d'utilisateur, le mot de passe (haché), le courrier électronique, le téléphone et peut facilement être étendu pour contenir FirstName, LastName ou autre. Il n'y a donc vraiment aucune raison de crypter les informations utilisateur dans un cookie et de les transmettre d'un client à l'autre. Il prend en charge des notions telles que les revendications des utilisateurs, les jetons d'utilisateurs, les rôles d'utilisateurs et les connexions externes. Voici les entités dans ASP.NET Identity:

  • Utilisateurs AspNet
  • AspNetUserRoles
  • AspNetUserClaims
  • AspNetUserLogins (pour lier des fournisseurs d'identité externes, comme Google, AAD)
  • AspNetUserTokens (pour stocker des éléments tels que access_tokens et refresh_tokens amassés par l'utilisateur)

Quels sont les avantages et les inconvénients de l'utilisation de vos propres versets de serveur de jetons pour créer votre propre principe personnalisé?

Un serveur de jetons serait un système qui génère une structure de données simple contenant des informations d'autorisation et / ou d'authentification. L'autorisation prend généralement le for d'un jeton nommé access_token . Ce serait les "clés de la maison", pour ainsi dire, vous permettant de passer la porte et d'entrer dans la résidence d'une ressource protégée, généralement une API Web. Pour l'authentification, le id_tokencontient un identifiant unique pour un utilisateur / une personne. Bien qu'il soit courant de mettre un tel identifiant dans le access_token, il existe désormais un protocole dédié pour cela: OpenID-Connect .

La raison d'avoir votre propre service de jetons de sécurité (STS) serait de protéger vos actifs d'information, via la cryptographie, et de contrôler quels clients (applications) peuvent accéder à ces ressources. De plus, les normes de contrôle d'identité existent désormais dans les spécifications OpenID-Connect. IdentityServer est un exemple de serveur d'autorisation OAuth 2.0 combiné à un serveur d'authentification OpenID-Connect.

Mais rien de tout cela n'est nécessaire si vous voulez juste une table utilisateur dans votre application. Vous n'avez pas besoin d'un serveur de jetons, utilisez simplement ASP.NET Identity. L'identité ASP.NET mappe votre utilisateur à un objet ClaimsIdentity sur le serveur - pas besoin d'une classe IPrincipal personnalisée.

Lorsque vous utilisez une solution basée sur le cloud ou un serveur de jetons séparé, comment intégriez-vous cela à votre application actuelle, aurais-je toujours besoin d'une table d'utilisateurs dans mon application, comment associeriez-vous les deux?

Consultez ces tutoriels pour intégrer des solutions d'identité distinctes avec une application: https://identityserver4.readthedocs.io/en/latest/quickstarts/0_overview.html https://auth0.com/docs/quickstart/webapp/aspnet-core

Au minimum, vous auriez besoin d'une table à deux colonnes mappant le nom d'utilisateur à l'identifiant d'utilisateur du fournisseur externe. C'est ce que fait la table AspNetUserLogins dans ASP.NET Identity. Les lignes de cette table dépendent cependant du fait qu'il s'agit d'un enregistrement utilisateur dans AspNetUsers.

ASP.NET Identity prend en charge les fournisseurs externes tels que Google, Microsoft, Facebook, tout fournisseur OpenID-Connect, Azure AD sont déjà là. (Google et Microsoft ont déjà implémenté le protocole OpenID-Connect, vous n'avez donc pas non plus besoin de leurs packages d'intégration personnalisés, comme celui-ci , par exemple). En outre, ADFS n'est pas encore disponible sur ASP.NET Core Identity.

Consultez ce document pour démarrer avec les fournisseurs externes dans ASP.NET Identity:

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

Étant donné qu'il existe tellement de solutions différentes, comment puis-je créer une application d'entreprise, pour permettre la connexion via Gmail / Facebook tout en étant capable de s'étendre à d'autres SSO

Comme expliqué ci-dessus, ASP.NET Identity le fait déjà. Il est assez facile de créer un tableau «Fournisseurs externes» et les données pilotent votre processus de connexion externe. Donc, quand un nouveau "SSO" arrive, ajoutez simplement une nouvelle ligne avec les propriétés comme l'url du fournisseur, l'ID client et le secret qu'il vous donne. ASP.NET Identity a déjà l'interface utilisateur intégrée dans les modèles Visual Studio, mais consultez Connexion sociale pour des boutons plus cool.

Sommaire

Si vous avez juste besoin d'une table d'utilisateurs avec des capacités de connexion par mot de passe et un profil utilisateur, alors ASP.NET Identity est parfait. Pas besoin d'impliquer des autorités extérieures. Mais, si de nombreuses applications ont besoin d'accéder à de nombreuses API, une autorité indépendante pour sécuriser et valider les jetons d'identité et d'accès est logique. IdentityServer est un bon choix , ou voir openiddict-core ou Auth0 pour une solution cloud.

Je m'excuse, c'est que cela n'atteint pas la cible ou si c'est trop introductif. N'hésitez pas à interagir pour accéder à la cible que vous recherchez.

Addendum: Authentification des cookies

Pour effectuer une authentification simple avec des cookies, procédez comme suit. Mais, à ma connaissance, un principal de revendications personnalisé n'est pas pris en charge. Pour obtenir le même effet, utilisez la liste des revendications de l' ClaimPrincipalobjet.

Créez une nouvelle application Web ASP.NET Core 1.1 dans Visual Studio 2015/2017 en choisissant «Aucune authentification» dans la boîte de dialogue. Ensuite, ajoutez le package:

Microsoft.AspNetCore.Authentication.Cookies

Sous la Configureméthode en Startup.csplace ceci (avant app.UseMvc):

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

Ensuite, créez une interface utilisateur de connexion et publiez le formulaire html dans une méthode d'action comme celle-ci:

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

L'objet HttpContext.User doit avoir vos revendications personnalisées et sont facilement récupérables dans la collection List de ClaimPrincipal.

J'espère que cela suffira, car une solution / projet complet semble un peu trop pour un article StackOverflow.


1
Veuillez montrer un exemple d'implémentation de l'authentification dans le noyau
johnny 5

2
La documentation ASP.NET Core montre l'exemple canonique: docs.microsoft.com/en-us/aspnet/core/security/authentication/… .
travis.js

Si vous pouvez poster un exemple simple d'authentification. Sans lien pour que les gens aient accès à une ressource, je publierai une réponse détaillée sur la configuration d'IdentityServer4
johnny 5

Pour IdentityServer, cela a-t-il l'exemple que vous recherchez: identityserver4.readthedocs.io/en/dev/quickstarts/… ?
travis.js

Pour ASP.NET Identity, cela n'a-t-il pas l'exemple ou est-ce que ce que vous dites est obsolète? docs.microsoft.com/en-us/aspnet/core/security/authentication/…
travis.js

11

TL; DR

J'aimerais vraiment afficher une publication complète sur la façon de mettre en œuvre correctement IdentityServer4 mais j'ai essayé d'intégrer tout le texte, mais c'était au-delà de la limite de ce que StackOverflow accepte donc à la place, je corrigerai quelques conseils et choses que j'ai appris.

Quels sont les avantages de l'utilisation d'un serveur de jetons par rapport à une identité ASP?

Un serveur de jetons présente de nombreux avantages, mais il ne convient pas à tout le monde. Si vous implémentez une solution de type entreprise, où vous souhaitez que plusieurs clients puissent se connecter, le serveur de jetons est votre meilleur pari, mais si vous créez simplement un site Web simple qui souhaite prendre en charge les connexions externes, vous pouvez vous en sortir avec l'identité ASP et certains middleware.

Identity Server 4 conseils

Le serveur d'identité 4 est assez bien documenté par rapport à beaucoup d'autres frameworks que j'ai vus, mais il est difficile de partir de zéro et de voir la situation dans son ensemble.

Ma première erreur essayait d'utiliser OAuth comme authentification, oui, il existe des moyens de le faire, mais OAuth est pour l'autorisation et non l'authentification, si vous voulez vous authentifier, utilisez OpenIdConnect (OIDC)

Dans mon cas, je voulais créer un client javascript, qui se connecte à une API Web. J'ai regardé beaucoup de solutions, mais au départ, j'ai essayé d'utiliser le webapi pour appeler l'authentification par rapport au serveur d'identité et j'allais simplement que ce jeton persiste car il a été vérifié par rapport au serveur. Ce flux peut potentiellement fonctionner mais il comporte de nombreux défauts.

Enfin, le bon flux lorsque j'ai trouvé l'exemple de client Javascript, j'ai obtenu le bon flux. Votre client se connecte et définit un jeton. Ensuite, votre API Web utilise le client OIdc, qui vérifiera votre jeton d'accès par rapport à IdentityServer.

Connexion aux magasins et aux migrations Au début, j'ai eu de nombreuses idées fausses sur les migrations. J'avais l'impression que l'exécution d'une migration générait le SQL à partir de la dll en interne, au lieu d'utiliser le contexte configuré pour comprendre comment créer le SQL.

Il existe deux syntaxes pour les migrations, sachant que celle que votre ordinateur utilise est importante:

dotnet ef migrations add InitialIdentityServerMigration -c ApplicationDbContext

Add-Migration InitialIdentityServerDbMigration -c ApplicationDbContext

Je pense que le paramètre après la migration est le nom, pourquoi vous avez besoin d'un nom, je ne suis pas sûr, ApplicationDbContextc'est un DbContext Code-First dans lequel vous souhaitez créer.

Les migrations utilisent une magie automatique pour trouver votre chaîne de connexion à partir de la configuration de votre démarrage, j'ai simplement supposé qu'elle utilisait une connexion de l'explorateur de serveur.

Si vous avez plusieurs projets, assurez-vous que le projet est défini avec ApplicationDbContext comme démarrage.

Il y a beaucoup de pièces mobiles lors de la mise en œuvre de l'autorisation et de l'authentification, j'espère que ce message aidera quelqu'un. Le moyen le plus simple de comprendre pleinement les authentifications est de sélectionner leurs exemples pour tout rassembler et de vous assurer de lire la documentation.


le nom après add-migration est la référence liée à votre version / modifications que vous avez apportées. le même nom sera utilisé pour ajouter le script de migration Up & Down.
Jay

@Jay Merci pour cette clarification
johnny 5

Le contexte de la base de données de configuration du serveur d'identité n'est toujours pas aussi bon que IdentityDbContext. créer une implémentation personnalisée est une douleur. Identityserver 4 ne semble plus très actif pour publier de nouvelles mises à jour après les mises à jour .core.
Jay

3

Identité ASP.NET - c'est la construction d'une manière d'authentifier votre application, qu'il s'agisse d'une authentification au porteur ou de base, elle nous donne le code prêt à l'emploi pour effectuer l'enregistrement de l'utilisateur, la connexion, changer le mot de passe et tout.

Considérons maintenant que nous avons 10 applications différentes et qu'il n'est pas possible de faire la même chose dans les 10 applications. cette pratique très fragile et très mauvaise.

Pour résoudre ce problème, nous pouvons centraliser notre authentification et notre autorisation afin que chaque modification apportée n'affecte pas toutes nos 10 applications.

Le serveur d'identité vous offre la possibilité de faire de même. nous pouvons créer un exemple d'application Web qui vient d'être utilisé comme service d'identité et qui validera votre utilisateur et fournira un jeton d'accès JWT.


2

J'ai toujours utilisé l'autorisation / authentification intégrée ASP.NET Identity (et précédemment Membership), j'ai récemment implémenté Auth0 ( https://auth0.com ) et je le recommande comme autre chose à essayer.


L'exemple de base Auth0 .net est assez rapide et simple à implémenter, mais l'utilisation de toutes les fonctionnalités nécessite un peu de travail, j'ai implémenté Auth0 en intégrant beaucoup de fonctionnalités et cela fonctionne bien, mais comme toutes ces choses, ses besoins sont là. un peu de travail et une certaine frustration.
Mark Redman

Quand j'obtiendrai une authentification fonctionnant bien, je publierai une réponse détaillée à ce sujet. Je viens de travailler sur l'authentification la semaine dernière. Et rien n'est aussi droit qu'il devrait l'être
johnny 5

0

Les connexions sociales ne sont pas difficiles à implémenter avec Identity, mais il y a une configuration initiale impliquée et parfois les étapes que vous trouvez en ligne dans la documentation ne sont pas identiques, vous pouvez généralement trouver de l'aide dans la section développeurs de la plate-forme que vous essayez de configurer. les connexions sociales pour. L'identité est le remplacement de l'ancienne fonctionnalité d'appartenance trouvée dans les versions héritées du framework .net.Ce que j'ai trouvé surprenant, c'est que les cas d'utilisation marginaux, comme le passage d'un jeton jwt que vous avez déjà à une API Web, ne sont couverts nulle part dans les exemples en ligne. même sur pluralsight, je suis sûr que vous n'avez pas besoin de votre propre autorité de jeton pour le faire, mais je n'ai pas trouvé un seul exemple sur la façon de transmettre des données dans un get ou une publication qui ne traite pas d'un serveur auto-hébergé.


peut-être êtes-vous après ce docs.identityserver.io/en/release/quickstarts/…
Jay
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.