> For the complete documentation index, see [llms.txt](https://docs.lithnet.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.lithnet.io/okta-ma/authentication/creating-the-oauth-service-app.md).

# Creating the OAuth service app

Create the Okta API Services app used by both OAuth authentication methods.

Both OAuth methods use the same Okta object: an API Services app authenticating with `private_key_jwt`. This page covers creating the app, and the method-specific pages cover the key itself.

You'll need a Super Administrator account to grant the OAuth scopes, as Okta doesn't allow any other role to perform this step.

## Before you begin

Have the public key ready, or decide that Okta will generate the key pair:

* For [X.509 certificate authentication](/okta-ma/authentication/oauth-with-an-x509-certificate.md), create the certificate on the MIM server first and bring its public JWK here.
* For [private JWK authentication](/okta-ma/authentication/oauth-with-a-private-jwk.md), either bring the public half of your own key pair, or let Okta generate a 2048-bit RSA pair while you create the app.

## Step 1: Create the app

1. In the Okta Admin Console, open **Applications** > **Applications**.
2. Select **Create App Integration**, then **API Services**.
3. Name it something a future administrator will recognize, such as `MIM - Okta Management Agent`.
4. Save the app and record the **Client ID**.

![Selecting API Services when creating the app integration.](https://2206708376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0u5rDWCokdBire3bUPyS%2Fuploads%2Fgit-blob-319625959f9e28c3671b829a17ff874d80ec7175%2Fokta-create-api-services-app.png?alt=media)

![The service app General page, showing the client ID and client authentication method.](https://2206708376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0u5rDWCokdBire3bUPyS%2Fuploads%2Fgit-blob-6a188bf2459d12a153931e973a9a5e35dd34a42e%2Fokta-service-app-overview.png?alt=media)

## Step 2: Switch to public key authentication

On the app's **General** tab:

1. In **Client Credentials**, select **Edit**.
2. Set **Client authentication** to **Public key / Private key** and select **Save**. Confirm the change if prompted.
3. In **Public keys**, select **Edit** and choose **Save keys in Okta**.

![Configuring public-key client authentication and storing public keys in Okta.](https://2206708376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0u5rDWCokdBire3bUPyS%2Fuploads%2Fgit-blob-8af4646399ee858966f085c842101119c3e1bfbe%2Fokta-client-credentials-public-key.png?alt=media)

## Step 3: Add the public key

Select **Add** to open **Add a public key**, then follow the section below that matches your situation.

### Paste your own public key

Use this for X.509 certificate authentication, and for a private JWK you generated yourself.

Paste the public JWK, then select **Save** and save the **Public keys** section if prompted.

![Adding a public JWK to the service app.](https://2206708376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0u5rDWCokdBire3bUPyS%2Fuploads%2Fgit-blob-a5fbe0b89a7a8cf4a3d9e46fb637811850f0d1be%2Fokta-add-public-key.png?alt=media)

The box takes a single JWK object, not a JWKS document with a `keys` array. It must contain a `kid`, because Okta requires every key on the app to have a unique identifier.

{% hint style="info" %}
Okta only ever receives the public key. For X.509 authentication, that means the JWK the management agent tooling produced from your certificate. Do not upload the certificate, a `.cer` file, or a PFX.
{% endhint %}

For private JWK authentication, check that what you paste is the public half only: it must not contain `d`, `p`, `q`, `dp`, `dq`, or `qi`. The public and private JWK must share the same `kid`.

### Let Okta generate a key pair

Only for private JWK authentication.

1. Select **Generate new key**.
2. Copy the private JWK as soon as Okta displays it. Okta will not show it again.
3. Complete the dialog and save the **Public keys** section.

Okta generates a 2048-bit RSA pair. Keep the private JWK as a single JWK object, not wrapped in a `keys` array. You'll place it on the MIM server later.

## Step 4: Grant the OAuth scopes

Open the **Okta API Scopes** tab. Always grant `okta.schemas.read`, then grant the scopes matching what MIM will manage.

| MIM requirement                         | Scope                |
| --------------------------------------- | -------------------- |
| Retrieve the MIM schema                 | `okta.schemas.read`  |
| Import users only                       | `okta.users.read`    |
| Import and manage users                 | `okta.users.manage`  |
| Import groups and membership only       | `okta.groups.read`   |
| Import and manage groups and membership | `okta.groups.manage` |

Grant at least one user or group scope. A manage scope also covers importing, so you don't need to grant the matching read scope as well.

![The OAuth scopes required for user and group management.](https://2206708376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0u5rDWCokdBire3bUPyS%2Fuploads%2Fgit-blob-2ee4192c36dcc9f1431961e48a8811ccdce9d8c9%2Fokta-api-scopes.png?alt=media)

These grants determine what MIM sees in the schema. If no user scope is granted, the `user` object type isn't presented at all. A read scope presents import-only attributes, and a manage scope adds the exportable ones. The same applies to groups.

MIM schemas don't refresh by themselves, so retrieve the schema again in MIM after any scope change.

## Step 5: Assign an admin role

Open the app's **Admin roles** tab and assign a role covering the objects and operations MIM will manage.

A standard administrator role is fine when it matches what the connector needs. Use a custom role with a resource set when the connector must be confined to particular users or groups.

![An administrative role assigned to the service app.](https://2206708376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0u5rDWCokdBire3bUPyS%2Fuploads%2Fgit-blob-ba54da8ce0f8a976989f9c84c56b11ce0c75d73c%2Fokta-admin-roles.png?alt=media)

For a custom role, these are the Okta permissions matching each connector operation:

| Connector operation              | Okta permission                                                            |
| -------------------------------- | -------------------------------------------------------------------------- |
| Import users                     | `okta.users.read`                                                          |
| Create users                     | `okta.users.create`                                                        |
| Update user profiles             | `okta.users.userprofile.manage`                                            |
| Activate users on create         | `okta.users.lifecycle.activate`                                            |
| Suspend and unsuspend            | `okta.users.lifecycle.suspend`, `okta.users.lifecycle.unsuspend`           |
| Deactivate                       | `okta.users.lifecycle.deactivate`                                          |
| Permanently delete               | `okta.users.lifecycle.delete`                                              |
| Set or change a password         | `okta.users.credentials.resetPassword`, or `okta.users.credentials.manage` |
| Import groups and membership     | `okta.groups.read`                                                         |
| Create, update, or delete groups | `okta.groups.manage`                                                       |
| Change group membership          | `okta.groups.members.manage` and `okta.users.groupMembership.manage`       |

`okta.users.manage` covers the user create and profile permissions, and `okta.users.lifecycle.manage` covers all the lifecycle ones, if you'd rather grant access more broadly.

{% hint style="info" %}
Okta doesn't publish a role permission that covers the user profile schema, which the connector reads to build the MIM schema. Standard roles include this access. If schema retrieval fails under a custom role, this is the first thing to check.
{% endhint %}

Okta's [permissions](https://developer.okta.com/docs/api/openapi/okta-management/guides/permissions) and [roles](https://developer.okta.com/docs/api/openapi/okta-management/guides/roles) references list everything available.

Scopes and roles are independent. A scope appearing in the MIM schema doesn't mean Okta will permit the operation, and Okta doesn't expose the role's boundaries during schema retrieval. If the role or resource set is too narrow, the schema will still retrieve cleanly, but an import or export will fail with `403 Forbidden`.

## Step 6: Require DPoP (optional)

The management agent supports DPoP, and no configuration is needed in MIM to use it. To require it:

1. On the app's **General** tab, edit **Proof of possession** under **General Settings**.
2. Enable **Require Demonstrating Proof of Possession (DPoP) header in token requests**.
3. Save the app.

![Requiring DPoP proofs for the service app.](https://2206708376-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0u5rDWCokdBire3bUPyS%2Fuploads%2Fgit-blob-a29a2168972ee5ce24f772a030e8e2cff46da327%2Fokta-dpop-setting.png?alt=media)

Okta's [DPoP documentation](https://developer.okta.com/docs/guides/dpop/) describes the setting.

## Step 7: Continue the setup in MIM

You should now have the client ID, a registered public key, the OAuth scopes, and an admin role. Continue with:

* [Configure a private JWK in MIM](/okta-ma/authentication/oauth-with-a-private-jwk.md#step-3-configure-mim)
* [Configure an X.509 certificate in MIM](/okta-ma/authentication/oauth-with-an-x509-certificate.md#step-5-configure-mim)

Okta's [service app OAuth guide](https://developer.okta.com/docs/guides/implement-oauth-for-okta-serviceapp/-/main/) covers the same configuration from the Okta side.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.lithnet.io/okta-ma/authentication/creating-the-oauth-service-app.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
