Feature Spotlight: Fully customizable UIs and UI Workflows
This is the fourth part in a series of posts covering new (and old) features of Duende IdentityServer. These posts are not supposed to be super technical deep dives (that’s what documentation is for), but rather explain the feature at a more conceptual level, why it exists, and why it might useful for you.
The Problem
Every login workflow is different. In some cases changing some colours and a logo is sufficient, but in most cases more modifications are necessary. Here are some examples:
- full control over login page look and feel
- splitting up the login process into multiple pages
- custom visualization and filtering of external provider options
- full control over data access and validation
- connect to legacy data sources
- live-migrate / consolidate legacy accounts into new systems
- customize password policies
- adding extra workflows when necessary
- different UIs for first-time vs returning users
- registration or on-boarding steps
- adding extra (but optional) UI steps like EULAs
- Including user management features
- change/forgot password
- profile self-service
- incorporating various user authentication methods
- multi-factor (SMS, email, TOTP etc..)
- FIDO2
- federation
- choice of UI technology
- MVC/Razor, Javascript/Angular/React/etc, WASM
- location of UI (and thus separation of teams)
- co-located with IdentityServer vs separate host
There are certainly more variations of the above, but you get the idea.
The Solution
This is why we designed the UI as a first-class extensibility point right from the start - and the contract is very simple. You configure the entry point to your UI on the IdentityServer options:
services.AddIdentityServer(options =>
{
options.UserInteraction.LoginUrl = "/login";
});
Whenever we determine that user interaction is required, we redirect to the above endpoint. In addition we add a return URL parameter that contains all the information about the current protocol request to customise the UI workflow.
GET /login?returnUrl=...
You can now build an arbitrarily complex UI workflow.
When you are done, our expectation is that you have started a session for the user via the standard ASP.NET Core SignIn mechanism, and come back to the return URL we gave you. IdentityServer will then pick up the rest of the protocol work and ultimately return back to the client application. That’s it!
The technology that is used to implement the UI - or the physical location of the UI does not make a difference to IdentityServer, as long as the above contract is implemented.
If you want to redirect to a UI that it hosted in a different application, you do this instead:
services.AddIdentityServer(options =>
{
options.UserInteraction.LoginUrl = "https://login.mycompany.com/login";
});
Our Quickstart UI and UI template as well as the ASP.NET Identity integration are written in MVC. We are planning to replace this with Razor Pages in the near future (here’s the PR but it needs more work). In addition we provide a sample JavaScript-based UI that demonstrates the needed mechanics between front and backend.