Dynamic Client Registration
Enable DCR only when you need runtime registration for compatibility clients.
DCR is the compatibility path in SqlOS.
It exists for real clients that still expect runtime registration at POST /register.
Enable DCR when:
Keep it off when:
CIMD is available and fits the clientbuilder.AddSqlOS<AppDbContext>(options =>
{
options.AuthServer.EnableChatGptCompatibility(dcr =>
{
dcr.MaxRegistrationsPerWindow = 25;
});
});Or enable it directly:
builder.AddSqlOS<AppDbContext>(options =>
{
options.AuthServer.ClientRegistration.Dcr.Enabled = true;
});SqlOS then advertises registration_endpoint in auth-server metadata.
SqlOS intentionally keeps DCR narrow:
authorization_coderesponse_types=codetoken_endpoint_auth_method=nonescope, persisted as the client's allow-list and echoed on the registration responseSqlOS does not use DCR for:
Honor the RFC 7591 scope member. SqlOS persists the registered set as AllowedScopesJson and always echoes scope on the 201 response so the client can predict later grants from that response alone.
scope is omitted, SqlOS registers an empty allow-list and echoes scope as an empty string. Later authorize, device, and client_credentials grants then intersect to nothing.ClientRegistration.Dcr.AllowedScopes is non-empty, it is the operator ceiling. Requested scopes outside that set are invalid_client_metadata.MaxScopeCount (default 32) and MaxScopeLength (default 128). Exceeding those limits is a registration error.builder.AddSqlOS<AppDbContext>(options =>
{
options.AuthServer.EnableChatGptCompatibility(dcr =>
{
dcr.AllowedScopes.Add("openid");
dcr.AllowedScopes.Add("profile");
dcr.AllowedScopes.Add("offline_access");
dcr.MaxScopeCount = 16;
});
});openid is stored and granted as an ordinary allow-listed string. It is never always-allowed, and because a registration without scope stores an empty allow-list, a dynamically registered client must be granted openid deliberately — in the registration request or by an operator afterward. With OpenID Provider mode enabled (the default), a granted openid mints an id_token at the token endpoint; the warning when an OIDC-capable client omits openid is on the admin, dashboard, hosted, and headless surfaces.
DCR creates real client rows in the existing store, so lifecycle controls matter.
SqlOS includes:
AllowedScopes ceiling plus count/length boundsUse a policy hook when redirect rules alone are not enough:
builder.AddSqlOS<AppDbContext>(options =>
{
options.AuthServer.ClientRegistration.Dcr.Policy = async (context, cancellationToken) =>
{
if (context.RedirectUris.Count == 0)
{
return SqlOSClientRegistrationPolicyDecision.Deny("At least one redirect URI is required.");
}
return SqlOSClientRegistrationPolicyDecision.Allow();
};
});This is the right place for: