Skip to content
We just launched Duende IdentityServer v7.2.0 and BFF v3.0. Check it out!

Authentication Session

#Regardless of how the user proves their identity on the login page, an authentication session must be established. This authentication session is based on ASP.NET Core’s authentication system, and is tracked with a cookie managed by the cookie authentication handler.

To establish the session, ASP.NET Core provides a SignInAsync extension method on the HttpContext. This API accepts a ClaimsPrincipal which contains claims that describe the user. IdentityServer requires a special claim called sub whose value uniquely identifies the user. On your login page, this would be the code to establish the authentication session and issue the cookie:

var claims = new Claim[] {
new Claim("sub", "unique_id_for_your_user")
};
var identity = new ClaimsIdentity(claims, "pwd");
var user = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(user);

Additional claims can be added to the cookie if desired or needed at other UI pages. For example, it’s common to also issue a name claim which represents the user’s display name.

The claims issued in the cookie are passed as the Subject on the ProfileDataRequestContext in the profile service.

Well Known Claims Issued From the Login Page

Section titled “Well Known Claims Issued From the Login Page”

There are some claims beyond sub that can be issued by your login page to capture additional information about the user’s authentication session. Internally Duende IdentityServer will set some of these values if you do not specify them when calling SignInAsync. The claims are:

  • name: The display name of the user.
  • amr: Name of the authentication method used for user authentication ( defaults to pwd).
  • auth_time: Time in epoch format the user entered their credentials (defaults to the current time).
  • idp: Authentication scheme name of the external identity provider used for login. When not specified then the value defaults to local indicating that it was a local login. This is used to determine if a user must re-authenticate when clients make authorization requests using the acr_values with an idp value, or the client has IdentityProviderRestrictions. If the user’s idp does not match the request, then they should re-authenticate.
  • tenant: Tenant identifier the user is associated with (if needed). This is used to determine if a user must re-authenticate when clients make authorization requests using the acr_values with a tenant value. If the user’s tenant does not match the request, then they should re-authenticate.

While you can create the ClaimsPrincipal yourself, you can alternatively use IdentityServer extension methods and the IdentityServerUser class to make this easier:

var user = new IdentityServerUser("unique_id_for_your_user")
{
DisplayName = user.Username
};
await HttpContext.SignInAsync(user);

Duende IdentityServer registers a cookie authentication handler by default for the authentication session. The scheme that the handler in the authentication system is identified by is from the constant IdentityServerConstants.DefaultCookieAuthenticationScheme.

When configuring IdentityServer, the AuthenticationOptions expose some settings to control the cookie (e.g. expiration and sliding). For example:

Program.cs
builder.Services.AddIdentityServer(options =>
{
options.Authentication.CookieLifetime = TimeSpan.FromHours(1);
options.Authentication.CookieSlidingExpiration = false;
});

If you require more control over the cookie authentication handler you can register your own cookie handler. You can then configure IdentityServer to use your cookie handler by setting the CookieAuthenticationScheme on the AuthenticationOptions. For example:

Program.cs
builder.Services.AddAuthentication()
.AddCookie("your_cookie", options => {
// ...
});
builder.Services.AddIdentityServer(options =>
{
options.Authentication.CookieAuthenticationScheme = "your_cookie";
});

If the CookieAuthenticationScheme is not set, the DefaultAuthenticationScheme configured for ASP.NET Core will be used instead. Note that the AddAuthentication call that sets the default can come after the AddIdentityServer call. For example:

Program.cs
// No cookie authentication scheme is set here.
// Identity Server will use the default scheme from ASP.NET Core,
// even though it is not yet defined.
builder.Services.AddIdentityServer();
// Default scheme is registered. IdentityServer will use this scheme.
builder.Services.AddAuthentication(defaultScheme: "your_cookie")
.AddCookie("your_cookie", options => {
// ...
});