Skip to content

Multi-account login management

Multi-account Login Management is a feature that saves account information when logging in or out, allowing users to reload saved account information for future logins. This provides a faster and more convenient login experience by utilizing previously authenticated account information.


Operation Flow and Restrictions

Before implementing the multi-account login management feature, let's explain the operation flow and restrictions.

The following operation flows for each function are example scenarios for reference when implementing multi-account login management. Depending on your development environment, the order of the flow or the method of saving account information may differ from these scenarios.

Saving Account Information While Logged In

This scenario describes saving account information while the user is logged in after completing an explicit login.

As a result of this scenario, you can implement re-login or account deletion using saved account information later.

※ The method of saving and handling account information may vary depending on the game client implementation.


Saving Account Information on Logout

This scenario describes saving account information when a logged-in user logs out.

As a result of this scenario, you can implement re-login or account deletion using saved account information later.

※ The method of saving and handling account information may vary depending on the game client implementation.


Re-login or Delete Using Saved Account Information

This is a flow for re-logging in using saved account information or deleting specific account information from the retrieved list, which is the actual implementation scenario for multi-account login management.

In the step where a user selects an account from the PlayerID list UI implemented in the game, the behavior differs depending on whether the user is currently logged in or not.

※ The UI configuration method for the PlayerID list implemented in the game client may vary depending on the game development environment.

Operational Restrictions

Before implementing multi-account login management, consider the following operational restrictions.

  • Account information can be saved only when logged in.
  • Using saved account information to view the PlayerID list or delete saved account information can be done regardless of the login status.
  • Re-login with saved account information after viewing the PlayerID list is only possible when logged out.

Implementation Guide

This guide explains how to implement the multi-account login management feature using the SDK.

Implement the feature step by step by calling the APIs provided by the SDK in the following order:

  1. After login is complete, save the current logged-in account information
  2. To log in with the saved account or delete saved account information, retrieve saved account information (PlayerID list)
  3. Using the retrieved saved account information, implement the feature to display the PlayerID list UI when the user clicks on Multi-account Login Management
  4. In the PlayerID list UI, implement login with saved account (PlayerID) or delete saved account (PlayerID)

1. Save the Current Logged-in Account Information

Saves the currently logged-in account information. By using the saved account information, you can log in faster without a separate authentication process during subsequent logins.

In the game client, if the user is logged in, provide a UI element in the account settings menu to allow the user to save the current logged-in account at any time, and call the account save API when the user activates the account save feature. For related flow, refer to the Saving Account Information While Logged In scenario above.

An example of the UI implementation for saving the current logged-in account is as follows.

Figure 1. Example of implementing the saving of the current logged-in account while logged in

Also, when logging out, you can implement a flow where, if the user is logged in and chooses to log out, a popup is displayed asking whether to save the account, and if the user clicks Save and Logout, the account save API is called to save the current logged-in account information and then log out. For related flow, refer to the Saving Account Information on Logout scenario above.

Figure 2. Example of implementing the saving of the current logged-in account when logging out

An example code for calling the API to save the current logged-in account is as follows.

AuthV4.storeCurrentPlayerId((ResultAPI result)=>{
    if (result.isSuccess()) {
        // API call succeeded
    }
});
FHiveAuthV4::StoreCurrentPlayerId(FHiveAuthV4OnStoreCurrentPlayerIdDelegate::CreateLambda([this](const FHiveResultAPI& Result) {
    if (Result.IsSuccess()) {
        // API call succeeded
    } 
}));
AuthV4::storeCurrentPlayerId([=](ResultAPI const & result) {
    if (result.isSuccess()) {
        // API call succeeded
    }
});
AuthV4.storeCurrentPlayerId(object : AuthV4.AuthV4StorePlayerIdListener {
    override fun onAuthV4StorePlayerId(result: ResultAPI) {
        if (result.isSuccess) {
            // API call succeeded
        }
    }
})
AuthV4.storeCurrentPlayerId(new AuthV4.AuthV4StorePlayerIdListener() {
    @Override
    public void onAuthV4StorePlayerId(ResultAPI result) {
        if (result.isSuccess()) {
            // API call succeeded
        }
    }
});
AuthV4Interface.storeCurrentPlayerId { (result) in
    if result.isSuccess() {
        // API call succeeded
    }
}
[HIVEAuthV4 storeCurrentPlayerId: ^(HIVEResultAPI * result) {
    if([result isSuccess]){
        // API call succeeded
    }
}];


2. Retrieve Saved Account Information (PlayerID list)

Retrieves the saved account information (PlayerID list) from the SDK and authentication server. The game client can use the retrieved PlayerID list to implement a separate PlayerID list UI.

