Don't seed openid/profile/offline_access as ApiScopes

IdentityServer8 refuses to start when an IdentityResource and an
ApiScope share the same Name — it throws

  Found identity scopes and API scopes that use the same names.
  This is an invalid configuration. Scopes found: openid, profile

and the host crashes before serving any request.

Constants.BuildInApiScopes has historically listed 'openid',
'profile' and 'offline_access' alongside the application scopes
(admin, moderation, performer, client). The IdentityResource
counterparts are seeded separately via
IdentityResources.OpenId().ToEntity() /
IdentityResources.Profile().ToEntity() in
EnsureDefaultApplicationScopes, so listing them again in
BuildInApiScopes produces a duplicate 'openid' / 'profile' once
that seeder is wired into MigrateDatabase and starts running on
every restart (commit be334a69). 'offline_access' is handled
directly by IdentityServer8 (DefaultResourceValidator has a
special-case branch for it) and never needs an ApiScope row.

Trim BuildInApiScopes to application scopes only. The live
ConfigurationDb already contains both IdentityResources and
ApiScopes for the same names from earlier hand-rolled SQL
bootstrap, so the duplicate-name check fires the moment the
process tries to enumerate its resources at startup.
This commit is contained in:
Paul Schneider 2026-06-25 23:11:16 +01:00
commit 68eb24ba44

View file

@ -4,8 +4,17 @@ using IdentityServer8.EntityFramework.Entities;
public static class Constants
{
// ApiScopes seeded explicitly by EnsureDefaultApplicationScopes.
// IMPORTANT: only application-defined API scopes go here. Do NOT add
// "openid", "profile", or "offline_access" — those are identity scopes
// and IdentityServer8 refuses to start when an IdentityResource and an
// ApiScope share the same Name ("Found identity scopes and API scopes
// that use the same names"). 'openid' and 'profile' are seeded as
// IdentityResources via IdentityResources.OpenId().ToEntity() /
// IdentityResources.Profile().ToEntity() further down;
// 'offline_access' is handled by IdentityServer8 itself and never
// needs an explicit ApiScope row.
public static readonly string[] BuildInApiScopes = {
"profile", "openid", "offline_access",
"admin", "moderation", "performer", "client" };
// One ApiResource per application scope. Each scope is exposed by