Migrating OAuth Clients

When you move an OAuth authorization server to Descope, the hardest part is often the clients. Partner apps and machine-to-machine (M2M) services already hold a client_id and client_secret from your previous provider, and rotating every one of them means coordinating a change with every team or customer that owns a client.

Descope avoids that by letting you create each Inbound App with the client's existing credentials. The clients keep calling with the same ID and secret while you cut the token endpoint over to Descope. The one change your services do need is the issuer they validate, covered in Issuer After Importing Client IDs.

This page covers the OAuth client side of a migration. For users, passwords, and sessions, see Migration to Descope and Session Migration.

Importing Existing Client Credentials

Note

Some SDKs do not expose these fields yet, in which case you can use the Management API. See Inbound Apps with SDKs for more details.

To import a client, pass clientId and clientSecret when you create the Inbound App through the Management API. If you leave them empty, Descope computes a client ID and generates a secret, which is the default in the Console.

The clientId and clientSecret fields are accepted only at create time and cannot be changed later. The clientId must be unique in the project. For a public client, pass clientId only.

curl -X POST "__BaseURL__/v1/mgmt/thirdparty/app/create" \
  -H "Authorization: Bearer <Project ID>:<Management Key>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Migrated partner client",
    "clientId": "<existing-client-id>",
    "clientSecret": "<existing-client-secret>"
  }'

The create response returns the app id, the clientId, and cleartext (the secret) once. Store the secret if you need it. After that, the Console and load APIs show the client ID the same way they do for a generated app.

For the rest of the app's configuration, such as scopes, redirect URLs, and the consent flow, see Creating Inbound Apps.

Issuer After Importing Client IDs

Note

The Connection Information does not change for apps that weren't imported with a custom client ID, whether they existed before the migration or you create them after it.

Those apps keep showing __BaseURL__/v1/apps/__ProjectID__ as their issuer. To keep one consistent issuer per project, use the customized issuer with those apps too.

Importing an app with a custom clientId changes your project-level issuer. Before the import, the issuer is __BaseURL__/v1/apps/__ProjectID__. After the import, the issuer for your project is:

__BaseURL__/v1/apps/customized/__ProjectID__

Use the customized issuer wherever you validate tokens for the imported apps, such as the iss check in your APIs or gateway. If those services validated tokens from your previous authorization server, set their expected issuer to this value when you switch them over to Descope.

You can also use the customized issuer for every other app and agentic client in the project, including the ones that existed before the import and the ones you create afterward. Using one issuer everywhere means your services only need to trust one issuer.

Was this helpful?

On this page