Identity
Blouppy.Identity is the Starter's own OAuth 2.0 / OpenID Connect server, built on
OpenIddict and ASP.NET Identity. It is a
separate ASP.NET Core application, with its own Razor pages and its own hexagon: it
references nothing of the API's.
What it handles
- Accounts — registration with e-mail confirmation, password reset, TOTP two-factor with recovery codes, GitHub and Google sign-in, a Cloudflare Turnstile CAPTCHA on the anonymous forms, and a rate limit per address on them.
- The protocol —
/connect/authorize,/connect/token,/connect/revocation,/connect/userinfo,/connect/endsession,/connect/introspect, and the key set at/.well-known/jwks. - Personal access tokens —
blp_pat_reference tokens, minted here and introspected by the API (see MCP and access tokens). - Single sign-on and SCIM — organizations' verified domains, their OpenID Connect connections and the SCIM 2.0 endpoint (see SSO and SCIM).
How it is put together
| Concern | Where |
|---|---|
| Storage | One context, ApplicationDbContext: ASP.NET Identity's tables and OpenIddict's applications, authorizations, scopes and tokens |
| Clients | Declared in code (Server/ServerConfiguration.cs) and brought in line on every start by ApplicationRegistrar — they are configuration, not sample data |
| Signing and encryption keys | Created on first start and stored in server_keys, protected by Data Protection, so every replica signs with the same key and a restart invalidates nothing. Certificates you provide can replace them |
| Claims | Rebuilt from the account at every sign-in and refresh (Server/UserPrincipalFactory) |
| Old tokens | Pruned every hour by TokenPruning: tokens and authorizations nobody can use any more, after 14 days |
The tokens the API sees
- The gateway's access token — a JWT signed with the server's RSA key, valid 15
minutes, audience
blouppy_api. The API validates it with ASP.NET Core's JWT handler. - Its refresh token — encrypted, readable only by the identity host, valid 14 days.
- A personal access token — a reference token: the API asks the identity host about it (introspection) and caches the answer for a minute.
Where the user's profile lives
The name, e-mail and avatar belong to the identity host. The application database reads
them through a projection, users_view, which is why no application domain owns them
and why the read side can join a member's name in the same query.
Sign-in pages
The pages — login, registration, two-factor, password reset, SSO sign-in — share one
layout, Pages/Shared/_AuthLayout.cshtml, styled with the design system's tokens. The
stylesheet is the Tailwind CLI's output, committed so the host builds without Node:
cd back/Blouppy.Identity && npm ci && npm run build:css