IdentityServer UI Flows: Login, Logout, Consent, and Federation
When to Use This Skill
- Building or customizing the login page (local credentials, MFA, passwordless)
- Integrating external identity providers (Google, Azure AD, SAML, etc.)
- Implementing the consent page for third-party client authorization
- Building the logout flow with session cleanup and client notifications
- Implementing a federation gateway with Home Realm Discovery (HRD)
- Handling and displaying error pages for protocol errors
- Using
IIdentityServerInteractionServiceto interact with the protocol engine - Redirecting users back to clients after login/logout
Docs: https://docs.duendesoftware.com/identityserver/ui
Architecture Overview
IdentityServer separates the protocol engine from the user interface. The engine handles OAuth/OIDC endpoints and redirects to your UI pages as needed. Your UI code handles all user interaction and then communicates results back to the engine.
Required Pages
Login Page
Configuring the Login URL
If not set, IdentityServer infers the URL from the cookie handler's LoginPath:
Authorization Context
When IdentityServer redirects to the login page, it passes a returnUrl query parameter. Use IIdentityServerInteractionService.GetAuthorizationContextAsync to extract the original authorization request parameters:
Important: Do not parse the returnUrl yourself. Always use the interaction service.
Establishing the Authentication Session
After validating credentials, create the authentication session:
Or with explicit claims:
Well-Known Session Claims
Protecting Against Open Redirects
Always validate the returnUrl before redirecting:
Completing Login with CompleteLoginAsync
After establishing the authentication session, redirect the user back to the returnUrl. This causes the browser to re-issue the original authorize request, allowing IdentityServer to complete the protocol workflow.
External Login (Federation)
Registering External Providers
Triggering External Authentication
Handling the Callback
SignInScheme and SignOutScheme
State and URL Length
If external provider state makes the URL too long (>2000 chars), use the IdentityServer-provided IDistributedCache-backed data format:
Logout Page
Configuring the Logout URL
Logout Steps
- End the IdentityServer session — remove the authentication cookie
- Sign out of external provider — if an external login was used
- Notify client applications — via front-channel, back-channel, or JS-based notifications
- Redirect back to client — if the logout is client-initiated
Client Notification Mechanisms
Recommendation: Use back-channel notifications for cross-site architectures. Front-channel and JS-based notifications rely on cookies in iframes, which may not work reliably across different sites.
Getting Logout Context
Back-Channel Logout
Back-channel logout happens automatically when you call HttpContext.SignOutAsync() — IdentityServer uses IBackChannelLogoutService to notify all clients that have BackChannelLogoutUri configured.
For .NET clients: use the BFF framework which has built-in back-channel logout support, or see the IdentityServer samples.
Consent Page
When Consent Is Required
Consent applies only to user-based (interactive) authorization requests. Client-credentials (M2M) flows never prompt for consent — there Client.AllowedScopes alone governs access.
Consent is controlled per client via RequireConsent (default: false). Set RequireConsent = false for first-party clients to suppress the scope prompt; set true for third-party clients. When enabled, IdentityServer redirects to the consent page before completing authorization.
The offline_access scope always triggers consent when the client has consent enabled.
Required vs. Optional Scopes
IdentityResource and ApiScope expose a Required bool:
- If the consent response omits a
Requiredscope, IdentityServer returnsaccess_deniedand the request fails. - Optional scopes can be declined and the flow still succeeds — the issued tokens/userinfo simply omit that data.
Remembered Consent
Enable persistence with Client.AllowRememberConsent (bool) and Client.ConsentLifetime (expiry). Granted scopes are stored in the operational (persisted grant) store; set RememberConsent = true on the ConsentResponse to persist a grant.
IdentityServer re-prompts for consent when:
- there is no remembered consent, or it has expired,
- a new, not-previously-granted scope is requested,
- the request includes
offline_access, - the request contains a parameterized scope value, or
AllowRememberConsent = false.
Device flow: in IdentityServer v8, device-flow (Device Authorization Grant) consent is never remembered — the user consents on every device authorization.
Revoking Consent
Use IIdentityServerInteractionService.RevokeUserConsentAsync(clientId) for the current user. This removes all persisted grants for that user/client — remembered consent, reference tokens, and refresh tokens.
Consent Page Flow
Denying Consent
Validating returnUrl
User Registration (prompt=create)
The prompt=create OIDC parameter sends the user straight to a registration page instead of login.
Host Configuration
Set CreateAccountUrl in AddIdentityServer. This makes IdentityServer advertise create in prompt_values_supported in discovery. If unset, prompt=create is ignored and not advertised.
prompt=create must be the only prompt value — it cannot be combined with login, consent, select_account, or none.
Triggering Registration from an ASP.NET Core Client
Registration Page Handler (Host)
Important: GetAuthorizationContextAsync returning null signals an invalid returnUrl — redirect away instead of trusting it. Establish the session only after any required confirmation/approval/MFA step.
Error Page
Configuration
Retrieving Error Details
Errors are commonly due to misconfiguration. The error page should inform the user something went wrong without exposing sensitive details.
Federation Gateway and Home Realm Discovery
What Is a Federation Gateway?
A federation gateway architecture shields clients from authentication complexity. Clients trust only IdentityServer; the gateway coordinates with external providers, handling protocol bridging (OIDC, SAML, WS-Fed), claim transformation, and trust management.
Home Realm Discovery (HRD) Strategies
Restricting Providers Per Client
HRD via acr_values
Clients can hint at the desired provider:
Your login page checks context.IdP from GetAuthorizationContextAsync and can skip the login UI entirely, redirecting straight to the external provider.
Common Anti-Patterns
-
❌ Parsing
returnUrlmanually to extract authorization parameters -
✅ Use
IIdentityServerInteractionService.GetAuthorizationContextAsync(returnUrl) -
❌ Redirecting to
returnUrlwithout validation, enabling open redirect attacks -
✅ Validate with
Url.IsLocalUrl()or_interaction.IsValidReturnUrl() -
❌ Forgetting to delete the external authentication cookie after callback processing
-
✅ Always call
HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme) -
❌ Using front-channel logout across different sites/domains (cookie/iframe issues)
-
✅ Use back-channel logout for cross-site architectures
-
❌ Issuing the authentication session without a
subclaim -
✅ The
subclaim is required — it uniquely identifies the user and must never change -
❌ Hardcoding external provider list without checking both static schemes and dynamic providers
-
✅ Query
IAuthenticationSchemeProviderfor static schemes andIIdentityProviderStorefor dynamic providers
Common Pitfalls
-
Login page does not preserve
returnUrl: ThereturnUrlmust survive across all page transitions (post-backs, external redirects, MFA steps). Store it in hidden form fields, route data, or theAuthenticationProperties.Itemsdictionary. -
Cookie handler
LoginPathmismatch: If no explicitLoginUrlis configured, IdentityServer infers it from the cookie handler'sLoginPath. Make sure the cookie handlerLoginPathmatches your actual login page route. TheLogoutUrlis not inferred from the cookie handler — it must always be set explicitly viaopt.UserInteraction.LogoutUrl. -
SignOutScheme differs with ASP.NET Identity: When using ASP.NET Identity, the
SignOutSchemefor external providers should beIdentityConstants.ApplicationScheme, notIdentityServerConstants.SignoutScheme. -
Consent persistence is temporary by default: The consent result between the consent page and authorization endpoint is stored in a cookie. For custom persistence, implement
IConsentMessageStore. -
Error messages are deliberately brief: For security, error messages returned to clients are minimal. Check the IdentityServer logs (at
Debuglevel) for full error details. -
External provider
subis provider-specific: Thesubclaim from an external provider is that provider's unique ID. Map it to your local user database — do not use it directly as the IdentityServersub.


