Added in Unreleased.

ZeeKayDa.Auth exposes an OpenID Connect discovery document as defined by OpenID Connect Discovery 1.0 Section 3 and Section 4.

For setup steps, see Configure discovery. For design rationale, see Why discovery matters.

Endpoint URL

Method: GET

Route:

  • Root issuer: /.well-known/openid-configuration
  • Path-bearing issuer: {issuer-path}/.well-known/openid-configuration

The route is constrained to the configured issuer host. A request for the same path on a different host is not handled by ZeeKayDa.Auth.

Examples:

  • Issuer: https://id.example.com
    Discovery URL: https://id.example.com/.well-known/openid-configuration
  • Issuer: https://id.example.com/tenant-a
    Discovery URL: https://id.example.com/tenant-a/.well-known/openid-configuration

This path behavior follows OpenID Connect Discovery 1.0 Section 4.1 and RFC 9207 Section 4.

Registration

Register services with AddZeeKayDaAuth(...), then map endpoints with app.MapZeeKayDaAuth().

using ZeeKayDa.Auth;
using ZeeKayDa.Auth.AspNetCore.Extensions;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddZeeKayDaAuth(options =>
{
    options.Issuer = "https://id.example.com";
});

var app = builder.Build();

app.UseRouting();
app.MapZeeKayDaAuth();

app.Run();

Response

Status code

  • 200 OK when discovery is configured correctly

Response headers

Header Value
Content-Type application/json
Cache-Control public, max-age=3600, must-revalidate by default; no-store when DiscoveryDocumentCacheMaxAgeSeconds is 0
Access-Control-Allow-Origin *

Metadata fields

All of the fields below are published in the discovery document. Some are fixed values, and others come from AuthorizationServerOptions.

JSON field Source Default / notes
issuer Issuer Published verbatim as configured.
authorization_endpoint AuthorizationEndpoint or derived from Issuer Default is {issuer}/connect/authorize.
token_endpoint TokenEndpoint or derived from Issuer Default is {issuer}/connect/token.
jwks_uri JwksUri or derived from Issuer Default is {issuer}/connect/jwks.
response_types_supported ResponseTypesSupported Defaults to ["code"]. Required by OIDC Discovery 1.0 Section 3.
scopes_supported IScopeRepository By default, published from the built-in repository containing openid and profile.
response_modes_supported ResponseModesSupported Defaults to ["query"].
grant_types_supported GrantTypesSupported Defaults to ["authorization_code"].
token_endpoint_auth_methods_supported TokenEndpointAuthMethodsSupported Defaults to ["client_secret_basic"].
subject_types_supported Fixed value Always ["public"]. Pairwise subject identifiers are not currently supported.
id_token_signing_alg_values_supported IdTokenSigningAlgValuesSupported Defaults to ["RS256"]. Required by OIDC Discovery 1.0 Section 3.

The recommended metadata fields are described by OpenID Connect Discovery 1.0 Section 3 and RFC 8414 Section 2.

To replace the default scope source, register a custom scope repository. For example:

using ZeeKayDa.Auth.Scopes;

var auth = builder.Services.AddZeeKayDaAuth(options =>
{
    options.Issuer = "https://id.example.com";
});

auth.AddInMemoryScopes(
[
    new ScopeDefinition
    {
        Name = ScopeNames.OpenId,
        IdTokenClaims = ["sub"],
        AccessTokenClaims = ["scope"],
    },
    new ScopeDefinition
    {
        Name = ScopeNames.Profile,
        IdTokenClaims = ["name", "family_name"],
        AccessTokenClaims = ["name"],
    },
    new ScopeDefinition
    {
        Name = "internal.admin",
        IsDiscoverable = false,
        AccessTokenClaims = ["scope"],
    },
]);

Only scopes with IsDiscoverable = true are included in scopes_supported.

Pre-alpha advertised endpoints

ZeeKayDa.Auth is pre-alpha. Discovery currently publishes default authorization_endpoint, token_endpoint, and jwks_uri values so clients can observe the intended metadata shape, but the protocol implementations are not complete yet.

Until those surfaces are implemented:

Endpoint Methods Status
{issuer}/connect/authorize GET, POST 501 Not Implemented
{issuer}/connect/token POST 501 Not Implemented
{issuer}/connect/jwks GET 501 Not Implemented

Endpoint URI derivation

When endpoint overrides are not set, ZeeKayDa.Auth derives published endpoint URLs from the configured issuer using URI combination rules.

For example, with this issuer:

https://id.example.com/tenant-a

the default published endpoints are:

  • https://id.example.com/tenant-a/connect/authorize
  • https://id.example.com/tenant-a/connect/token
  • https://id.example.com/tenant-a/connect/jwks

This matters for issuers with path segments.

Example document

{
  "issuer": "https://id.example.com/tenant-a",
  "authorization_endpoint": "https://id.example.com/tenant-a/connect/authorize",
  "token_endpoint": "https://id.example.com/tenant-a/connect/token",
  "jwks_uri": "https://id.example.com/tenant-a/connect/jwks",
  "response_types_supported": ["code"],
  "scopes_supported": ["openid", "profile", "api.read"],
  "response_modes_supported": ["query"],
  "grant_types_supported": ["authorization_code"],
  "token_endpoint_auth_methods_supported": ["client_secret_basic"],
  "subject_types_supported": ["public"],
  "id_token_signing_alg_values_supported": ["RS256"]
}

Startup validation

Discovery configuration is validated at startup.

Startup fails when:

  • Issuer is missing or empty
  • Issuer is not an absolute URI
  • Issuer uses HTTP and AllowInsecureIssuer is not enabled
  • Issuer uses HTTP with a non-loopback host
  • Issuer contains a query string or fragment
  • Issuer contains user information
  • ResponseTypesSupported or IdTokenSigningAlgValuesSupported is null or empty
  • any supported metadata collection is null
  • a custom scope repository is configured with blank or duplicate scope names

Warning: AllowInsecureIssuer = true is for local loopback development and testing only. It does not permit HTTP issuers on non-loopback hosts.