An example code for calling the API to retrieve saved account information (PlayerID list) is as follows.

AuthV4.getStoredPlayerIdList((ResultAPI result, List<long> playerIdList) =>
{
    if (result.isSuccess())
    {
        foreach (long playerId in playerIdList) {
            // API call succeeded
            // playerId: player ID
        }
    }
});
FHiveAuthV4::GetStoredPlayerIdList(FHiveAuthV4OnGetStoredPlayerIdListDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TArray<int64>& PlayerIdList) {
    if (Result.IsSuccess()) {
        for (int64 PlayerId : PlayerIdList) {
            // API call succeeded
            // playerId: player ID
        }
    }
}));
AuthV4::getStoredPlayerIdList([=](ResultAPI const & result, std::vector<PlayerID> const& playerIdList) {
    if (result.isSuccess()) {
        for (auto playerId : playerIdList) {
            // API call succeeded
            // playerId: player ID
        }
    }
});
AuthV4.getStoredPlayerIdList(object : AuthV4.AuthV4PlayerIdListListener {
    override fun onAuthV4GetPlayerIdList(result: ResultAPI, playerIdList: ArrayList<Long>?) {
        if (result.isSuccess) {
            playerIdList?.let {
                for (playerId in it) {
                    // API call succeeded
                            // playerId: player ID
                }
            }
        }
    }
})
AuthV4.getStoredPlayerIdList(new AuthV4.AuthV4PlayerIdListListener() {
    @Override
    public void onAuthV4GetPlayerIdList(ResultAPI result, ArrayList<Long> playerIdList) {
        if (result.isSuccess()) {
            if(playerIdList != null) {
                for(Long playerId : playerIdList) {
                    // API call succeeded
                            // playerId: player ID
                }
            }
        }
    }
});
AuthV4Interface.getStoredPlayerIdList { (result, playerIdList) in
    if result.isSuccess() {
        for playerId in playerIdList {
                            // API call succeeded
                            // playerId: player ID
        }
    }
}
[HIVEAuthV4 getStoredPlayerIdList: ^(HIVEResultAPI * result, NSArray<NSNumber *> * playerIdList) {
    if([result isSuccess]){
        for (NSNumber* playerId in playerIdList) {
            // API call succeeded
            // playerId: player ID
        }
    }
}];


3. Login with Saved Account (PlayerID)

Logs in quickly with a saved account (PlayerID) through the multi-account login management feature while logged out.

