/ Docs

Okta (Okta Identity Engine)

Last updated June 10, 2026 · View as Markdown

Okta_Logo_BrightBlue_Medium.png Okta is a platform-as-a-service used for identity management (IDaaS). It is a customizable, secure, drop-in solution to add authentication and authorization services to your applications, providing scalable authentication built right into your application without the development overhead, security risks, and maintenance.

The Relyance Okta integration helps with a) understanding personal data types stored in Okta and b) providing visibility into third-party vendors configured in Okta. This guide is for customers using the newer Okta Identity Engine (OIE) platform. If you're unsure whether you're using Okta Classic or Okta OIE, see this support article from Okta.

Choose an authentication method

Relyance supports two ways to connect to Okta. Both run the same scans and read the same data - they differ only in how the connection authenticates.

  • Machine to Machine (Recommended) - Uses cryptographic key signing instead of a client secret. No interactive browser sign-in at connection time and no refresh token to expire. Relyance generates and manages the key for you; you only paste a JWKS URL into Okta. Start with this method.
  • OAuth2 (OIDC Web App)- The original interactive flow. Requires a Super Admin to click Authorize in a browser and relies on a refresh token. Use this only if you cannot create an API Services app. See Part 2.

Configure a service app in Okta so Relyance can connect without an interactive browser sign-in at connection time. Setup takes about 5–10 minutes and only needs to be done once.

ℹ️ Why Machine to Machine?

The standard OAuth2 flow requires a Super Admin to click

Authorize interactively in a browser. Machine to Machine uses cryptographic key signing instead - no browser step, no refresh token to expire. Relyance generates and manages the key for you; you only need to paste a JWKS URL into Okta. Okta also requires the service app to have both OAuth scopes and an admin role before it can call Okta Management APIs.

🔑 Which admin role do you need?

The integration runs Vendor Discovery by default. Vendor Discovery calls Okta's API Service Integrations endpoint (/integrations/api/v1/api-services), which Okta authorizes only for the Super Administrator role - no narrower or custom role can cover it. So the service app you create must be assigned Super Administrator. This is the standard setup.

