# Connect Okta

Canonical URL: https://docs.fuse.init.inc/integrations/okta/setup

Create an Okta OAuth service app with private-key JWT auth and submit client credentials to Init.



## Before you start [#before-you-start]

Okta uses **customer client credentials** (`oauth2_client_credentials` + `customer_credentials`). There is no Init platform OAuth app for this provider.

**Connection admin/user** creates an Okta API service app, grants Management API scopes, and submits the org domain, client ID, and complete RSA private JWK through Init Connect. **Engine operator** does not store a shared Okta client secret.

You need:

* An Okta org Super Admin (or equivalent) who can create API service apps and assign admin roles/scopes.
* The org hostname only (for example `example.okta.com`), not the `-admin` console host and not a custom domain.
* Access to Init Connect for the tenant that will own the connection.

## Configure the provider [#configure-the-provider]

### Create an Okta API service app (**Connection admin/user**) [#create-an-okta-api-service-app-connection-adminuser]

1. In the Okta Admin Console, create an **API Services** OAuth app (service app) for machine-to-machine access.
2. Configure client authentication as **public key / private key** (`private_key_jwt`). Client secret auth is not accepted for Okta Management API scopes.
3. Generate an RSA key pair. Register the **public** JWK on the service app. Keep the **complete private** JWK offline in a secret manager.
4. Grant only the Okta API scopes required for the Init actions you will run (for example `okta.users.read`, `okta.groups.read`, `okta.apps.read`, plus manage variants when writes are required). Prefer least privilege.
5. Assign any Okta admin roles the service app needs so those scopes can actually call Management API endpoints.
6. Copy the Client ID (20 alphanumeric characters). Note the org domain hostname without scheme or path.

There is no one-time Init platform Okta app registration.

## Connect to Init [#connect-to-init]

**Connection admin/user** starts an Okta Connect session and submits only these contract fields:

| Field             | Required | Notes                                                                                                                                                 |
| ----------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `org_domain`      | Yes      | Hostname only under a reviewed Okta suffix (`okta.com`, `oktapreview.com`, `okta-emea.com`, `okta-gov.com`). No scheme, path, port, or `-admin` host. |
| `client_id`       | Yes      | Service app client ID (20 alphanumeric characters).                                                                                                   |
| `private_key_jwk` | Yes      | Complete RSA private JWK used to sign client assertions.                                                                                              |

The private JWK must be a strict RSA signing key with all of these members: `kty` (`RSA`), `kid`, `alg` (`RS256`), `use` (`sig`), `n`, `e`, `d`, `p`, `q`, `dp`, `dq`, and `qi`. Do not paste a real JWK into tickets or docs. Never embed JWT client assertions in documentation.

## Permissions [#permissions]

Service-app grants control which Okta Management API scopes Init can mint. Match grants to the generated action scope matrix; do not enable unused admin scopes.

Okta also requires appropriate admin roles on the service app so granted scopes succeed at runtime. Scope grants without roles still fail with authorization errors.

## Verify the connection [#verify-the-connection]

1. Complete Connect and confirm the connection is active.
2. Run Init’s connection test or a safe read such as listing users or groups the service app can access.
3. Success looks like Okta returning Management API data without `401` invalid-client or scope errors.

## Rotate or revoke access [#rotate-or-revoke-access]

1. Generate a new RSA key pair. Register the new public JWK on the Okta service app.
2. Reconnect in Init with the same `org_domain` / `client_id` and the new complete private JWK.
3. Remove the old public key from the Okta app after cutover.
4. To revoke access entirely, deactivate or delete the service app in Okta and delete the Init connection.

If a private JWK is exposed, rotate keys immediately in Okta, then reconnect.

## Troubleshooting [#troubleshooting]

| Symptom                             | What to check                                                                                                                      |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Connect rejects `org_domain`        | Use hostname only; no `https://`, path, port, IP, custom domain, or `-admin` host.                                                 |
| Connect rejects `client_id`         | Must be exactly 20 alphanumeric characters from the service app.                                                                   |
| Connect rejects `private_key_jwk`   | JWK must include every required RSA private member (`d`, `p`, `q`, `dp`, `dq`, `qi`, etc.) with `kty=RSA`, `alg=RS256`, `use=sig`. |
| `invalid_client` / assertion errors | Public key registered in Okta must match the private JWK; `kid` must align.                                                        |
| `403` / insufficient permissions    | Missing Okta API scope grants or admin roles on the service app; update grants and reconnect.                                      |

