Session Migration

Migrating from an existing authentication provider such as Auth0, Okta, or a custom-built solution to Descope should not require users to re-authenticate. In many applications, especially those involving mobile, desktop, or smart devices, logging a user out during a migration introduces unnecessary friction and disrupts the user experience.

To improve this experience, Descope supports session migration, which allows your client to send a session token from your existing provider to Descope, who will then verify it, and issue a new Descope session token for the same user. This process allows users to continue their sessions without noticing any change in the underlying authentication system.

How It Works

  1. A user makes a request with an active session token from your existing authentication provider.
  2. Your frontend will use the Descope SDK to send the token to Descope for validation.
  3. Upon successful validation, Descope will extract the unique user identifier (e.g., email or user ID).
  4. Based on that user identifier, Descope will issue a new session token for that user.
  5. The new Descope token is returned to the client, replacing the previous session.

Prerequisites

Important

Currently, session migration is in beta and is only supported with users who have already been imported into Descope. Just in time user creation is not supported at this time.

Before implementing session migration, ensure the following:

  • All users who authenticate using session migration must already exist in Descope.
  • Your backend is capable of validating tokens from Descope, as well as your existing authentication provider.

Step-by-Step Implementation

Step 1. Dual Token Validation in Your Backend

During the migration period, it is recommended for your backend to be capable of validating both legacy and Descope tokens. This is a transitional strategy that allows you to gradually move users to Descope while maintaining your existing authentication as a fallback.

A typical implementation involves checking the token's issuer and key ID (kid) to determine the provider, then validating it accordingly.

Example high-level logic:

function handleRequest(req) {
  const token = extractToken(req);
 
  // First try to validate as a Descope token
  if (isDescopeToken(token)) {
    validateDescopeToken(token);
    return continueRequest();
  }
  
  // If not a Descope token, try legacy token validation
  if (isLegacyToken(token)) {
    const userId = validateLegacyToken(token);
    const descopeToken = issueDescopeToken(userId);
    return respondWithToken(descopeToken);
  }
  
  // If neither token is valid, proceed with normal authentication flow
  return proceedWithNormalAuth();
}

You can use your legacy provider's SDK (e.g., Auth0's jsonwebtoken, Okta's JWT verifier) to validate legacy tokens. This approach ensures a smooth transition by:

  1. Prioritizing Descope tokens for users who have already migrated
  2. Converting legacy tokens to Descope tokens when encountered
  3. Falling back to normal authentication for users who haven't migrated yet

Step 2. Generate Descope Session Token

Important

This action requires the user to already exist in Descope. If the user is not present, the API will return an error.

To implement session migration on the client side, use the getExternalToken prop in the Descope AuthProvider component. This function should return a valid token from your external provider, which the SDK will use to authenticate the user with Descope.

Terminal
npm i --save @descope/react-sdk
import { AuthProvider } from '@descope/react-sdk';
 
const AppRoot = () => {
  return (
    <AuthProvider
      projectId="my-project-id"
      getExternalToken={async () => {
        // Bring token from external provider (e.g. get access token from another auth provider)
        return 'my-external-token';
      }}
    >
      <App />
    </AuthProvider>
  );
};

The SDK will automatically handle the token exchange process, converting the external token into a Descope session token. This allows for a seamless transition without requiring users to re-authenticate.

Step 3. Populate Descope with Users Prior to Migration

Session migration requires that the users already exist in Descope. Descope will not automatically provision users during this process.

Options for populating users:

  • Bulk import: Use the User Import Tool or Management API to import your existing user base.
  • Automated sync:
    • Auth0: Use Auth0 Actions to create users in Descope during login or registration events.
    • Okta: Use Okta Workflows or SCIM provisioning to push users into Descope.
  • Manual provisioning: For static user lists or low-volume use cases.

Important

It is strongly recommended to automate user creation in Descope for any new accounts created between your initial export and the session migration cutover.

Handling the New Descope Token

If you're using Descope's client SDKs (React, Next.js, WebJS, Kotlin, Swift), the SDK will automatically handle session management for you after successful session migration.

The SDK will automatically store and manage the new Descope tokens, so you don't need to manually handle token storage or session management - it works just like completing a flow or logging in via any other SDK authentication method.

Finalizing the Migration

Once your application is stable and all users are actively receiving Descope tokens, you can:

  • Remove legacy token validation logic from your backend.
  • Fully enforce Descope-issued session tokens across all endpoints.
  • Revoke or expire legacy sessions if needed.

Testing and Verification

Before launching session migration in production:

  • Test the flow using both legacy and Descope tokens across various clients.
  • Verify that session tokens are issued with expected claims and expiration times.

Limitations

  • Descope does not support JIT user creation during session migration. You must pre-provision users.
  • Session migration does not carry over legacy tokens' claims (e.g., roles, groups). You must recreate any needed claims in Descope's user profile or token generation logic. For this, you can use a JWT Template.
  • This migration flow only applies to token-based sessions (JWTs, access tokens) and may not work with opaque session cookies unless decoded by your legacy provider.

Summary

Session migration enables a seamless transition to Descope by allowing your backend to recognize and convert existing sessions from other authentication providers. This is especially critical for high-availability or consumer-facing applications where user disruption must be minimized.

By properly preparing your backend and provisioning your user base in advance, you can switch authentication providers with zero impact on the end-user experience. This strategy is commonly used in mobile and enterprise scenarios, where maintaining session continuity is essential.

Was this helpful?