OAuth APIs (Resource Servers)
An OAuth API in Modgud is the registration of a resource server — an API that wants to validate access tokens issued by Modgud and use them to authorise requests.
OAuth API vs OAuth Client
- OAuth Client = the app that performs the user login and gets tokens
- OAuth API = the API that validates tokens and authorises requests against them
An app can be both (e.g. a BFF pattern: user-login as a client, its own API as an API).

When do I need an OAuth API registration?
For most cases — a SaaS app that validates Modgud tokens — yes, you register an OAuth API for it. The registration is what lets Modgud emit a tailored resource_access block for this RS on /connect/userinfo. Specifically, it's required when:
- You want per-Audience permission narrowing in
resource_accessblocks. The RS declares itsPermissionIdssubset of the App's catalog, and the IdP narrows each user's emission to that subset. - The API wants to authenticate against the OAuth server itself (e.g. for token introspection)
- You want multi-secret support (several parallel valid secrets, e.g. for seamless rotation)
- The API needs explicit scope lists for discovery
Relationship to Applications
Every OAuth API belongs to exactly one Application. A microservice architecture under one app — e.g. acme-api, acme-search, acme-files all linked to the App acme — works because permissions stay app-centric: each microservice gets its own PermissionIds subset of the same App catalog, and the IdP narrows its resource_access[acme] emission accordingly.
Creating an API
Administration → OAuth → APIs → Create.
Required fields
- Name — technical identifier (e.g.
acme-api). Used inaudclaims when the token is issued. - Display Name — UI label
- Application — which App does this RS belong to? Required for per-Audience subset narrowing.
- Description — optional
PermissionIds
The subset of the linked App's catalog this RS gates on. Used by the IdP to narrow the resource_access block in UserInfo for this audience — sibling RSs under the same App don't see each other's permissions in the user's claims.
Default at creation: full catalog. Tighten to a strict subset for microservices that only need a slice.
Scopes
A list of scope names this API understands. Any token whose scope claim contains one of these is considered "for this API". Used for OIDC discovery and resource indication.
One-click implicit scope
In the API detail modal there is a Create implicit scope button when the API has no scope with the same name yet. Clicking it creates a real OAuthScope row with:
Name= API nameResources=[<api-name>](so the audience matches the API)Enabled = true,ShowInDiscoveryDocument = false(private by default, see below)- Linked to the same App as the API
This is the fast path for the common 1:1 case: an API and a scope that always go together. After creation the button disappears (re-check via API list reload). The implicit scope is otherwise a normal scope row — editable, deletable, can be requested by clients via scope=<api-name>.
When to keep things separate
Two situations warrant a manually-created additional scope on top of the implicit one:
- Granularity —
<api>.read/.write/.adminagainst the same audience. Differentiates capabilities viascp, notaud. - Multi-RS scope — one scope name pointing to multiple APIs (
scope=admin→aud: [policy-api, audit-api]). Edge case but valid.
User claims
Optional list of claim types this API expects in tokens. Used by some IdP-side filtering mechanisms; for most setups, leave empty.
How a resource server authenticates against Modgud
An OAuth API has no credential surface of its own. When the resource server needs to call Modgud directly (e.g. token introspection), it does so via OAuth using a confidential OAuth Client linked to a Service Account: the client requests an access token via Client-Credentials and uses it as a bearer like any other token. There is no per-API shared secret to rotate.
Editing
Most fields can be edited live; Name is immutable after creation. Changing the linked Application is allowed but be careful — the RS's scope-resolution and the per-Audience resource_access shape immediately switch to the new app context.
Deleting
List → right-click → Delete. Soft-deleted; the OAuth API is no longer usable but the aggregate stream is retained for audit.
Common patterns
One app, one resource server
Default for most SaaS apps: create one OAuth API named after the app's slug, link it to the App, and pick the catalog subset it gates on.
One app, multiple resource servers (microservices)
Each microservice gets its own OAuth API entry with its own narrower PermissionIds subset of the App's catalog. All link to the same App. Per-Audience narrowing in UserInfo means a token used against microservice A only carries A's permission subset, not B's — even when both are under the same App.
Multi-tenant API
If the same API logic serves multiple realms, each realm gets its own OAuth API entry. Modgud's tenancy already enforces realm separation at the database level, so cross-realm token leakage is impossible.
Tips
Audit trail
RS-Auth-protected endpoint calls log the calling RS's name. Useful when several microservices share one App and you want to know which specific RS made a given request.
Two distinct identities
A user bearer token identifies the user; the RS-as-OAuth-client identity (a Client-Credentials access token minted via a Service Account) identifies the RS itself. They sit on independent authentication axes — both can be relevant on the same request.