Skip to main content
Version: 1.0

Set up identity providers and resource servers

Before clients can register or obtain tokens you need to establish the trust infrastructure: identity providers (for user-facing flows) and resource servers (the APIs tokens are issued for).


1.1 Identity providers

An Identity Provider (IdP) is an external OIDC provider that the AS federates with. The AS acts as an OIDC Relying Party to the IdP during the authorization code flow.

Fields:

FieldDescription
idpIdStable admin-assigned key (e.g. corporate-idp). Used in policy as subject.idp.
issuerOIDC issuer URL. Must be unique per tenant.
nameDisplay name
clientIdThe AS's client_id at this IdP
clientSecretThe AS's client_secret at this IdP
scopesScopes to request from this IdP (e.g. ["openid", "profile", "email"])
authorizationEndpointIdP's authorization endpoint
tokenEndpointIdP's token endpoint
userinfoEndpointIdP's userinfo endpoint
jwksUriIdP's JWKS URI (used to verify ID tokens)
tenantIdScope to tenant; null = platform-wide

Register an IdP:

curl -X POST https://pbac.example.com/admin/api/identity-providers \
-H "X-Admin-API-Key: $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"idpId": "corporate-idp",
"issuer": "https://idp.example.com",
"name": "Corporate IdP",
"clientId": "pbac-relying-party",
"clientSecret": "secret",
"scopes": ["openid", "profile", "email"],
"authorizationEndpoint": "https://idp.example.com/oauth2/authorize",
"tokenEndpoint": "https://idp.example.com/oauth2/token",
"userinfoEndpoint": "https://idp.example.com/oauth2/userinfo",
"jwksUri": "https://idp.example.com/.well-known/jwks.json"
}'

List IdPs:

curl https://pbac.example.com/admin/api/identity-providers \
-H "X-Admin-API-Key: $ADMIN_KEY"

Update or delete:

# Update
curl -X PUT https://pbac.example.com/admin/api/identity-providers/corporate-idp \
-H "X-Admin-API-Key: $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{ "issuer": "https://idp.example.com", "name": "Updated Name", "enabled": true }'

# Delete
curl -X DELETE https://pbac.example.com/admin/api/identity-providers/corporate-idp \
-H "X-Admin-API-Key: $ADMIN_KEY"

1.2 IdP selection policy

The AS uses OPA policy data to route authorize requests to the right IdP. Configure in the user.idp_selection block of your policy data (see Policy Data Guide for how to update policy data):

{
"oauth": {
"user": {
"idp_selection": {
"default_idp": "corporate-idp",
"resource_to_idp": {
"https://api.example.com/fhir": "health-idp"
},
"resource_type_to_idp": {
"urn:example:SensitiveRecord": "mfa-idp"
},
"acr_to_idp": {
"urn:acr:mfa": "mfa-idp"
}
}
}
}
}

Priority: acr_to_idp > resource_to_idp > resource_type_to_idp > default_idp


1.3 Resource servers

A resource server (RS) is an API that accepts tokens issued by this AS. It is identified by a resource indicator — a URI used in RFC 8707 resource parameters.

The AS uses the resource server DB records at token time to resolve resourceresource_type (longest-prefix match). If there is no matching RS record, a token request with that resource will fail with invalid_target unless the caller supplies a resource_type hint.

Resource servers are auto-created by DCR when the OPA register policy returns is_resource_server: true with granted_resource_indicators. Use the Admin API to pre-create, inspect, or manage them independently:

curl -X POST https://pbac.example.com/admin/api/resource-servers \
-H "X-Admin-API-Key: $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"resourceIndicator": "https://api.example.com/fhir",
"name": "FHIR API",
"description": "Clinical data API",
"enabled": true
}'

The response includes the numeric id needed to associate resource types and resource instances.

Wildcard indicators

Use https://api.example.com/fhir/* to match any sub-path. The AS uses longest-prefix matching, so more specific indicators win over wildcards.

Associate resource types with an RS is handled automatically during DCR or via the resource type admin API. An RS can serve multiple resource types.


Resource types

Resource types classify the data that RSes host. Each type carries a set of valid scopes.

Create a resource type:

curl -X POST https://pbac.example.com/admin/api/resource-types \
-H "X-Admin-API-Key: $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"typeUri": "urn:example:Patient",
"name": "Patient Record",
"description": "Clinical patient record",
"scopes": ["read", "write", "delete"],
"enabled": true
}'
FieldDescription
typeUriUnique URI identifying the type (e.g. urn:example:Patient)
nameDisplay name
scopesScopes valid for this type
parentTypeIdOptional parent type for subtyping hierarchies

AS-hosted resource types (built-in; no need to create):

Type URIValid ScopesGrants access to
urn:as:userinfoopenid, profile, email/userinfo endpoint
urn:as:introspectuma_protection, introspection/introspect endpoint
urn:as:authzenauthzen/access/v1/evaluation endpoint

Resource instances

A resource is a specific instance hosted by an RS with a given type.

curl -X POST https://pbac.example.com/admin/api/resources \
-H "X-Admin-API-Key: $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"resourceServerId": 1,
"resourceTypeId": 2,
"resourceIdentifier": "patient/123",
"scopes": ["read", "write"]
}'
FieldDescription
resourceServerIdFK to resource_server
resourceTypeIdFK to resource_type
resourceIdentifierRS-local identifier (e.g. patient/123)
ownerSubjectIdOptional: FK to subject if user-owned
scopesAllowed scopes on this instance (subset of type scopes)

Subjects

Subjects are the user/human principals that appear in user-delegated tokens. They are created automatically on first authorization code flow, but can be pre-registered:

curl -X POST https://pbac.example.com/admin/api/subjects \
-H "X-Admin-API-Key: $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"subjectId": "alice@example.com",
"identityProviderId": 1
}'

Next steps

  • Policy Data — Configure denylists, entitlements, IdP selection, and trust issuers
  • Registering Software — Register clients via DCR with software statements
  • Getting Tokens — Request access tokens using all supported grant types