The implementation steps for logging in with a saved account are as follows.

  1. After the user logs out and tries to log in again, on the login screen, click on Multi-account Login Management → Call the API to retrieve saved account information (PlayerID list)
  2. Display the PlayerID list UI implemented in the previous step
    Figure 3. Example of logging in with a saved account through Multi-account Login Management

  3. The user selects a specific account from the PlayerID list UI and logs in → Call the API to log in with the 'Saved Account Information (PlayerID)'
    'Example code for calling the API to log in with the saved PlayerID' is as follows:

    AuthV4.signInWithStoredPlayerId(playerId, useAutoSignIn, (ResultAPI result, AuthV4.PlayerInfo playerInfo)=>{
        if (result.isSuccess()) {
            // Authentication succeeded
            // playerInfo: Authenticated user information
    
            // Example: Retrieve email information
            foreach (KeyValuePair<AuthV4.ProviderType, AuthV4.ProviderInfo> entry in playerInfo.providerInfoData) {
    
                AuthV4.ProviderInfo providerInfo = entry.Value;
                if(providerInfo.providerEmail != null && providerInfo.providerEmail != "") {
                    string email = providerInfo.providerEmail;
                    break;
                }
            }
        }
        else if (result.needExit()) {
            // TODO: Implement app exit functionality
            // e.g.) Application.Quit();
        }
    });
    
    FHiveAuthV4::SignInWithStoredPlayerId(playerId, useAutoSignIn, FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {
        if (Result.IsSuccess()) {
            // Authentication succeeded (PlayerInfo: Authenticated user information)
    
            // Example: Retrieve email information
            for (const auto& ProviderInfoEntry : PlayerInfo.ProviderInfoData) {
                FHiveProviderInfo ProviderInfo = ProviderInfoEntry.Value;
                FString Email = ProviderInfo.ProviderEmail;
            }
        } else if (Result.NeedExit()) {
            // TODO: Implement app exit functionality
            // e.g.) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        }
    }));
    
    AuthV4::signInWithStoredPlayerId(playerId, useAutoSignIn, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {
        if (result.isSuccess()) {
            // Authentication succeeded
            // playerInfo: Authenticated user information
    
            // Example: Retrieve email information
            for(auto it = playerInfo.providerInfoData.begin(); it != playerInfo.providerInfoData.end(); ++it) {
                hive::ProviderInfo providerInfo = it->second;
                if(!providerInfo.providerEmail.empty()) {
                    std::string email = providerInfo.providerEmail;
                    break;
                }
            }
        }
        else if (result.needExit()) {
            // TODO: Implement app exit functionality
            // Cocos2d-x engine users
            // e.g.) exit(0);
            // Unreal engine users
            // e.g.) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        }
    });
    
        AuthV4.signInWithStoredPlayerId(playerId, useAutoSignInState, object : AuthV4.AuthV4SignInListener {
                override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
                        if (result.isSuccess) {
                                // Authentication succeeded
                                // playerInfo: Authenticated user information
    
                                // Example: Retrieve email information
                                playerInfo?.let {
                                        for ((key, value) in it.providerInfoData) {
                                                var providerInfo: AuthV4.ProviderInfo = value
                                                if(providerInfo.providerEmail.isNotEmpty()) {
                                                        val email = providerInfo.providerEmail
                                                        break
                                                }
                                        }
                                }
                        } else if (result.needExit()) {
                                // TODO: Implement app exit functionality
                                // e.g.) exitProcess(
    

4. Delete Saved Account (PlayerID)

Deletes a saved account (PlayerID) through the multi-account login management feature while logged out.

In the displayed PlayerID list UI, the user can choose to delete the saved account (PlayerID) instead of logging in.

Figure 4. Example of deleting a saved account through Multi-account Login Management


An example code for calling the API to delete a saved account (PlayerID) is as follows.

AuthV4.deleteStoredPlayerId(playerId, (ResultAPI result)=>{
    if (result.isSuccess()) {
        // API call succeeded
    }
});
FHiveAuthV4::DeleteStoredPlayerId(playerId, FHiveAuthV4OnDeleteStoredPlayerIdDelegate::CreateLambda([this](const FHiveResultAPI& Result) {
    if (Result.IsSuccess()) {
        // API call succeeded
    } 
}));
AuthV4::deleteStoredPlayerId(playerId, [=](ResultAPI const & result) {
    if (result.isSuccess()) {
        // API call succeeded
    }
});
AuthV4.deleteStoredPlayerId(playerId, object : AuthV4.AuthV4DeletePlayerIdListener {
    override fun onAuthV4DeletePlayerId(result: ResultAPI) {
        if (result.isSuccess) {
            // API call succeeded
        }
    }
})
AuthV4.deleteStoredPlayerId(playerId, new AuthV4.AuthV4DeletePlayerIdListener() {
    @Override
    public void onAuthV4DeletePlayerId(ResultAPI result) {
        if (result.isSuccess()) {
            // API call succeeded
        }
    }
});
AuthV4Interface.deleteStoredPlayerId(playerId) { (result) in
    if result.isSuccess() {
        // API call succeeded
    }
}
[HIVEAuthV4 deleteStoredPlayerId: playerId handler:^(HIVEResultAPI *result) {
    if([result isSuccess]){
        // API call succeeded
    }
}];


Error Codes

This section explains the error codes sent by the SDK during the implementation of the multi-account login management feature.

Error Code Message Description
NEED_INITIALIZE AuthV4NotInitialized If the SDK setup has not been completed (AuthV4.setup)
IN_PROGRESS AuthV4InProgress If the API is called again before receiving a response
INVALID_SESSION AuthV4SessionNotExist If the requested PlayerID does not exist in the list
INVALID_SESSION AuthV4SessionProcessingFail Failed to save/delete session

 


Implementation Notes

Please note the following when implementing the multi-account login management feature.

  • API Continuous Call Limitation

    If you repeatedly call the API before receiving a response after an interface call, you may not receive a normal response. Be sure to wait for a response before calling the next API.

  • Caution with Login Session Storage Method

    Login sessions are stored based on the logged-in account, not the device. Therefore, depending on the implementation method, login information may be exposed to other users using the same device. Be cautious when using the login session storage feature for services that require security.

  • Prohibition of Multi-account Login Management Feature Usage for COPPA Applicability (ageGateU13 = true)

    The multi-account login management feature allows for fast login by saving account information. However, for those subject to COPPA, restrict the multi-account login management feature so that account information is not saved and session-based login is not provided.

    The SDK does not automatically restrict the use of the multi-account login management feature, so separate 대응이 필요합니다. Additionally, COPPA restricts the collection, use, and sharing of personal information for users under 13 years of age, so it is recommended to avoid storing related data, including session information.