For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Identity providers
Review how the Solo UI authenticates users with an OpenID Connect identity provider, and how it maps user groups to roles.
About
The Solo UI authenticates every user through an OpenID Connect (OIDC) identity provider (IdP). You have the following provider choices.
| Provider | Use it for | Guide |
|---|---|---|
| Auto identity provider | Development and testing, with a set of hardcoded users. This is the default. | Auto identity provider |
| Your own OIDC provider | Production, single sign-on (SSO), and role-based access control (RBAC) that maps your own user groups to Solo UI roles. | Set up an external OIDC provider |
An external OIDC provider gives you the following capabilities.
- Single sign-on: Users log in to the Solo UI with the credentials that you already manage in your IdP.
- Role-based access control: The Solo UI reads a group claim from the access token and maps those groups to the
global.Admin,global.Writer, andglobal.Readerroles. - Token expiry and refresh: You control how long an access token stays valid, and the UI refreshes it with a refresh token.
How the Solo UI selects the provider
The oidc.issuer Helm value in the management chart selects the provider.
oidc.issuer | Result |
|---|---|
| Empty, which is the default | The management chart deploys the auto identity provider as the idp container in the solo-enterprise-ui pod, and exposes it on port 5556 of the solo-enterprise-ui service. |
| An issuer URL | The chart omits the idp container and port 5556, and the UI redirects users to your IdP instead. |
Because the setting is a single value, you switch from the auto provider to your own IdP by upgrading the management chart, and you switch back by setting oidc.issuer to an empty string again.
Important
You must use an external OIDC issuer to run more than one UI replica. The auto identity provider generates its token-signing key in-process for each pod, so a token that one replica issues fails validation on another. The management chart refuses to render ui.replicaCount greater than 1 while the auto provider is in use, and fails the install or upgrade with the following message: ui.replicaCount > 1 requires an external OIDC issuer: set oidc.issuer. For more information, see High availability and disaster recovery.
Authentication and authorization flow
The following diagram shows how your IdP, the UI frontend, and the UI backend interact when a user logs in and then calls a Solo UI API. Follow the arrows from the User at the top to see which component holds the token at each stage.
sequenceDiagram
participant U as User
participant F as UI frontend
participant I as Your IdP
participant B as UI backend
Note over U,B: Authentication
U->>F: 1. Open the Solo UI
F->>I: 2. Redirect to the IdP login page
U->>I: 3. Enter credentials
I->>F: 4. Return an authorization code
F->>I: 5. Exchange the code for tokens (PKCE)
I->>F: 6. Return an access token and a refresh token
Note over U,B: Authorization
F->>B: 7. Call the API with the access token
B->>B: 8. Validate the token and read the group claim
B->>B: 9. Map groups to roles with the RBAC ConfigMap
B->>F: 10. Return the API response, or deny the request
Note over U,B: Token refresh
F->>I: 11. Exchange the refresh token for a new access token
Read the flow in three stages.
- Authentication, steps 1 to 6. The UI frontend redirects the user to your IdP. Because the frontend is a public client, it uses the Proof Key for Code Exchange (PKCE) flow to exchange the authorization code for tokens, which avoids holding a client secret in the browser.
- Authorization, steps 7 to 10. The UI backend validates the access token and reads the group claim from it. The backend maps those groups to Solo UI roles, then allows or denies the request.
- Token refresh, step 11. When the access token expires, the frontend exchanges the refresh token for a new access token, and the user stays logged in.
Role-based access control
The UI backend maps groups from the access token to Solo UI roles. The management chart writes the mapping to the rbac-config-management ConfigMap in the namespace where you install the chart.
The following snippet shows the default configuration of the ConfigMap.
apiVersion: v1
kind: ConfigMap
metadata:
name: rbac-config-management
namespace: solo-enterprise
data:
config: |
{
"roleMapper": "has(claims.Groups) ? claims.Groups.transformList(i, v, v in rolesMap, rolesMap[v]) : []",
"roleMappings": {"admins":"global.Admin","readers":"global.Reader","writers":"global.Writer"},
"defaultRoles": ["global.Authenticated"]
}Set the following Helm values to change the mapping.
Note
Do not edit the ConfigMap directly. The management chart regenerates the ConfigMap on every upgrade, which overwrites your changes.
| Field | Description |
|---|---|
rbac.roleMapping.roleMapper | A Common Expression Language (CEL) expression that turns claims into roles. The claims variable holds the token claims and the rolesMap variable holds roleMappings. The default expression reads a Groups claim, and returns no mapped roles when the token has no such claim. Claim names are case-sensitive, so an IdP that returns a lowercase groups claim needs its own expression. |
rbac.roleMapping.roleMappings | A map of your IdP group names to Solo UI roles. The three roles are global.Admin for full access, global.Writer for create, read, and update access, and global.Reader for read-only access. When a user’s groups map to more than one role, the highest-privilege role applies, in the order Admin, Writer, Reader. |
rbac.roleMapping.defaultRoles | Roles that every authenticated user gets in addition to the mapped roles. With products.mesh.enabled=true, any authenticated user can view the mesh UI views (Fleet Graph, Global Services, and Dashboard) without a mapped RBAC role. This is controlled by the rbac.roleMapping.defaultRoles Helm value, which defaults to ["global.Authenticated"] when the mesh product is enabled. Reading an individual resource’s YAML from the Fleet Graph still requires the global.Reader role. To require an explicitly mapped role for all access, set rbac.roleMapping.defaultRoles=[]. For all available options, see the Helm values reference. |
For every available value, see the management chart reference.
Authorization modes
The rbac.mode Helm value selects how the UI backend authorizes each management API call. The default value, coarse, checks the global roles that rbac.roleMapping.roleMappings defines. The fine-grained value instead evaluates built-in catalog defaults and EnterpriseAgentgatewayRBACPolicy grants. These grants scope access to individual Solo Enterprise for agentgateway resources, including Budgets, Budget entries, HTTPRoutes, and VirtualKeys.
Fine-grained mode covers Solo Enterprise for agentgateway resources only. Istio mesh views such as the Fleet Graph, Global Services, and Dashboard keep the global role checks in both modes, so a user sees the same mesh resources either way.
When rbac.mode is set to fine-grained, the UI backend builds the policy subject from two verified JWT claims, which you can point at different claim names than the defaults.
| Field | Description |
|---|---|
rbac.subjectMapping.userClaim | Verified JSON Web Token (JWT) claim to use as the subject user. The default value is preferred_username. Changing this value later requires migrating the user values in your policies and owned resources. |
rbac.subjectMapping.groupsClaim | Verified JWT claim to use as the subject groups. The default value is Groups. |
For the policy shape and a worked example, see Fine-grained management RBAC in the Solo Enterprise for kagent documentation.
Client IDs
The Solo UI needs one OIDC client for the UI backend and one for the UI frontend, because the two components have different security requirements. The backend is a confidential client that validates tokens server-side, and the frontend is a public client that runs in the browser.
Note
The Solo UI ships the same management chart for Solo Enterprise for Istio, Solo Enterprise for agentgateway, and Solo Enterprise for kagent. As a result, ui.backend.oidc.clientId defaults to kagent-backend and ui.frontend.oidc.clientId defaults to kagent-ui. Set both values to the client IDs that you create in your IdP, rather than naming your clients to match the defaults.
Next steps
Set up your provider with the external OIDC provider guide. The guide applies to any OIDC-compliant provider.