Refresh Token Migration

Starting in Mobile SDK 13.2, apps can seamlessly migrate a user’s refresh token to a new consumer key or different scopes without requiring the user to log out and log back in.

Migration Scenarios 

Seamless refresh token migration enables apps to adopt different OAuth configurations, including:

  • Token format upgrades - Migrate from standard opaque tokens to JWT-based access tokens.
  • App type transitions - Migrate from a connected app to an external client app. See Salesforce Help: Create an External Client App from a Connected App.
  • Scope expansion - Exchange a refresh token for a new one that includes additional post-login scopes, such as sfap_api.

Migration Behavior Rules 

  • The migration process exchanges the existing refresh token for a new token using the new OAuth configuration.
  • If the new configuration requires additional scopes or uses a different consumer key, the user can see the OAuth approval screen.
  • After successful migration, the refresh token and access token are replaced, and the consumer key, redirect URI, and scopes are updated in the user account.
  • The user org ID and user ID remain unchanged.
  • If migration fails, existing credentials remain unchanged.

Token Migration APIs for Android 

To migrate a user refresh token to a new OAuth configuration on Android, use these methods on UserAccountManager.

1val currentUser = UserAccountManager.getInstance().currentUser
2val newConfig = OAuthConfig(
3    consumerKey = "new_consumer_key",
4    redirectUri = "new_redirect_uri",
5    scopes = listOf("api", "refresh_token", "id", "sfap_api") // Add new scope.
6)
7
8UserAccountManager.getInstance().migrateRefreshToken(
9    userAccount = currentUser,
10    appConfig = newConfig,
11    onMigrationSuccess = { migratedUser ->
12        Log.d(TAG, "Migration successful for ${migratedUser.username}")
13        // User account has been updated with new credentials.
14    },
15    onMigrationError = { error, errorDesc, exception ->
16        Log.e(TAG, "Migration failed: $error - $errorDesc", exception)
17        // Handle error; user may need to re-authenticate.
18    }
19)
1UserAccount currentUser = UserAccountManager.getInstance().getCurrentUser();
2OAuthConfig newConfig = new OAuthConfig(
3    "new_consumer_key",
4    "new_redirect_uri",
5    Arrays.asList("api", "refresh_token", "id", "sfap_api") // Add new scope.
6);
7
8UserAccountManagerExtensionKt.migrateRefreshToken(
9    UserAccountManager.getInstance(),
10    currentUser,
11    newConfig,
12    migratedUser -> {
13        Log.d(TAG, "Migration successful for " + migratedUser.getUsername());
14        return null;
15    },
16    (error, errorDesc, exception) -> {
17        Log.e(TAG, "Migration failed: " + error + " - " + errorDesc, exception);
18        return null;
19    }
20);

Token Migration APIs for iOS 

To migrate a user refresh token to a new OAuth configuration on iOS, use migrateRefreshToken on UserAccountManager (Swift) or SFUserAccountManager (Objective-C).

1guard let currentUser = UserAccountManager.shared.currentUserAccount else { return }
2
3let newConfigDict: [String: Any] = [
4    "remoteAccessConsumerKey": "new_consumer_key",
5    "oauthRedirectURI": "new_redirect_uri",
6    "oauthScopes": ["api", "refresh_token", "id", "sfap_api"], // Add new scope.
7    "shouldAuthenticate": true
8]
9guard let newConfig = BootConfig(newConfigDict) else { return }
10
11UserAccountManager.shared.migrateRefreshToken(
12    for: currentUser,
13    newAppConfig: newConfig,
14    success: { authInfo, migratedUser in
15        print("Migration successful for \(migratedUser.userName ?? "")")
16    },
17    failure: { authInfo, error in
18        print("Migration failed: \(error.localizedDescription)")
19    }
20)
1SFUserAccount *currentUser = [SFUserAccountManager sharedInstance].currentUser;
2NSDictionary *newConfigDict = @{
3    @"remoteAccessConsumerKey": @"new_consumer_key",
4    @"oauthRedirectURI": @"new_redirect_uri",
5    @"oauthScopes": @[@"api", @"refresh_token", @"id", @"sfap_api"],
6    @"shouldAuthenticate": @YES
7};
8SFSDKAppConfig *newConfig = [[SFSDKAppConfig alloc] initWithDict:newConfigDict];
9
10[[SFUserAccountManager sharedInstance] migrateRefreshTokenFor:currentUser
11    newAppConfig:newConfig
12    success:^(SFOAuthInfo *authInfo, SFUserAccount *migratedUser) {
13        NSLog(@"Migration successful for %@", migratedUser.userName);
14    }
15    failure:^(SFOAuthInfo *authInfo, NSError *error) {
16        NSLog(@"Migration failed: %@", error.localizedDescription);
17    }];

We've Moved

Welcome to the new home of the Mobile SDK Developer Guide! For now, the Japanese guide can be found in PDF form.