Okta is a cloud identity and access management platform; Serval connects to it to read and manage users, groups, and applications, run access reviews, and automate identity lifecycle tasks.
Okta is a cloud identity and access management (IAM) platform for managing users, groups, and application access. Serval connects to Okta using OAuth 2.0 client credentials against an Okta API Services app. Once connected, Serval can reach any Okta Management API capability - reading and managing users, groups, and applications, running access reviews, and automating identity lifecycle tasks. Serval also continuously brings your Okta directory into Serval in the background so users, groups, and applications stay up to date.Authentication: OAuth 2.0 client credentials - either a client secret (client_secret_basic) or a private key JWT (private_key_jwt).Data sync: On-demand access to the full Okta Management API from workflows, plus a built-in background directory sync of users, groups (with members), and applications (with their assigned groups). Optionally, Okta event hooks push user and group changes to Serval in real time.
Any Okta Management API capability can be used from a workflow, with automatic retries on transient errors, pagination handling, and rate-limit awareness.
User lifecycle management
Create users, look up a user by email, deactivate users, and suspend users (which clears their active sessions first, then suspends them). Requires the user read and/or manage scopes.
Group management and membership
Create groups, look up a group by exact name, list all groups, and add or remove a user from a group. Requires the group read and/or manage scopes.
Background directory sync
Continuously brings Okta users, groups (with members), and applications (with their assigned groups) into Serval on a schedule - groups refresh fully every 48 hours with a delta sync every 4 hours; users and apps sync on the standard schedule.
Real-time sync via event hooks
Optionally, an Okta event hook notifies Serval the moment a user or group changes, and Serval refreshes just that user or group within seconds - see Real-time sync with event hooks.
Access management and provisioning
Grants and revokes access by adding or removing users from Okta groups (using the “Member” entitlement). Requires the group manage scope.
Serval connects to an Okta API Services app using OAuth 2.0 client credentials. You can either install Serval from the Okta Integration Network (OIN), which generates credentials for you, or create your own custom Okta API Services app. In both cases you must grant the required scopes on the Okta app and assign the app an admin role so those scopes can actually act on resources. Full provider guidance lives in Okta’s client credentials grant guide.
Add the integration, review the requested API scopes, and authorize it. Okta generates a Client ID and a Client Secret for your org.
3
Copy the Client Secret immediately
The Client Secret is shown only once. Copy it right away - you will not be able to view it again later.
4
Assign an admin role
Under your admin-role assignments, give the app an admin role such as Super Administrator, a combination like Group / Organization / Application Administrator, or a least-privilege custom role with a resource set. Scopes plus the admin role together govern what Serval can do.
1
Create an API Services app
In the Okta admin console, create a new app integration of type API Services, name it (for example, “Serval”), and save it.
2
Grant API scopes
Grant the required scopes to the app - at minimum the read scopes for users, groups, and apps; add the manage scopes to let Serval take action. Okta groups these under the User, Group, Application, and SystemLog tags.
3
Assign an admin role
Under your admin-role assignments, assign the app an admin role (Super Administrator, a set such as Group / Organization / Application Administrator, or a custom role plus resource set).
A scope alone is not enough. Scopes gate which parts of the API are available; the admin role gates which resources Serval can actually touch.
4
Copy the credentials
Copy the Client ID (shown at the top of the app integration page) and the Client Secret to paste into Serval.
1
Create an API Services app
In the Okta admin console, create a new app integration of type API Services, name it (for example, “Serval”), and save it.
2
Disable DPoP
In the app’s general settings, uncheck the “Require Demonstrating Proof of Possession (DPoP)” option.
Serval does not support DPoP / proof-of-possession. If it is left enabled, token use will be rejected.
3
Switch to public/private key authentication and add a key
Set client authentication to the public-key / private-key method, add a key, generate it, and copy the key. Save it when prompted.
The key is not saved until you confirm it - verify it persisted before leaving the page. The key must be an RSA key.
4
Grant API scopes and assign an admin role
Grant the required scopes and assign the app an admin role under your admin-role assignments, exactly as for the client-secret path.
5
Copy the credentials
Copy the Client ID (shown at the top of the app integration page) and the full generated key to paste into Serval.
Enter your credentials into the Serval connect form. The same fields are used whether you authenticate with a client secret or a private key - Serval automatically picks the right method based on what you paste into the Client Secret field.
1
API Domain (required)
Your Okta domain without the leading “https://” - for example, “yourcompany.okta.com”. Enter the bare host with no scheme and no “-admin” suffix.
Do not paste the admin console URL. If your console shows “yourcompany-admin.okta.com”, strip the “-admin” and enter “yourcompany.okta.com”. An invalid domain shows: “Must be a valid Okta domain (e.g., yourcompany.okta.com)”.
2
Client ID (required)
The OAuth 2.0 client ID from your Okta application - exactly 20 alphanumeric characters. An invalid value shows: “Must be a valid Okta client ID (20 alphanumeric characters)”.
3
Client Secret (required)
This field is masked. Paste either your plain OAuth 2.0 client secret or the full private key you generated in Okta. Serval automatically uses the private-key method when you paste a key, and the client-secret method otherwise.
When editing an existing connection, you can leave this field blank to keep the stored secret unchanged. The stored secret is always shown masked, never in clear text.
4
Scopes (required)
A comma-separated list of OAuth scopes. Serval pre-fills a default set covering app, user, and group read and manage plus log read. These scopes must also be granted on the Okta app itself. Not all of the pre-filled scopes are required - you can remove any scopes you don’t need.
An empty list is rejected. Each scope must follow the expected format, otherwise you will see: “Each scope must follow the format okta.<resource>.<operation> or okta.<resource>.<subresource>.<operation> (e.g., okta.users.read, okta.accessRequests.catalog.read). SSF scopes are ssf.<operation> (e.g., ssf.read, ssf.manage).”
After you connect, Serval runs a series of health checks against your Okta org and reports the result of each one. Each health check is an API call that exercises a specific scope, so the checks always run regardless of which scopes you configured - a check whose scope you removed will simply fail with a missing-scope message. This is expected if you intentionally trimmed the scope list, and you can safely ignore failures for capabilities you don’t plan to use.
List Okta Apps confirms Serval can list applications. On success it reports “Successfully listed” followed by the number of apps found. On failure it reports “Unable to list apps.” If the required scope is missing in Serval, it reports “Missing required scope in Serval: okta.apps.read”.
List Okta Users confirms Serval can list users. On success it reports “Successfully listed” followed by the number of users found. On failure it reports “Unable to list users.” If the scope is missing, it reports “Missing required scope in Serval: okta.users.read”.
List Okta Groups confirms Serval can read groups. On success it reports “Successfully listed” followed by the number of groups found. On failure it reports “Unable to list groups.” If the scope is missing, it reports “Missing required scope in Serval: okta.groups.read”.
Manage Okta Groups creates a temporary test group (named with a “serval-healthcheck-” prefix) and immediately deletes it to verify write access. On success it reports “Successfully created and deleted test group:” followed by the test group’s name. On failure it reports “Unable to create and delete groups.” If the scope is missing, it reports “Missing required scope in Serval: okta.groups.manage”.
When a check fails with a permission error, Serval adds: “The correct scope is configured in Serval, but the OAuth application may need admin consent or additional admin roles in Okta.” When Okta returns a server error, Serval adds: “Okta returned a server error. This is likely a temporary issue with Okta’s API - please try again later.”
The most common surprise: the scope is configured correctly in Serval but a check still fails with a permission error. This almost always means the Okta app is missing the admin role (or admin consent). Assign the app an admin role under your admin-role assignments - a scope on its own is not enough.
By default, Serval learns about changes in Okta on the background sync schedule, so a change can take hours to appear. With an Okta event hook configured, Okta notifies Serval the moment a user or group changes, and Serval re-fetches just that user or group - changes typically appear in Serval within seconds.This is optional and additive: the background directory sync keeps running either way, acting as a safety net for anything the event hook misses.No additional OAuth scopes are required - event hooks reuse the same scopes your directory and resource sync already use.
If you don’t see the Webhooks section described below on your Okta application’s Settings tab, make sure user or resource (group) sync is enabled for this Okta app - the section only appears once one of those syncs is turned on. If it’s still missing, contact support@serval.com.
1
Copy the webhook details from Serval
In Serval, go to Applications, open your Okta application, and switch to the Settings tab. The Webhooks section shows two values: a Webhook URL (on Serval’s public API host) and a Secret. Copy both.
The Secret can be re-copied from this page at any time - unlike Okta, Serval does not hide it after setup.
2
Create the event hook in Okta
In the Okta admin console, go to Workflow → Event Hooks and choose Create Event Hook. Give it a name (for example, “Serval real-time sync”) and fill in:
URL: the Webhook URL copied from Serval.
Authentication field: X-Webhook-Secret
Authentication secret: the Secret copied from Serval.
Custom header fields: leave empty.
Paste the Secret exactly as copied - no quotes and no trailing whitespace. Serval compares the value character-for-character and rejects anything that doesn’t match.
3
Subscribe to events
The Subscribe to events box starts empty - add the events Serval acts on. Okta lists them by friendly name; these are the ones that trigger a refresh (API event type in parentheses).User events (for user sync):
User removed from group (group.user_membership.remove)
Any other event types are safely ignored, and any extra user.* or group.* event simply re-fetches that user or group, so subscribing to more does no harm.
4
Verify the hook
Save the hook and click Verify. Okta sends a one-time verification challenge to the Webhook URL, which Serval answers automatically.
The hook shows as “Verified” in Okta. From this point on, changes flow to Serval as they happen.
A health check fails on permissions even though the scope is set in Serval
Scopes typed into the Serval form are only the scopes requested on the token. They must also be granted on the Okta API Services app, and the app must be assigned an admin role (or a custom role plus resource set). Scopes gate which part of the API is available; the admin role gates which resources can be acted on. Add the missing scope on the Okta app and assign it an admin role under your admin-role assignments.
EMEA (okta-emea.com) domains fail at request time
Serval only connects to “okta.com” and “oktapreview.com” hosts. The connect form’s validation will accept an “okta-emea.com” domain, but requests to EMEA-cell domains will fail once they actually run. Use an “okta.com” or “oktapreview.com” domain.
The API Domain is rejected or requests go to the wrong host
The API Domain field expects a bare host such as “yourcompany.okta.com”. Do not include “https://”, and do not copy the admin console URL - “yourcompany-admin.okta.com” is wrong; strip the “-admin” to get “yourcompany.okta.com”. The domain is used as both the token host and the API base, so a wrong value breaks everything downstream.
Private key authentication isn't being used (or fails)
Serval decides between the plain-secret and private-key methods purely by whether the Client Secret value is a key (in JSON form). For key-based authentication, paste the full key into the Client Secret field; anything that is not a JSON key is treated as a plain client secret. The key must be an RSA key - a non-RSA key fails token generation with “key is not an RSA private key”.
Tokens are rejected after enabling private key auth
Serval does not support DPoP / proof-of-possession. In the custom API Services app’s general settings, uncheck the “Require Demonstrating Proof of Possession (DPoP)” option before connecting, otherwise token use will be rejected.
Updating the connection wiped or kept the secret unexpectedly
On update, Serval still requires Scopes, Client ID, and API Domain, but the Client Secret is optional. Leave it blank to keep the existing stored secret unchanged, or paste a new value to replace it. The stored secret is always returned masked.
Requests are being throttled / rate limited
Okta enforces roughly 250 requests per minute per application on the groups and apps endpoints. Serval paces background syncs to stay under this limit and automatically retries when throttled, but heavy custom workflows against these endpoints can still hit Okta’s rate limits.
Event hook verification fails in Okta
Check the URL first: it must be the exact Webhook URL copied from the Webhooks section of your Okta application’s Settings tab in Serval, with no edits. A 404 during verification almost always means the URL is wrong or truncated. If the URL is correct and verification still fails, re-copy the Secret from Serval and re-save the hook - remember it must be pasted exactly into the X-Webhook-Secret authentication field.
The event hook is verified but changes don't appear in Serval
Confirm the hook is subscribed to the event types listed in Real-time sync with event hooks - a verified hook with no matching subscriptions delivers nothing useful. Also check Okta’s event hook preview/delivery log to confirm Okta is sending events and receiving successful responses. If deliveries succeed but nothing changes in Serval, the secret may be wrong: Serval acknowledges every delivery (so Okta shows success) but rejects events whose X-Webhook-Secret value doesn’t match. Re-copy the Secret from Serval and update the hook. The scheduled background sync still keeps data correct in the meantime.
Need help? Contact support@serval.com for assistance with your Okta integration.