Aller au contenu principal

Authentification Forms et gestion de la connexion

L'authentification Forms active une connexion par login et mot de passe. Elle se configure côté serveur dans OnConfigureAuthentification.

Activer Forms​

Main.cs
protected override void OnConfigureAuthentification(AuthenticationOptions options)
{
// Active la saisie login / mot de passe sur la page de connexion.
options.AllowFormAuthentication = true;
}

Forms peut être combiné avec Windows ou un fournisseur externe. Dans ce cas, la page de connexion détermine si elle doit rediriger l'utilisateur vers un fournisseur externe ou afficher le mot de passe Forms.

Workflow d'authentification​

Lorsqu'un utilisateur tente de se connecter, l'application peut intervenir dans le fichier Main.cs du projet serveur.

ÉtapeMéthodeUsage
Impersonation de développementGetImpersonatedIdentity()Simuler une identité en DEBUG uniquement.
Configuration du contexteOnConfigureAuthenticationContext(AuthenticationContext context)Définir AllowUnknownUser, IsEmailLogin ou les options de rôles personnalisés.
Résolution utilisateurGetIdentityUserAsync(AuthenticationContext context)Retrouver l'utilisateur à partir du contexte. À surcharger seulement pour des cas particuliers.
Utilisateur inconnuOnUnknownUserAsync(AuthenticationContext context)Créer ou refuser un utilisateur absent de la base.
Post-connexionOnSignInAsync(AuthenticationContext context, ApplicationUser user)Mettre à jour l'utilisateur, ses rôles, ses claims ou les choix de rôle.
Forms et utilisateurs inconnus

Par défaut, l'exemple Demo ne déclenche pas la création automatique pour Forms : AllowUnknownUser est positionné à false quand AuthenticationMode vaut Forms.

Configurer le contexte d'authentification​

Main.cs
protected override void OnConfigureAuthenticationContext(AuthenticationContext context)
{
// Les utilisateurs inconnus ne sont acceptés que hors Forms.
context.AllowUnknownUser = context.IdentitySource.AuthenticationMode != AuthenticationMode.Forms;

// La recherche utilisateur se fait par UserName plutôt que par Email.
context.IsEmailLogin = false;
}

Les propriétés principales du contexte sont :

PropriétéDescription
IdentitySource.AuthenticationModeMode de connexion : Forms, Windows ou SSO.
IdentitySource.ClaimsClaims fournis par le fournisseur d'identité, notamment en SSO.
IdentitySource.SourceNameNom de la source d'identité.
IdentitySource.UserLoginLogin fourni par la source d'identité.
AllowUnknownUserIndique si OnUnknownUserAsync peut être appelé.
IsEmailLoginIndique si l'utilisateur est recherché par Email plutôt que par UserName.
IsCustomRolesEnabledIndique si les rôles doivent être remplacés par les rôles personnalisés du contexte.

Impersonation en développement​

GetImpersonatedIdentity() sert uniquement aux tests et au développement. La méthode doit rester protégée par #if DEBUG.

Main.cs
#if DEBUG
public override IdentitySource GetImpersonatedIdentity()
{
// Lit l'identité simulée depuis la configuration de développement.
return ImpersonatedIdentity.FromConfiguration(Configuration);
}
#endif
appsettings.Development.json
{
"Impersonate": {
"Enabled": true,
"Login": "admin",
"FirstName": "Admin",
"LastName": "Demo"
}
}

Gérer un utilisateur inconnu​

OnUnknownUserAsync est appelée si aucun utilisateur n'est trouvé et si AllowUnknownUser l'autorise. Elle peut retourner un utilisateur créé par l'application ou null pour refuser la connexion.

Main.cs
protected override Task<ApplicationUser> OnUnknownUserAsync(AuthenticationContext context)
{
// L'application refuse la création automatique de l'utilisateur.
return Task.FromResult<ApplicationUser>(null);
}

Exemple de création à la connexion pour une identité non Forms :

Main.cs
protected override Task<ApplicationUser> OnUnknownUserAsync(AuthenticationContext context)
{
string userLogin = context.IdentitySource.UserLogin;

ApplicationUser user = new()
{
Email = userLogin,
UserName = userLogin,
EmailConfirmed = true
};

// Crée l'utilisateur avec un rôle applicatif.
return CreateUserAsync(user, Roles.User);
}

Gérer la post-connexion avec OnSignInAsync​

OnSignInAsync est appelée lorsque l'utilisateur est connu. Elle permet notamment de mettre à jour les rôles issus d'un facteur externe ou d'ajouter des claims au jeton avec context.AddCustomClaim(...). Un claim utilisé par une policy du serveur doit être déclaré dans AuthenticationOptions.AccessTokenClaims : voir Policy fondée sur un claim personnalisé.

Main.cs
protected override Task OnSignInAsync(AuthenticationContext context, ApplicationUser user)
{
// Les rôles externes remplacent les rôles existants pendant la connexion.
context.IsCustomRolesEnabled = true;
context.AddCustomRoles(GetExternalRoles(context.IdentitySource.UserLogin));

return Task.CompletedTask;
}

private static IEnumerable<string> GetExternalRoles(string userLogin)
{
// Exemple pédagogique : remplacer par la source externe réelle de l'application.
return new[] { Roles.User.ToString(), Roles.Admin.ToString() };
}
Rôles personnalisés

AddCustomRole et AddCustomRoles nécessitent d'activer IsCustomRolesEnabled avant l'ajout. Si aucun rôle n'est disponible, la connexion échoue.

Choix de rôle ou de profil​

Si l'utilisateur possède plusieurs rôles, l'application peut proposer un choix pendant le workflow.

Main.cs
protected override Task OnSignInAsync(AuthenticationContext context, ApplicationUser user)
{
// Propose les rôles disponibles à l'utilisateur connecté.
context.EnableGroupChoice<Roles>();

return Task.CompletedTask;
}

Il est aussi possible d'ajouter explicitement des choix regroupant des rôles.

Main.cs
protected override Task OnSignInAsync(AuthenticationContext context, ApplicationUser user)
{
// Propose des profils composés de rôles applicatifs.
context.AddRoleChoice("Admin & User", Roles.Admin.ToString(), Roles.User.ToString());
context.AddRoleChoice("Only Admin", Roles.Admin.ToString());
context.AddRoleChoice("Only User", Roles.User.ToString());

return Task.CompletedTask;
}

Retrouver l'utilisateur​

Par défaut, Lagoon retrouve l'utilisateur avec FindByEmailAsync si IsEmailLogin est vrai, sinon avec FindByNameAsync. Ne surchargez GetIdentityUserAsync que pour un cas particulier, par exemple plusieurs comptes pour un même utilisateur avec une notion actif/inactif.