🔒 The Super Administrator role grants Relyance no write access - Okta's authorization model prevents it.

  • Two independent checks. Okta authorizes every Management API call against both the access token's scopes and the app's admin role. A call succeeds only if both permit it. Relyance's token carries read scopes only, so Okta refuses every create, update, or delete with insufficient_scope - the role cannot override a scope the token doesn't have.
  • Capability comes from scopes, not the role. The role decides which resources are in reach; the granted scopes decide which operations are allowed. With read-only scopes, the allowed operations are read-only - on every resource, Super Administrator or not.
  • You control the scopes. The app holds exactly the scopes you grant on the Okta API Scopes tab. For discovery that is okta.*.read only, and Okta issues a token containing only those.
  • The app cannot expand its own access. Granting a scope is a Super Administrator action in the Okta console; doing it via the API requires a management scope the read-only app does not hold. There is no path for the app to escalate itself.
  • Why you may see okta.users.manage in the token request: the connector lists it on every request so a single app can also serve DSR, but Okta issues only the scopes you have granted and silently omits the rest (per Okta's documented downscoping behavior). Grant okta.users.manage only when you enable DSR; otherwise it is never issued and the app stays strictly read-only.
  • Fully auditable. Every call the app makes appears in your System Log, and you can revoke the app or any scope at any time.

⚠️ Exception - DSR / right-to-erasure.

The read-only guarantee above holds only while you have not granted a write scope. If you separately enable DSR, you grant okta.users.manage

, which lets the app deprovision and delete Okta users (DSR issues

DELETE /api/v1/users/{id}

) - this is intentional and required for erasure. Combined with Super Administrator, that delete capability spans every user in the org. So grant okta.users.manage only if you actually run DSR, and treat the DSR trust decision separately from Vendor Discovery. Discovery-only connections should never have this scope granted.

Not running Vendor Discovery? Then the app only needs Read-Only Administrator. Everything else in this guide is the same.

Before you start

  1. An Okta account with Super Administrator access. An Application Administrator may be able to create the API Services app, but Super Administrator access is needed to grant Okta API scopes and assign an admin role to the app.
  2. Access to the Relyance configuration portal for your organization ( Settings → Integrations → Okta ).

Step 1 - Create an API Services app in Okta

Okta Admin Console → Applications

  1. In the Okta Admin Console, navigate to Applications › Applications and click Create App Integration.
  2. Select API Services and click Next.
  3. Name the app - e.g. Relyance Integration- and click Save.
  4. On the app's General tab, scroll to Client Credentials and change Client authentication to Public key / Private key.
  5. Under PUBLIC KEYS, select Use a URL to fetch public keys / JWKS URL. Leave the URL field blank for now - you'll fill it in after Step 4.
  6. Click Save. Then copy the Client ID shown at the top of the General tab - you'll need it in Step 4.

Step 2 - Grant OAuth scopes to the app

Okta Admin Console → your app → Okta API Scopes

Navigate to the Okta API Scopes tab on the app and click Grant for each scope below.

Scope Purpose Required for
okta.users.read Read user profiles All
okta.groups.read Read group memberships All
okta.logs.read Read system logs All
okta.apps.read Read application catalog All
okta.idps.read Read identity providers All
okta.authenticators.read Read authenticator configs All
okta.oauthIntegrations.read Read OAuth app integrations All
okta.orgs.read Read org settings All
okta.users.manage Fulfill data subject requests (DSAR / right to erasure). Requires user-management authority in the app's admin role. DSR only

✅ Scopes are necessary but not sufficient.

Okta also checks the service app's admin role and resource permissions on each Management API call. Complete the next step before testing the connection.

Step 3 - Assign an admin role to the app

Okta Admin Console → your app → Admin roles

Grant the service app an admin role so Okta authorizes the resources Relyance reads. OAuth scopes let the app request API access; the admin role determines which resources it can reach. Assign Super Administrator - the integration's default Vendor Discovery requires it, and it stays read-only because the app holds only read scopes (see "Which admin role do you need?" above).

  1. In Okta, open the app you created for Relyance.
  2. Go to the Admin roles tab and click Edit assignments or Add assignment.
  3. Assign Super Administrator and save.
Role When to use Notes
Super Administrator Default - required for Vendor Discovery The standard role for this integration, and the only one that authorizes the API Service Integrations endpoint. It grants no write access on its own - the app can only do what its granted scopes allow, which for discovery are read-only. Verify granted scopes on the Okta API Scopes tab.
Read-Only Administrator Only if Vendor Discovery is disabled Covers users, groups, system logs, applications, identity providers, authenticators, and org settings. Does not cover Vendor Discovery - the API Service Integrations endpoint returns 403 / E0000006 under this role.
+ User-management Add on only for DSR / right-to-erasure DSR also needs user-management authority for the affected users, plus the okta.users.manage OAuth scope. Not needed for discovery.

⚠️ If this step is skipped, the access token may still contain scopes like okta.logs.read or okta.groups.read

, but Okta can return

E0000006

/

You do not have permission to perform the requested action

.

✅ After saving role assignments, retry

Test Connection

. You do not need to rotate keys or recreate the app; Relyance can request a fresh access token on the next test if needed.

Step 4 - Configure the connection in Relyance

Settings → Integrations → Okta → Machine to Machine

  1. In Relyance, go to Settings › Integrations › Okta and click Add connection.
  2. Select Machine to Machine (marked Recommended ) as the authentication method.
  3. Fill in the two fields:
    • Client ID - from the app's General tab in Okta (Step 1).
    • Subdomain - your Okta subdomain, i.e. the prefix before .okta.com (e.g. acme for acme.okta.com ).

✅ Click Save.

Relyance will generate a cryptographic key pair on its end. The first save attempt may fail authentication - that's expected, because Okta has not been given the JWKS URL yet. The connection page will now show a Public Key URL panel, which you'll use in the next step.

Step 5 - Paste the Public Key URL into Okta

Back to Okta Admin Console → your app → General

  1. In Relyance, copy the URL from the Public Key URL panel on the connection page. It will look like: https://api.relyance.ai/v1/integrations/okta/<your-tenant>/<connection-id>/jwks
  2. In Okta, go back to your app's General tab → PUBLIC KEYS section.
  3. In the JWKS URL field (visible because you selected "Use a URL to fetch public keys" in Step 1), paste the URL you just copied.
  4. Click Save. Okta will fetch the JWKS from Relyance.

✅ Okta caches the JWKS for around an hour.

Subsequent key rotations on Relyance's side are picked up automatically - you won't need to revisit this step.

Step 6 - Test the connection

Back to Relyance

  1. In Relyance, return to the Okta connection page and click Save (or Test Connection ) again.
  2. Relyance signs a token request with its private key, Okta verifies it against the JWKS it fetched from your URL, and the connection succeeds if scopes and admin-role permissions are correctly assigned. ✅

How the token request is signed

Worth knowing before you debug one, because it explains most failures:

  • The grant is client credentials with private_key_jwt — there is no client secret for this method, which is why the app's client authentication must be Public key / Private key.
  • Every request is also DPoP-bound (RFC 9449). Relyance always sends a DPoP proof and answers Okta's use_dpop_nonce challenge automatically; there is no non-DPoP fallback, so an app that cannot accept a DPoP-bound token request will never connect.
  • One EC P-256 key signs both the client assertion and the DPoP proof. Relyance generates and holds it, and publishes it at the Public Key URL — which is why that URL is read-only in Relyance and why Okta must fetch the JWKS from it rather than being given a static key.
  • Proofs carry an iat timestamp and are short-lived, so significant clock skew on either side shows up as a rejected proof rather than as a scope or role error.

After it connects: confirm you got the whole picture

Okta grants only the scopes the app is authorised for and silently omits the rest — a connection can succeed with a partial grant, so verify rather than assume:

  1. Open the connection and check Scopes and Permissions lists all nine scopes from Step 2.
  2. In Last Scan Status, confirm the resource groups you expect (users, groups, system logs, applications) completed. A group that scanned zero resources usually means its scope was requested but not granted.
  3. If DSR deletion is in scope, confirm okta.users.manage is present. Granting only the read scopes keeps the app read-only regardless of its admin role.

🔧 Troubleshooting

Error Likely cause Fix
invalid_client / The client_assertion JWT kid is invalid Okta hasn't (re)fetched the JWKS yet, or the URL was pasted into the wrong app Confirm the JWKS URL in the right app, save Okta config, wait ~30 seconds, retry
unauthorized_client App's client authentication is not set to Public key / Private key In Okta General tab → Client Credentials, switch to Public key / Private key
E0000006 / You do not have permission The service app has scopes, but no admin role or an admin role/resource set that does not cover the requested resource Assign Super Administrator (the default - Vendor Discovery requires it). Read-Only Administrator is sufficient only if Vendor Discovery is disabled.
E0000006 on /integrations/api/v1/api-services only Vendor Discovery endpoint reached without Super Administrator (no lesser role can authorize it) Assign Super Administrator to the service app, then retry - no key rotation needed. As long as you grant only read scopes, the app stays read-only despite the role (verify on the Okta API Scopes tab). If you don't want Super Administrator, disable Vendor Discovery; all other areas keep working.
insufficient_scope One or more required OAuth scopes were not granted Okta API Scopes tab → grant any missing scopes from the table in Step 2
Okta can't reach the JWKS URL URL typo, or Okta blocked the domain Open the URL in a browser - it should return JSON with a keys array
Works now, stops working later Okta app deactivated, or the integration removed in Relyance Check the app's status in Okta Admin Console; verify the Relyance connection still exists
invalid_dpop_proof The DPoP proof was rejected — most often clock skew between Relyance and Okta, or an app that cannot accept a DPoP-bound token request Check the Okta app accepts DPoP for token requests; there is no non-DPoP fallback
Connected, but a resource group scanned zero items The scope for that area was requested but not granted — Okta omits ungranted scopes silently rather than failing Compare Scopes and Permissions on the connection against the nine scopes in Step 2, then grant the missing one
Sandbox tenant will not connect The Sandbox Oauth2 method takes Okta domain (the full domain), not the Okta Subdomain the production methods use Enter the full domain for the sandbox method

Part 2 - OAuth2 Authentication (OIDC Web App)

Use this method only if you cannot create an API Services app. It requires an Okta Subdomain, Client ID, Client Secret, and an interactive OAuth2 sign-in.

In Okta

You'll need to first create an OAuth 2.0 application.

  1. Login to your Okta account.
  2. Click on the Applications menu, and navigate to and click on the Applications menu item.
  3. Click on Create App Integration.
  4. Select Sign-In Method = OIDC and Application Type = Web Application, and click Next.
  5. Enter the following: App Integration Name: Relyance (or whatever you would like it to be) Logo (optional): Attached to this guide. Sign-in Redirect URIs: https://root.relyance.ai/api/oauth2 Assignments - Controlled Access: Skip group assignment for now.
  6. Click on Save.
  7. Use the copy icon buttons to copy and save the Client ID and Client Secret to be used in Relyance AI later.
  8. Click on the Edit button in the following screen.
  9. Enable the Refresh Token checkbox. The refresh token allows

mceclip1.png

mceclip2.png

mceclip3.png

mceclip0.png offline_access

. It is a long-lived token that can be used to obtain a new access token when the original one expires. 10. Scroll down, and click on Save. 11. Click on the Assignments tab. 12. Click on the Assign dropdown and select Assign to People. 13. Assign a user account to be used in the OAuth authentication for the integration (you may wish to create a new service account for this instead of attaching it to a named user) by clicking Assign beside their name, then Save and Go Back. If authentication is being done using a service account, ensure the service account is assigned to the Okta application and has Read-only Administrator access. 14. Click on Done. 15. Click on the Okta API Scopes tab. 16. Grant the following scopes: - okta.logs.read - okta.users.read - okta.apps.read - okta.idps.read - okta.authenticators.read - okta.oauthIntegrations.read - okta.groups.read - okta.orgs.read 17. If using a service account, you will need to grant the account Read-only Administrator access. Navigate to Security › Administrators, select the service account, and provide it with the Read-only Administrator role.

In the Relyance AI application

Screenshot Screenshot

  1. Login to your Relyance AI account.
  2. Navigate to the Settings (bottom-left corner).
  3. Select Integrations.
  4. Search and locate the Okta integration card and click on it.
  5. Click on the Add Connection button on the top right.
  6. Provide a meaningful name for the integration and click on the Add button.
  7. In the Overview section, select the integration features you wish to enable, review the Scope and Permission and Endpoint details, and click on Continue. For more details, see

Screenshot Screenshot Screenshot

Integration Features

. 8. In the Connection section, provide the appropriate values and click on Continue: 1. Connection Name: Updates the integration named in Step 6. If you have multiple integrations for the same vendor, assign distinct names to streamline filtering by Discovery Source across the Inventory, Visual Maps, Assets, and Data Flow Analysis pages. 2. Rescan Frequency: Configures how often Relyance executes scans against this vendor connection. 3. Business Atlas Associations (required): the business entities or products that newly discovered third parties, services and assets from this integration are attributed to. Choose at least one from the Select Associations dropdown — the wizard will not advance past this step without one. For more details, see Business Atlas.4. For more details, see

Business Atlas

. 9. In the Authentication section, choose one of the modes below. Machine to Machine is recommended for new connections (see Part 1 ). 1. OAuth2 / App Token - Client ID, Client Secret, Okta Subdomain 2. Custom - API Token, Subdomain 3. Sandbox OAuth2 - Client ID, Client Secret, Okta domain (the full domain, not just the subdomain prefix) 4. Okta Classic - API Token, Subdomain 10. This step applies only if the Data Inspection check box was enabled in Step 7. In the Data Inspection section, provide the appropriate values and click on Continue: - Minimum Confidence Level: Adjusts the sensitivity of Data Inspection. Lower likelihoods (e.g. unlikely ) offer more coverage but may produce false positives; higher sensitivity (e.g. very likely ) provides greater accuracy but less coverage. 11. Review the configuration summary from the Completion section and click on Finish. 12. Confirm the integration Status reflects Connected.

Screenshot

Screenshot

Screenshot

Check the connection after setup

Open the connection to see what Relyance is authorised for and what the last scan actually covered — a missing scope or a partial grant shows up here rather than as an error:

The connections list for this integration

Manage this integration with Terraform

Connections for this integration can be managed as code with the Relyance Terraform provider. Non-secret fields go in auth.params; secret fields go in auth.secrets_wo, which is write-only — never stored in Terraform state. Rotate secrets by bumping auth.secrets_wo_version.

OAuth client credentials (M2M)

resource "relyance_integration_connection" "okta_0" {
  vendor = "okta"
  name   = "<your connection name>"

  auth = {
    method = "oauth-client-credentials"
    params = {
      client_id = "<client_id>"
      subdomain = "<subdomain>"
      public_key_url = "<public_key_url>"
      data_storage_location = "us"
    }
  }

  scans = { "data-inspection" = { enabled = true } }
}

OAuth (browser authorization)

The OAuth (browser authorization) method uses a browser authorization flow, so the connection is created in the Relyance app. Manage it in Terraform afterwards by importing it (terraform import relyance_integration_connection.example okta/<connection_id>) or reading it with the relyance_integration_connection data source.

API token

resource "relyance_integration_connection" "okta_2" {
  vendor = "okta"
  name   = "<your connection name>"

  auth = {
    method = "api-token"
    params = {
      subdomain = "<subdomain>"
      data_storage_location = "us"
    }
    # Secret fields are write-only: sent to Relyance, never stored in state.
    secrets_wo = {
      api_token = var.okta_api_token
    }
    secrets_wo_version = 1
  }

  scans = { "data-inspection" = { enabled = true } }
}

OAuth (browser authorization) — Sandbox Oauth2

The OAuth (browser authorization) — Sandbox Oauth2 method uses a browser authorization flow, so the connection is created in the Relyance app. Manage it in Terraform afterwards by importing it (terraform import relyance_integration_connection.example okta/<connection_id>) or reading it with the relyance_integration_connection data source.

API token — Okta Classic

resource "relyance_integration_connection" "okta_4" {
  vendor = "okta"
  name   = "<your connection name>"

  auth = {
    method = "api-token-okta-classic"
    params = {
      subdomain = "<subdomain>"
      data_storage_location = "us"
    }
    # Secret fields are write-only: sent to Relyance, never stored in state.
    secrets_wo = {
      api_token = var.okta_api_token
    }
    secrets_wo_version = 1
  }

  scans = { "data-inspection" = { enabled = true } }
}