[Actualité] IdentityServer4 : Authentification d’un utilisateur avec OpenID Connect
par
, 12/12/2018 à 03h03 (10919 Affichages)
IdentityServer est une solution open source .NET de gestion d’identité et de contrôle d’accès. Il repose sur les protocoles OpenID Connect et OAuth 2.0.
IdentityServer peut être utilisé par les entreprises pour mettre en place une solution pour :
- la protection de leurs ressources ;
- l’authentification des utilisateurs via une base de données ou des fournisseurs externes d’identité (Microsoft, Google, Facebook, etc.) ;
- la gestion des sessions et la fédération (single sign-on) ;
- la génération des jetons pour les clients ;
- la validation des jetons et bien plus.
Ce billet est le quatrième que j’écris sur le sujet. Les billets précédents ont porté sur les points suivants :
Mise en place d’un STS avec IdentityServer4 pour sécuriser ses applications .NET
Sécurisation d’une Web API ASP.NET Core avec le STS IdentityServer4
IdentityServer4 : création et configuration du Client pour accéder à une Web API ASP.NET Core sécurisée
Nous disposons d’une application Web dont nous voulons sécuriser certaines pages. Pour accéder à ces pages, l’utilisateur doit s’authentifier au préalable en utilisant son compte.
Nous devons donc intégrer cette nouvelle application à notre IdentityServer. Lorsque l’utilisateur vaudra accéder à une page protégée, il sera redirigé vers IdentityServer qui affichera une fenêtre d’authentification. Une fois ce dernier authentifié, il sera redirigé vers la page à laquelle il voulait accéder.
Ajout de l’interface d’authentification
Actuellement notre solution IdentityServer ne dispose d’aucune interface. Tout ce qu’elle est en mesure d’afficher dans un navigateur c’est un « Hello World! ».
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseIdentityServer(); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); }
Elle ne dispose donc d’aucune vue, aucun contrôleur, etc. Pourtant, nous avons besoin d’une solution permettant d’authentifier un utilisateur via un formulaire, mettre fin à sa session, etc. Pour mettre cela en place, nous allons nous appuyer sur un modèle Quickstart existant fourni par les développeurs de IdentityServer4.
Ce modèle est disponible dans le repository GitHub suivant https://github.com/IdentityServer/Id.../release/Views. Vous pouvez le télécharger et copier/coller les dossiers Quickstart, Views et wwwroot dans votre projet.
Vous pouvez aussi simplement ouvrir le terminal Powershell dans le dossier racine du projet et exécuter la commande :
Je n’entrerais pas dans les détails d’implémentation de ce modèle.
Code : Sélectionner tout - Visualiser dans une fenêtre à part iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.ps1'))
Transformation du projet en solution MVC
Le Quickstart que nous avons intégré repose sur ASP.NET MVC. Nous allons apporter quelques modifications à notre projet pour prendre en charge ASP.NET Core MVC.
La première chose à faire sera de modifier la méthode ConfigureServices() et ajouter la ligne de code suivante au début :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
Cette ligne de code permet d’enregistrer les services pour la prise en charge de ASP.NET Core MVC.
Par la suite, vous devez modifier la méthode Configure pour intégrer les middlewares nécessaires à la gestion des fichiers statistiques et le routage. Par ailleurs, vous devez supprimer la ligne de code permettant d’afficher le « Hello Word! » :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage() ; } app.UseStaticFiles(); app.UseIdentityServer(); app.UseMvcWithDefaultRoute(); }
Ajout du support pour OpenID Connect
OpenID Connect est une couche d'identification basée sur le protocole OAuth 2.0, qui autorise les clients à vérifier l'identité d'un utilisateur final en se basant sur l'authentification fournie par un serveur d'autorisation, dont IdentityServer. L’authentification d’un utilisateur via un formulaire avec IdentityServer repose sur OpenID Connect.
L’implémentation utilise le concept de scopes (portés). Nous devons définir comme nous l’avons fait précédemment pour l’API les ressources auxquelles le client doit accéder. Sauf qu’ici, il s’agit des informations du profil utilisateur (id, nom, email, etc.) que nous souhaitons partager avec le client. Ces ressources sont donc de type IdentityResources.
Pour le faire, nous allons éditer le fichier Config.cs et ajouter les lignes de code suivantes :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 public static IEnumerable<IdentityResource> GetIdentityResources() { return new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile(), }; }
Une fois cela fait, nous devons modifier la méthode ConfigureServices du fichier Startup.cs pour ajouter cette nouvelle ressource à la configuration d’IdentityServer. Cela se fait en utilisant la méthode d’extension AddInMemoryIdentityResources :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); //configure identity server with in-memory stores, keys, clients and resources services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryIdentityResources(Config.GetIdentityResources()) .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients()); }
Ajout des utilisateurs pour les tests
Les informations saisies par l’utilisateur dans le formulaire d’authentification doivent être validées avant de lui donner les accès. Cependant nous ne disposons pas d’une base de données des utilisateurs que nous pouvons utiliser. IdentityServer pour des besoins de tests permet de définir et utiliser une liste de type TestUser.
Nous allons une nouvelle fois modifier le fichier Config.cs et ajouter le code suivant pour définir notre liste d’utilisateurs avec leurs revendications (claims):
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 public static List<TestUser> GetUsers() { return new List<TestUser> { new TestUser{SubjectId = "818727", Username = "alice", Password = "alice", Claims = { new Claim(JwtClaimTypes.Name, "Alice Smith"), new Claim(JwtClaimTypes.GivenName, "Alice"), new Claim(JwtClaimTypes.FamilyName, "Smith"), new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"), new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), new Claim(JwtClaimTypes.WebSite, "http://alice.com"), new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json) } }, new TestUser{SubjectId = "88421113", Username = "bob", Password = "bob", Claims = { new Claim(JwtClaimTypes.Name, "Bob Smith"), new Claim(JwtClaimTypes.GivenName, "Bob"), new Claim(JwtClaimTypes.FamilyName, "Smith"), new Claim(JwtClaimTypes.Email, "BobSmith@email.com"), new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), new Claim(JwtClaimTypes.WebSite, "http://bob.com"), new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json), new Claim("location", "somewhere") } } }; }
Nous devons également modifier la méthode ConfigureServices du fichier Startup.cs pour ajouter cette liste à la configuration d’IdentityServer. Cela se fait en utilisant la méthode d’extension AddTestUsers lors de l’appel de AddIdentityServer() :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); //configure identity server with in-memory stores, keys, clients and resources services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryIdentityResources(Config.GetIdentityResources()) .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients()) .AddTestUsers(Config.GetUsers()); ; }
Enregistrez les modifications et exécutez l’application. Vous aurez le résultat suivant affiché dans le navigateur :
Si vous cliquez sur « Click here to manage your stored grants. », vous essayerez d’accéder à une page protégée. De ce fait, vous serez redirigé vers la page d’authentification :
Vous venez de mettre en place une interface d’authentification en utilisant OpenID Connect. Dans le prochain billet, nous verrons comment configurer une application Web pour utiliser cette nouvelle fonctionnalité que nous avons intégrée à IdentityServer pour valider l’identité d’un utilisateur.
Restez connecté !