Protéger une application web
Introduction
Maintenant que nous avons les fondamentaux de la création du serveur d’identité, nous allons pouvoir commencer à créer des applications qui consommeront notre SSO. Ceci pourra se faire de deux manières différentes. Premièrement, l’authentification de notre utilisateur. Deuxièmement, l’authentification de notre application auprès d’une API. Les deux peuvent se rejoindre, mais ce n’est pas une obligation. Notre application web peut avoir sa propre authentification, indépendante de l’utilisateur connecté, afin d’effectuer des opérations auprès de services de l’écosystème.
Créer l’application cliente
Avant de pouvoir consommer notre SSO, notre future application web doit être déclarée auprès de celui-ci. Nous allons donc commencer par déclarer dans le SSO une application cliente et ses options.
1. Client pour une application web MVC
Le type d’application cliente influe sur la configuration de celle-ci, il est donc nécessaire de savoir à l’avance à quel type d’application on a affaire, faute de quoi la configuration risque d’être erronée. Pour ce premier cas, nous allons créer une application cliente qui sera une application ASP.NET MVC classique (le fonctionnement pour les les applications ASP .NET utilisant les pages razor est identique).
Dans notre méthode Seed(), à la suite des IdentityResources, nous allons ajouter la configuration d’une application cliente :
if (!await configurationDbContext.Clients.AnyAsync(client =>
client.ClientId == "78D9E2F100D049E8A46477CEFC811C49"))
{
Client mvcWebApplication = new Client
{
AllowedGrantTypes = GrantTypes.Code,
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email
},
ClientId = "78D9E2F100D049E8A46477CEFC811C49",
ClientName = "MVC Web Application",
ClientSecrets = {
new Secret("22435308B4C04FD9B4886BC4457F66B445AB50DF52E34F3C904B841F
380F7225".ToSha256())
},
PostLogoutRedirectUris = {
"https://localhost:5001/signout-callback-oidc"
},
RedirectUris = {
"https://localhost:5001/signin-oidc" }
}; ...
Consommer une API
Il peut arriver qu’une application web « classique » soit amenée à consommer une API protégée par OAuth. On distingue deux cas de figure :
-
L’API nécessite un utilisateur identifié.
-
L’API se contente de l’identification de l’application entrante.
1. L’API nécessite un utilisateur identifié
Dans ce cas, il existe une problématique de cycle de vie du token.
Quand l’utilisateur s’authentifie, le SSO retourne un token qui justifie de son identité. À ce moment, un cookie est émis et c’est ce cookie qui servira tout au long de l’utilisation de l’application. Le cookie ne pouvant être utilisé pour authentifier l’utilisateur auprès de l’API, il y a un premier enjeu de conservation du token afin de l’avoir à disposition pour la suite. Une application web étant par défaut stateless et potentiellement multi-instance, le plus simple pour conserver un token est de le conserver dans le cookie d’authentification. Attention donc à conserver des tokens courts afin de ne pas alourdir celui-ci.
Le deuxième enjeu est un enjeu de cycle de vie.
Le cookie a une durée de vie plus ou moins longue, renouvelable, etc., alors que l’access token a une durée de vie fixe d’une heure (par défaut). Le problème de son renouvellement est également un vrai sujet car il faut que ce soit fait sans déranger l’utilisateur dans son travail.
Pour ce faire, nous allons faire appel à deux choses :
La sauvegarde du token. Le middleware qui gère OpenID Connect nous offre toutes les mécaniques nécessaires. Reprenez les options passées en argument de la méthode AddOpenIdConnect() :
.AddOpenIdConnect(options =>
{
......
options.SaveTokens = true;
});
La deuxième étape consiste à se brancher sur le cycle de vie du cookie. Le token est stocké dans le cookie. Le cookie faisant foi pour l’authentification de l’utilisateur, celui-ci est scruté à chaque appel. Nous allons donc profiter de cette mécanique pour regarder également notre token.
Jusque-là...