Okta Agent OIDC / MCP Access Setup
Automates the Okta objects Cross-App Access agent setup needs: the login app (delegation caller), the AI Agent's credential and delegation link, and a Dynamic Client Registration (DCR) client for each governed MCP server. A few objects have no Okta API and stay Console-only — this page covers exactly which.
This feature is in Preview. The shipping identity model — one Okta AI Agent identity shared by every governed agent behind this deployment, or one per named agent — may still change as usage grows.
Prerequisites
- Your Okta org already connected under Integrations → Okta (Discovery) (read-only sync of apps/groups). Agent OIDC / MCP Access Setup reuses that connection's org URL.
- A separate Okta API token for this feature. Okta tokens carry whatever permissions the admin who created them holds — use a token from an account with rights to create apps, assign users, and manage AI Agent objects.
- At least one MCP server already registered in AIControls (MCP Servers page) — per-server provisioning looks up a real server row and fails otherwise.
Enable write access
- Go to Integrations → Okta (Discovery), open either the Agents or MCP tab, and expand Advanced / manual setup.
- Paste your write-scoped Okta API token and click Enable write access.
Once write access is enabled, the Agents tab lists every AI Agent Okta already has — not just ones AIControls created — and lets you register a new one or onboard an existing one with a guided wizard. See Register or onboard an agent below; the rest of this page (Shared identity / Per-agent identities, the manual Console steps) is the advanced/manual path underneath that wizard, still there for Shared-mode deployments and troubleshooting.
Register or onboard an agent (guided)
The Agents tab is the primary way to bring an agent under governance — it always uses per-agent identities (below), never Shared mode.
- Click Register a new agent to create a brand-new Okta AI Agent identity from scratch, or click Onboard as governed agent → on a row that Okta already has but AIControls doesn't govern yet. Both open the same wizard — onboarding just pre-fills the identity step with the existing agent instead of asking for a name.
- Identity — name/description (new agents) or a read-only confirmation of what Okta already has (existing agents), plus which users this agent's login app should be assigned to.
- Credential — choose who holds the signing key. AIControls manages this credential (recommended): the keypair is generated and the private key is encrypted and stored by AIControls — nothing to copy out. Bring your own key: generated the same way, but shown once and never persisted, same as this page's existing Shared/Per-agent flows below.
- Connect MCP servers — optionally pick which MCP servers this agent should reach now; you can add more later from the Agents tab.
- Review & create — confirms exactly what will be created vs. reused (a new identity, or none at all for onboarding) before calling Okta.
As of this writing, "AIControls manages this credential" is storage only — the encrypted key isn't yet used to sign anything at runtime. It exists so a future automatic-signing feature has somewhere to read from. Choose "Bring your own key" if you need this agent to actually authenticate outbound today.
Choosing a mode (advanced)
| Shared identity | Per-agent identities | |
|---|---|---|
| Okta AI Agent identities created | One, for the whole deployment | One per named agent you register |
| Revoking one agent's access | Not possible without affecting every governed agent | Independent — revoke or re-provision one agent without touching the others |
| Setup effort | Lower — one identity to provision | Higher — provision each agent separately |
Shared identity is the default and the simpler starting point. Move to per-agent identities once you have distinct automated agents (a Kubernetes remediation bot, a nightly cost-report job, a CI deploy agent) that should be independently auditable and revocable in Okta.
Shared identity mode
- In Okta, go to Directory → AI Agents → Create AI Agent and create an empty AI Agent object. Copy its id.
- Back in AIControls' Agent Identity card, paste the AI Agent id and the email addresses of the users who should be able to sign in through it, then click Provision agent identity.
- Save the private key shown in the dialog — it is generated on this call and never stored. If you lose it, re-provisioning issues a new one and invalidates the old.
- Under Per-Server DCR Clients, click Provision Agent OIDC next to each MCP server you want this agent to reach. Save that server's private key the same way.
Per-agent identities mode
- In AIControls' Agent Identities card, click + Add governed agent and give it a short slug (lowercase letters, numbers, hyphens — e.g.
k8s-remediator) and a display name. - Click Provision identity on that agent's row and add the assigned user emails. Leave the Okta AI Agent id field blank to have AIControls create and activate a new AI Agent object for you automatically — only set it if you want to reuse an existing one. Save the private key shown.
- Select the agent under Per-Server Access and provision a DCR client for each MCP server it needs, giving AIControls a label for the Resource app to reuse or create (e.g.
aicontrols-github-mcp) — this also wires the Resource connection automatically. Reuse the same label across every agent/server pair that should share one Resource app. Each agent's per-server clients are independent — provisioning one agent never touches another's. - To decommission an agent, click Remove on its row. This deletes its per-server DCR clients in AIControls; the Okta-side objects (its login app, credential, delegation link) are left as-is — remove those from the Okta Console.
Once provisioned, each governed agent shows up as its own identity on the Identities page and in the Audit Log, labeled by its display name rather than the delegating human's email — see Governed agents sharing a delegator.
Finish in the Okta Console
Shared identity mode still has three objects with no Okta API, created by hand once per deployment:
- The AI Agent object itself (Directory → AI Agents → Create AI Agent) — its id is what you paste into AIControls above.
- A Resource app with Cross-App Access enabled: Applications → Create App Integration → OIDC → Web Application — not "Resource Servers"/"MCP Servers", which require client-secret authentication AIControls doesn't use here. On the app's Cross-App Access tab, paste the Issuer URL from a server's provisioning result.
- On the AI Agent object: add a Resource connection to that app (Client ID at resource = the Client ID from the provisioning result), then Activate the agent.
Per-agent identities mode automates the AI Agent object (creation + activation) and the Resource connection — only one step remains, once per Resource app (not once per agent):
- A Resource app with Cross-App Access enabled: Applications → Create App Integration → OIDC → Web Application — or reuse the app the Per-Server card's automation just found or created for the label you gave it. On the app's Cross-App Access tab, paste the Issuer URL from a server's provisioning result.
Re-running per-server provisioning for the same agent and server replaces the DCR client with a fresh keypair. In Shared identity mode, update the Resource app's Client ID at resource afterward, since the old one no longer has a matching private key — Per-agent mode's automation re-wires the Resource connection for you on every run.
Access token lifetime
Every Cross-App Access token AIControls mints for a governed agent's jwt-bearer grant expires after a fixed lifetime — 1 hour by default. There is no refresh token in this flow by design: a client re-presents its ID-JAG assertion (or fetches a fresh one from the IdP) to mint a new access token once the old one expires, rather than silently extending a long-lived session.
To change the lifetime:
- Go to Settings → Identity & Access → SSO and open the XAA tab.
- Set Access Token Lifetime, in seconds (allowed range: 5 minutes to 24 hours).
- Click Save. The new lifetime applies immediately, to every access token minted from that point on — no restart required, and tokens already issued keep whatever lifetime they were minted with.
A shorter lifetime bounds how long a compromised or leaked access token stays usable, at the cost of more frequent ID-JAG re-presentation; a longer lifetime reduces that overhead. Choose based on how sensitive the governed agents reaching this deployment are.
MCP server discovery
The MCP tab lists MCP servers registered in Okta's own native MCP Server Registry, separate from the app-based Resource app model this page otherwise uses. That registry is a very new Okta capability and is empty on most orgs — this is expected, not an error. Below it, AIControls lists its own governed MCP servers that already have some tie to Okta (a promoted discovered app, or an existing Cross-App Access config), as candidates worth registering natively later; that push isn't automated yet. Click Register manually to give a new MCP server a resource identity — reusing an already-discovered Okta app, or creating a new one — before finishing its setup on the MCP Servers page.
Troubleshooting
"Connect the read-only Okta Discovery integration first"
Agent OIDC / MCP Access Setup reuses the org URL from Integrations → Okta (Discovery). Connect that read-only integration before enabling write access here.
"Unknown MCP server"
Per-server provisioning requires the server to already exist on the MCP Servers page. A server declared only in a self-hosted deployment's Helm values and never added through the UI won't have a row to provision against — add it first.
Provisioning is already in progress
Two requests for the same agent or server can't provision at once — retry once the first completes. If a request genuinely crashed mid-flight, the lock clears itself automatically after a few minutes.