Synadia Platform
Managing OIDC Providers
Servers older than version 1.6.0 do not support OIDC management via the UI or API.
Control Plane allows operators to set up OpenID Connect (OIDC) for authentication. Creating and updating providers can be done via both the user interface and the API.
Only Control Plane administrators can configure OIDC providers.
Configuration file
Since version 1.6.0 Control Plane supports managing OIDC providers from the configuration file in a limited capacity. The user interface or API should be used going forward.
The Authentication.Methods.OIDC block in the configuration file is now only used to seed initial OIDC provider data into the database. During server start-up the configuration file is read and new providers are loaded into the database.
All changes to providers after initial seed must be done via the UI or API.
Database
OIDC provider information is now stored in the database. This means that provider changes are instantly updated on change without requiring a server restart.
User interface
For Control Plane administrators the OIDC providers page is accessible through the /teams page. This can be accessed by clicking on the cog icon in the top right of the Control Plane navigation bar.
Overview
The overview panel shows all available OIDC providers as a list.

Adding a provider
To add a new provider, navigate to the OIDC overview page. Then follow these steps:
- Click the Add Provider button
- Fill out the provider details provided from your provider documentation
- Click the Save button
Updating a provider
To update an existing provider, navigate to the OIDC overview page. Then follow these steps:
- Click on the provider Name in the left hand column of the providers table
- The provider detail page should now be loaded into view
- Click on the pencil icon in the top right of the provider card component
- A side draw will open, pre-populating existing data. Amend any fields as required
- Click the Save button to persist the changes
Deleting a provider
To delete a provider, navigate to the OIDC overview page. Then follow these steps:
- Click on the provider Name in the left hand column of the providers table
- The provider detail page should now be loaded into view
- Navigate to the bottom of the page
- Inside the Danger Zone red box, click on Delete Provider
- A confirmation alert will appear, clicking Delete will remove the provider permanently
OIDC Group Mapping
Control Plane now supports mapping internal roles to OIDC claims from your Identity Provider (IDP).
More information about how this works can be found in the architecture page.
Setup
Control Plane reads the claims from the OIDC token presented during login and extracts the role or group from it. That group can then be used to programmatically link to Control Plane roles.
To enable this the following must occur:
- Your IDP must expose a custom claim
- Each IDP does this slightly differently but the claim must be exposed during the login event
- The role or group must be available as field on the token provided by the IDP to Control Plane
- Control Plane must be aware of the claim using our Jsonnet mapper
Once the claim has been added via the IDP a mapping can be constructed which links any user with that claim in their id_token to Control Plane roles.
Step 1: Configure your IDP to expose a claim
Your IDP can use any claim name (e.g., groups, roles, memberOf, or a custom name). The claim must be included in the id_token returned during the OIDC login flow.
Each IDP handles this differently:
| IDP | Typical Claim Name | Notes |
|---|---|---|
| Microsoft Entra | groups | Configure in App Registration → Token Configuration |
| Okta | groups | Add groups claim in Authorization Server settings |
| Auth0 | Custom namespace (e.g., https://myapp/roles) | Use Actions or Rules to add custom claims |
| Keycloak | roles or groups | Configure in Client Scopes → Mappers |
Step 2: Write a Jsonnet mapper
The Jsonnet mapper transforms your IDP's claim into a groups trait that Control Plane reads internally.
The output trait must be called groups. This is required by Control Plane. The input claim from your IDP can be named anything - the mapper handles the translation.
Add the following to your OIDC provider's mapper_schema field, replacing YOUR_IDP_CLAIM_NAME with your IDP's actual claim name:
local claims = std.extVar('claims');
{
identity: {
traits: {
username: claims.preferred_username,
name: claims.name,
[if 'YOUR_IDP_CLAIM_NAME' in claims.raw_claims then 'groups' else null]: claims.raw_claims.YOUR_IDP_CLAIM_NAME,
},
},
}
For example, if your IDP uses a claim called roles:
local claims = std.extVar('claims');
{
identity: {
traits: {
username: claims.preferred_username,
name: claims.name,
[if 'roles' in claims.raw_claims then 'groups' else null]: claims.raw_claims.roles,
},
},
}
When configuring via the API or configuration file, the Jsonnet mapper must be base64 encoded before saving.
# Encode your mapper
cat mapper.jsonnet | base64
And supplied as base64://ENCODED_STRING
Custom claims like groups require claims.raw_claims.X because they are not part of the standard OIDC specification. Standard claims (email, name, preferred_username) are available directly on the claims object.
Control Plane mapping
Once the claim has been added we can configure the Control Plane OIDC group mappings.
Group role mappings are configured as a property of the OIDC provider itself. Both the UI and API can be used to manage mappings.
Only administrators have the authority to do the following.
User Interface
The easiest way to get started is via the User Interface.
Accessing Group Mappings
This assumes an OIDC provider has already been created
- Click on the cog icon in the top right
- Click on OIDC Providers tab
- Select your OIDC provider from the list
- Scroll to the Group Mappings section at the bottom
- Click Manage Group Mappings

Group Mappings Overview
The Group Mappings page displays all configured mappings for this provider.

From this page you can:
- Add Group Mapping: Click the button to create a new mapping
- Search: Filter mappings by Group ID
- View details: Click on a row to see and edit the mapping
You can have multiple group mappings and users can be members of more than one at a time. The highest privilege will be granted to the user from their assignments.
Configuring a Group Mapping
The detail page shows the full configuration for a group mapping.

Group Information
- Group ID: The identifier from your IDP (must match the claim value in the token)
- App Role: Optional app-level role (User or Admin)
Only resources available to your team, system or account will be presented in the dropdowns. Once assigned they will not show up in the dropdowns - to edit, click on the three dots and select Edit.
Assigned Teams
Add teams and select roles (Admin, Maintainer, Observer, Limited). Users with this group claim will be granted the specified role on the team.
Assigned Systems
Add systems within assigned teams and select roles (Admin, Maintainer, Observer). The system must belong to a team that is already assigned above.
Assigned Accounts
Add accounts within assigned systems and select roles (Admin, Observer). The account must belong to a system that is already assigned above.
Removing resources from the mappings will automatically revoke access on the next login. Deleting an entire group will cascade and revoke access to all resources under that group.
API
Group role mappings use the existing OIDC provider endpoints. The group_role_mappings field is included in the provider request and response payloads.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /api/core/beta/oidc-providers | Create provider with mappings |
PATCH | /api/core/beta/oidc-providers/{oidcProviderId} | Update mappings on existing provider |
GET | /api/core/beta/oidc-providers/{oidcProviderId} | Retrieve provider with mappings |
Partial updates
The API uses PATCH semantics. You can update just group_role_mappings without providing other provider fields (client_id, issuer_url, etc.). Omitted fields remain unchanged.
curl -X PATCH /api/core/beta/oidc-providers/{id} \
-H "Content-Type: application/json" \
-d '{
"group_role_mappings": {
"my-group-id": {
"team_assignments": [...]
}
}
}'
Payload structure
The group_role_mappings field is a map where keys are the group IDs from your IDP (e.g., Entra Object ID, Okta group ID).
{
"group_role_mappings": {
"oidc-group-id-from-idp": {
"app_role": "User",
"team_assignments": [
{
"team_id": "2xGkABC123teamID",
"role": "Member",
"system_assignments": [
{
"system_id": "2xGkDEF456systemID",
"role": "Operator",
"account_assignments": [
{
"account_id": "2xGkGHI789accountID",
"role": "Operator"
}
]
}
]
}
]
}
}
}
Field reference
| Field | Description | Required |
|---|---|---|
| Map key | Group ID from your IDP | Yes |
app_role | App-level role: User, Admin, Support | No |
team_id | ID of the team in Control Plane | Yes (if assigning team) |
role (team) | Team role: Admin, Member, Viewer | Yes |
system_id | ID of a system within the team | Yes (if assigning system) |
role (system) | System role: Admin, Operator, Viewer | Yes |
account_id | ID of an account within the system | Yes (if assigning account) |
role (account) | Account role: Admin, Operator, Viewer | Yes |
The hierarchy is strict: systems must belong to the specified team, and accounts must belong to the specified system. Validation enforces this relationship.
Example: Multiple groups
{
"group_role_mappings": {
"engineering-admins": {
"app_role": "User",
"team_assignments": [
{
"team_id": "2xGkABC123teamID",
"role": "Admin"
}
]
},
"engineering-developers": {
"team_assignments": [
{
"team_id": "2xGkABC123teamID",
"role": "Member",
"system_assignments": [
{
"system_id": "2xGkDEF456systemID",
"role": "Operator"
}
]
}
]
},
"observers": {
"team_assignments": [
{
"team_id": "2xGkABC123teamID",
"role": "Viewer"
}
]
}
}
}
Removing a mapping
To remove a group mapping, set its value to null (RFC 7396 JSON Merge Patch):
curl -X PATCH /api/core/beta/oidc-providers/{id} \
-H "Content-Type: application/json" \
-d '{
"group_role_mappings": {
"group-to-remove": null
}
}'
Response format
GET responses include human-readable names for teams, systems, and accounts:
{
"group_role_mappings": {
"engineering-admins": {
"team_assignments": [
{
"team_id": "2xGkABC123teamID",
"team_name": "Engineering",
"role": "Admin",
"system_assignments": [
{
"system_id": "2xGkDEF456systemID",
"system_name": "Production",
"role": "Operator"
}
]
}
]
}
}
}