Overview of authentication and authorization
Lagoon relies on ASP.NET Core Identity to manage users, roles, hashed passwords, account recovery, account confirmation, and related mechanisms. An application must therefore not define its own user/role tables: the framework adds the Identity tables prefixed with AspNet to the data model.
| Table | Role |
|---|---|
AspNetUsers | Application users. |
AspNetRoles | Roles declared for the application. |
AspNetUserRoles | Association between users and roles. |
The other AspNet* tables serve Identity mechanisms such as password reset tokens, email address confirmation, or two-factor authentication.
An application connected only via SSO or Windows can also register no users in these tables: see Stateless users.
Supported authentication modes
The authentication modes documented for Lagoon are:
- anonymous mode, to open all or part of the application without identification;
- Windows authentication;
- Forms authentication, with login and password;
- SAML2, see SAML2 section;
- OpenID Connect / OAuth2, see OIDC section;
- external OAuth providers compatible with ASP.NET Core.
Combining several methods is possible. For example, an application can enable Forms and Windows: the login page then shows the form and the Windows login button.
Mode configuration examples
Windows only
protected override void OnConfigureAuthentification(AuthenticationOptions options)
{
// Active l'authentification Windows.
options.AllowWindowsAuthentication = true;
}
Forms only
protected override void OnConfigureAuthentification(AuthenticationOptions options)
{
// Active l'authentification par formulaire.
options.AllowFormAuthentication = true;
}
Forms + Windows
protected override void OnConfigureAuthentification(AuthenticationOptions options)
{
// Affiche le formulaire et le bouton de connexion Windows.
options.AllowFormAuthentication = true;
options.AllowWindowsAuthentication = true;
}
External providers
To use an external provider, an application must be created with that provider. It must be configured to redirect the authenticated user back to the application. After creation, retrieve the ClientId and ClientSecret and enter them in the application.
protected override void OnConfigureServices(IServiceCollection services)
{
services.AddAuthentication().AddGoogle("Google", "Explicit", options =>
{
// Renseigne les informations obtenues auprès du fournisseur externe.
options.ClientId = "";
options.ClientSecret = "";
});
}
The Explicit parameter displays a button labeled Google on the login page. An implicit configuration is possible with a regular expression in place of Explicit, to select the provider based on the entered identifier.
protected override void OnConfigureServices(IServiceCollection services)
{
services.AddAuthentication().AddGoogle("Google", "^(.*)@(gmail.com)$", options =>
{
// Renseigne les informations obtenues auprès du fournisseur externe.
options.ClientId = "";
options.ClientSecret = "";
});
}
With this configuration, un.utilisateur@gmail.com is authenticated with Google, while admin continues to the Forms password input if Forms is enabled.
Server wiring
On the server side, the entry point calls LagoonWebApplication.Run<Main>(args). The Main class inherits from LgAuthApplication<TDbContext, TUser> and centralizes the configuration of authentication, authorization, the HTTP pipeline, the DbContext, and services.
namespace Demo.Server;
/// <summary>
/// The entry point of the application.
/// </summary>
public class Program
{
/// <summary>
/// Application startup.
/// </summary>
/// <param name="args">The arguments.</param>
public static void Main(string[] args)
{
// Délègue le démarrage du serveur ASP.NET Core à Lagoon.
LagoonWebApplication.Run<Main>(args);
}
}
public class Main : LgAuthApplication<ApplicationDbContext, ApplicationUser>
{
protected override void OnConfigureAuthentification(AuthenticationOptions options)
{
// Autorise l'accès non authentifié au fichier index.html.
options.AllowAnonymousIndex = true;
// Active l'authentification par formulaire.
options.AllowFormAuthentication = true;
}
protected override void OnConfigureAuthorization(AuthorizationOptions options)
{
// Enregistre les policies partagées par le serveur et le client.
Policies.ConfigureAuthorization(options);
}
}
HTTP pipeline
The server pipeline must enable authentication before authorization and keep the Lagoon fallback for Blazor WebAssembly routing.
protected override void OnConfigure(IApplicationBuilder app)
{
if (ApplicationInformation.IsDevelopment)
{
app.UseWebAssemblyDebugging();
}
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
// Active les middlewares ASP.NET Core d'authentification et d'autorisation.
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapLagoonFallback();
});
}
MapLagoonFallback() is mandatory: it handles Blazor SPA routing, Lagoon endpoints, and the fallback to index.html.
Client wiring
On the Blazor WebAssembly client side, the entry point calls LagoonWebAssemblyApplication.RunAsync<Main>(args). Policies must be registered on the client side using the same method as on the server.
public class Main : LgCustomApplication
{
protected override void OnConfigureAuthorization(AuthorizationOptions options)
{
// Le client connaît les mêmes policies que le serveur.
Policies.ConfigureAuthorization(options);
}
}
Automatic login page
The login page adapts to the configuration:
| Configuration | Behavior |
|---|---|
| Windows only | Automatic login of the user. |
| A single external provider | Automatic login if the user is already authenticated with the provider, otherwise redirection to that provider. |
| Forms only | Login and password input. |
| Forms + external provider | Login input, optional detection of a provider associated with the domain, then SSO redirection or password input. |
Anonymous access
By default, Lagoon requires authentication before allowing access to the application. To open the home page, index.html must be authorized on the server side and the page must be marked as anonymous.
protected override void OnConfigureAuthentification(AuthenticationOptions options)
{
// Autorise l'accès à index.html sans utilisateur authentifié.
options.AllowAnonymousIndex = true;
}
[AllowAnonymous]
public partial class Index : LgPage
{
}
Advanced authentication options
Some options are carried by AuthenticationOptions.
| Option | Usage |
|---|---|
AllowFormAuthentication | Enables Forms. |
AllowWindowsAuthentication | Enables Windows. |
AllowAnonymousIndex | Authorizes index.html for unauthenticated users. |
FormAuthenticationCookieLifeTime | Duration, in days, of the Forms ticket stored in the cookie. |
SsoAuthenticationCookieLifeTime | Duration, in days, of the Windows/SSO ticket stored in the cookie. |
AccessTokenLifetime | Lifetime of the access token, in seconds. Default value: 1800. |
PasswordOptions | Complexity rules for the Forms password. |
AccessTokenClaims | Claims issued in the access token: see Policy based on a custom claim. |
PreserveStoredClaims | Preserves stored claims (AspNetUserClaims) on login whose type is not added by the login. Default value: false. See Claims stored in database. |
protected override void OnConfigureAuthentification(AuthenticationOptions options)
{
options.AllowFormAuthentication = true;
// Durée du ticket Forms lorsque l'utilisateur conserve sa session.
options.FormAuthenticationCookieLifeTime = 365;
// Durée du ticket Windows/SSO.
options.SsoAuthenticationCookieLifeTime = 1;
// Durée de vie du jeton d'accès en secondes.
options.AccessTokenLifetime = 1800;
// Règles de complexité du mot de passe Forms.
options.PasswordOptions.RequiredLength = 6;
options.PasswordOptions.RequiredUniqueChars = 1;
options.PasswordOptions.RequireDigit = true;
options.PasswordOptions.RequireNonAlphanumeric = true;
options.PasswordOptions.RequireLowercase = true;
options.PasswordOptions.RequireUppercase = true;
}
Logout and tokens
Lagoon uses JWT access tokens. On logout, the token is removed from the client browser storage and can no longer be renewed from the refresh token.
An access token already copied or stored before logout remains valid until it expires. A JWT is stateless: it is not possible to expire it manually on the server after it has been created.
See also: logout.md.