Reference

OAuth server (OpenIddict)

Opt-in package that lets other apps and tool clients sign users in through your app and get access tokens.

AuthEndpoints.OpenIddict (preview) turns an AuthEndpoints app into an OAuth 2.0 authorization server, built on OpenIddict 7.7. The core AuthEndpoints package does not change and has no OpenIddict dependency.

The package README covers setup, the consent step, certificates, dynamic registration, and every setting.

In short

The default recipe is one registration call and one map call, like AddPasswordAuth / MapPasswordAuth:

builder.Services.AddOAuthServer<AppUser, AppDbContext>(options =>
{
    options.Issuer = new Uri("https://auth.example.com/");
    options.Audience = "https://api.example.com/";
    options.Scopes.Add("api");
    options.LoginUrl = "https://app.example.com/sign-in";
    options.ConsentUrl = "https://app.example.com/oauth/consent";
    options.Certificates.Path = "/var/lib/myapp/oauth-keys";
});

// OnModelCreating
builder.UseAuthEndpointsOpenIddict<AppUser>();

app.MapOAuthServer();
await app.Services.SeedOAuthClientsAsync(); // after migrations, when options.Clients is used
  • MapOAuthServer maps the authorization server, the JSON consent API (/oauth), and developer app management (/oauth/apps). Turn the consent API or developer apps off, or move them, with app.MapOAuthServer(parts => …). Anonymous (dynamic) registration stays off unless options.DynamicRegistration.Enabled is set. The recipe does not seed configured clients, because only the host knows when its migrations have run.
  • The building blocks (AddAuthEndpointsOpenIddict, MapAuthEndpointsOpenIddict, MapOAuthConsentEndpoints, MapOAuthDeveloperAppEndpoints) stay public for hosts that want them one by one.
  • Authorization code + PKCE (S256 only), rotating refresh tokens with no reuse leeway, 15-minute reference access tokens, revocation.
  • /connect/authorize sends signed-out users to LoginUrl with a returnUrl on this server, and signed-in users to ConsentUrl?request={id}. Your page approves or denies through the consent API or IOAuthConsentService.
  • The token subject defaults to the Identity user id. Replace it with IOAuthPrincipalFactory.
  • Every code exchange and refresh checks the approving user again (exists, can sign in, not locked out, same security stamp). A failed check revokes the grant.
  • Developer apps: signed-in users register OAuth apps they own through the developer app API. A confidential app gets a client secret that is shown once; a public app (SPA, native, CLI) uses PKCE only. Optional admin approval, per-user limits, and secret rotation. The consent card shows a developer app's homepage, description, and whether it is confidential. It shows an owner only through a host IOAuthDeveloperAppOwnerDisplay, never the owner's email or user name.
  • Redirect URIs match exactly, except that loopback IP redirects (http://127.0.0.1, http://[::1]) may use any port (RFC 8252 §7.3).
  • Dynamic client registration and protected resource metadata are off by default.
  • HTTPS, resource (audience) validation, and per-client resource permissions are on by default.

Relation to external sign-in

External OAuth signs users in to your app with another provider. This package makes your app the provider. A user who signed in with a cookie-mode external provider can approve an OAuth client like any other signed-in user.

Limitations

This is a preview. OpenID Connect (ID tokens, userinfo, logout, and the email, email_verified, and amr claims) is not supported yet, and only this server can validate its access tokens. The package README lists every known gap. Remaining work is tracked in #389.