Log in/Log out
Login
Login in authentication is composed of the following steps.
Authv4Helper executes some part of login process, and indicates the proper page based on the response.
Refer to the following notes to implement the login function.
Automatic Login and Implicit Login
Automatic Login
Implicit Login is a method that the user does not select a means of login, but logs in the Apple Game Center account on iOS or the Google Play Games account on Android automatically. Implement the Implicit Login to be executed after failure of Automatic Login.
Offline Mode
Hive SDK v4 23.1.0 and higher offers an automatic login feature (AuthV4.signIn
using ProviderType.AUTO
, or AuthV4.Helper.signIn
) even when the user’s device is not connected to the network. To use the offline mode, follow the instructions below:
- It is necessary that the app was run in online mode at least once, resulting in a successful explicit, implicit, guest, or custom login, and subsequently,
playerId
andplayerToken
were issued.From the perspective of the app developers, there must have been at least one successful execution of
AuthV4.Helper.signIn
,AuthV4.showSignIn
, orAuthV4.signInWithAuthKey
in an online state, with the reception ofplayerId
andplayerToken
via callback. From the user’s perspective, they must have successfully logged into the app at least once while their device was connected to the network. However, if the user’s account was suspended or restricted during their last login attempt in online mode, they will not be able to log in in offline mode. - Activate the offline mode in the Hive console under App Center > Manage Project > Game Details > Hive Product Settings.
Automatic Login on Windows
Windows environment supports automatic login, and it can be enabled/disabled in the Hive console App Center. Note that the Windows automatic login works differently from the automatic login for the mobile environment. The differences are:
- In the mobile environment, a user is kept logged in by automatic login, but in Windows, it is kept only when a user enabled “keep me logged in” checkbox (displayed below the IdP list in login UI). In other circumstances, the login status does not continue.
- In the mobile environment, when you execute AuthV4Helper.Connect and convert to another account, the newly logged in account also is kept logged in by the automatic login, but in Windows, it is not.
Implicit Login
AuthV4.Helper.signIn
tries Automatic Login by using the authentication token key of PlayerID. If the token key generated from previous login does not exist, the game automatically sign in Apple Game Center for iOS, and Google Play Games for Android. If failed to sign in, it displays a proper login page in accordance with the response.
Followings are sample codes to execute Automatic Login.
API Reference: hive.AuthV4.Helper.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Attempt Hive SDK login (signIn) AuthV4.Helper.signIn (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) { if (result.isSuccess()) { // log-in succeed } else if (result.needExit()) { // TODO: implement app exit functionality // Example) Application.Quit(); } else { switch(result.code) { case ResultAPI.Code.AuthV4ConflictPlayer: // account conflict break; case ResultAPI.Code.AuthV4HelperImplifiedLoginFail: // implicit login failed // ex) AuthV4.showSignIn(...); break; default: // other exceptions break; } } }); |
API Reference: Auth4::signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Attempt Hive SDK login (signIn) AuthV4::Helper::signIn([=](ResultAPI const & result, std::shared_ptr playerInfo) { if (result.isSuccess()) { // log-in succeed } else if (result.needExit()) { // TODO: implement app exit functionality // Users of the Cocos2d-x engine // ex) exit(0); // Unreal engine users // Example) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false); } else { switch(result.code) { case ResultAPI::AuthV4ConflictPlayer: // account conflict break; case ResultAPI::AuthV4HelperImplifiedLoginFail: // implicit login failed // ex) AuthV4.showSignIn(...); break; default: break; } } }); |
API Reference: com.hive.Auth4.Helper.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Attempt Hive SDK login (signIn) AuthV4.Helper.signIn(object : AuthV4.Helper.AuthV4HelperListener { override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) { if (result.isSuccess) { // log-in succeed } else if (result.needExit()) { // TODO: implement app exit functionality // ex) exitProcess(0) } else { when (result.code) { ResultAPI.Code.AuthV4ConflictPlayer -> { // account conflict } ResultAPI.Code.AuthV4HelperImplifiedLoginFail -> { // implicit login failed // ex) AuthV4.showSignIn(...); } else -> { // other exceptions } } } } }) |
API Reference: com.hive.Auth4.Helper.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Attempt Hive SDK login (signIn) AuthV4.Helper.signIn(new AuthV4.Helper.AuthV4HelperListener() { @Override public void onAuthV4Helper(ResultAPI result, AuthV4.PlayerInfo playerInfo) { if (result.isSuccess()) { // log-in succeed } else if (result.needExit()) { // TODO: implement app exit functionality // ex) System.exit(0); } else { switch(result.code) { case AuthV4ConflictPlayer: // account conflict break; case AuthV4HelperImplifiedLoginFail: // implicit login failed // ex) AuthV4.showSignIn(...); break; default: // other exceptions break; } } } }); |
API Reference: HIVEAuth4:signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Attempt Hive SDK login (signIn) AuthV4Interface.helper().signIn() { (result, playerInfo) in if result.isSuccess() { // log-in succeed } else if result.needExit() { // TODO: implement app exit functionality // ex) exit(0) } else { switch result.getCode() { case .authV4ConflictPlayer: // account conflict case .authV4HelperImplifiedLoginFail: // implicit login failed // ex) AuthV4Interface.showSignIn() { (result, playerInfo) // // do something... // } default: // other exceptions break } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// Attempt Hive SDK login (signIn) [[HIVEAuthV4 helper] signIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) { if (result. isSuccess) { // log-in succeed } else if (result. needExit) { // TODO: implement app exit functionality // ex) exit(0); } else { switch(result.code) { case kAuthV4ConflictPlayer: // account conflict break; case kAuthV4HelperImplifiedLoginFail: // implicit login failed // ex) [HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) { // // do something... // }]; break; default: // other exceptions break; } } }]; |
Implicit Login Behavior: Mobile
On mobile platforms (Hive SDK Unity Android, etc., Android/iOS), implicit login (AuthV4.Helper.signIn
) causes an account conflict and prompts the user with a dialog asking whether to log in with the last logged-in account after the initial login.
Implicit Login Behavior: PC
On PC platforms (Hive SDK Unity Windows, etc., Windows), implicit login (AuthV4.Helper.signIn
) automatically logs in with the last logged-in account after the initial login, without causing any account conflict.
Explicit Login
Explicit Login means a process that user chooses an IdP to proceed with authentication. If a player failed to execute both Automatic Login and Implicit Login, implement the game to make the player go to the game title screen and execute Explicit Login when tapping the title.
Explicit Login is composed of the UI provided by Hive SDK or the UI customized in games with the IdP lists returned after initializing Hive SDK used in authentication. If you customize the UI, see Advanced >; Customizing Explicit Login UI.
Hive Platform controls and provides IdP lists in accordance with the policy of each country. For example, Google Play Games, Facebook, and Guest Login are not available in China.
An example screen of Explicit Login
IdP selection UI provided by Hive SDK
When implementing the function with the UI provided by Hive SDK
To implement Explicit Login with the UI provided by Hive SDK, you can display the IdP list UI by calling showSignIn()
method.
API Reference: hive.AuthV4.showSignIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Request Hive SDK AuthV4 Authentication UI AuthV4.showSignIn((ResultAPI result, AuthV4.PlayerInfo playerInfo)=>{ if (result.isSuccess()) { // authentication success // playerInfo : Authenticated user information // the example of getting 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 the termination of the app // Example) Application.Quit(); } }); |
API Reference: AuthV4::showSignIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// Request Hive SDK AuthV4 Authentication UI AuthV4::showSignIn([=](ResultAPI const & result, PlayerInfo const & playerInfo) { if (result.isSuccess()) { // authentication success // playerInfo: Authenticated user information // the example of getting 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 the termination of the app // Users of the Cocos2d-x engine // ex) exit(0); // Unreal engine users // Example) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false); } }); |
API Reference: com.hive.AuthV4.showSignIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Request Hive SDK AuthV4 Authentication UI AuthV4.showSignIn(object : AuthV4.AuthV4SignInListener { override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) { if (result.isSuccess) { // authentication Success // playerInfo: Authenticated user information // the example of getting 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 the termination of the app // ex) exitProcess(0) } } }) |
API Reference: com.hive.AuthV4.showSignIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Request Hive SDK AuthV4 Authentication UI AuthV4.showSignIn(new AuthV4.AuthV4SignInListener() { @Override public void onAuthV4SignIn(ResultAPI result, AuthV4.PlayerInfo playerInfo) { if (result.isSuccess()) { // authentication success // playerInfo: Authenticated user information // the example of getting email information if(playerInfo != null) { for (Map.Entry<AuthV4.ProviderType, AuthV4.ProviderInfo> entry : playerInfo.getProviderInfoData().entrySet()) { AuthV4.ProviderInfo providerInfo = entry.getValue(); if (providerInfo.getProviderEmail() != "") { String email = providerInfo.getProviderEmail(); break; } } } } else if (result.needExit()) { // TODO: Implement the termination of the app // Example) System.exit(0); } } }); |
API Reference: HIVEAuthV4:showSignIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
var email = String() // Request Hive SDK AuthV4 Authentication UI AuthV4Interface.showSignIn { (result, playerInfo) in if result.isSuccess() { // authentication success // playerInfo: Authenticated user information // the example of getting email information if let playerInfo = playerInfo { // find providerInfo that the providerEmail exists (the provider of the current sign-in) for key in playerInfo.providerInfoData.keys { if let providerInfo = playerInfo.providerInfoData[key], providerInfo.providerEmail.count > 0 { // providerEmail != "" email = providerInfo.providerEmail break } } } } else if result.needExit() { // TODO: Implement the termination of the app // ex) exit(0) } } |
API Reference: HIVEAuthV4:showSignIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
__block NSString* email = @""; // Request Hive SDK AuthV4 Authentication UI [HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) { if([result isSuccess]){ // authentication success // playerInfo: Authenticated user information // the example of getting email information if(playerInfo != nil) { // find providerInfo that the providerEmail exists (the provider of the current sign-in) for (NSString* key in playerInfo.providerInfoData.allKeys) { HIVEProviderInfo* providerInfo = playerInfo.providerInfoData[key]; if (providerInfo != nil && providerInfo.providerEmail.length > 0) { // providerEmail != "" email = providerInfo.providerEmail; break; } } } } else if ([result needExit]) { // TODO: Implement the termination of the app // Example) exit(0); } }]; |
Customizing Explicit Login UI
You can implement a customized UI for an explicit login by using providerTypeList
, which is returned as a callback handler of AuthV4.setup()
method called for Hive SDK initialization, or AuthV4.Helper.getIDPList()
method called after Hive SDK initialization. Customizing explicit login UI is used when you want to display the login screen according to the game UI, or to display the linking option with a specific IdP only. After designing the UI, call signIn()
method with the desired ProviderType depending on the user’s action.
- Example UI which exposes only Facebook-synced button on sign-in page
Followings are sample codes for the case that user selects Google sign-in on the customized explicit login UI.
API Reference: hive.AuthV4.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 |
using hive; AuthV4.signIn(AuthV4.ProviderType.GOOGLE, (ResultAPI result, AuthV4.PlayerInfo playerInfo) => { if (result.isSuccess()) { // call successful // playerInfo: Authenticated user information. // Example of email information search for ProviderType.GOOGLE Dictionary<AuthV4.ProviderType, AuthV4.ProviderInfo> providerInfoData = playerInfo.providerInfoData; AuthV4.ProviderInfo providerInfo = providerInfoData[AuthV4.ProviderType.GOOGLE]; string email = providerInfo.providerEmail; } }); |
API Reference: Auth4::signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <HIVE_SDK_Plugin/HIVE_CPP.h> AuthV4::signIn(ProviderType::GOOGLE, [=](ResultAPI const & result, PlayerInfo const & playerInfo) { if (result.isSuccess()) { // call successful // playerInfo: Authenticated user information. // Example of email information search for ProviderType::GOOGLE map<ProviderType, ProviderInfo> providerInfoData = playerInfo.providerInfoData; ProviderInfo providerInfo = providerInfoData[ProviderType::GOOGLE]; string email = providerInfo.providerEmail; } }); |
API Reference: AuthV4.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import com.hive.AuthV4 import com.hive.ResultAPI AuthV4.signIn(AuthV4.ProviderType.GOOGLE, object : AuthV4.AuthV4SignInListener { override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) { if (result.isSuccess) { // call successful // playerInfo: Authenticated user information // Example of email information search for ProviderType.GOOGLE if (playerInfo != null) { val providerInfoData = playerInfo.providerInfoData val providerInfo = providerInfoData[AuthV4.ProviderType.GOOGLE] if (providerInfo != null) { val email = providerInfo.providerEmail } } } } }) |
API Reference: com.hive.Auth4.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import com.hive.AuthV4; import com.hive.ResultAPI; AuthV4.INSTANCE.signIn(AuthV4.ProviderType.GOOGLE, (result, playerInfo) -> { if (result.isSuccess()) { // call successful // playerInfo: Authenticated user information // Example of email information search for ProviderType.GOOGLE if (playerInfo != null) { HashMap<AuthV4.ProviderType, AuthV4.ProviderInfo> providerInfoData = playerInfo.getProviderInfoData(); AuthV4.ProviderInfo providerInfo = providerInfoData.get(AuthV4.ProviderType.GOOGLE); if (providerInfo != null) { String email = providerInfo.getProviderEmail(); } } } }); |
API Reference: AuthV4Interface.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import HIVEService AuthV4Interface.signIn(.Google) { result, playerInfo in if result.isSuccess() { // 호출 성공 // playerInfo: 인증된 사용자 정보. // .Google의 이메일 정보 조회 예시 if let playerInfo = playerInfo, let providerInfo = playerInfo.providerInfoData["GOOGLE"] { let email = providerInfo.providerEmail } } } |
API Reference: HIVEAuth4:signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#import <HIVEService/HIVEService-Swift.h> [HIVEAuthV4 signIn:HIVEProviderTypeGoogle handler:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) { if ([result isSuccess]){ // call successful // playerInfo: Authenticated user information. // Example of email information search by HIVEProviderTypeGoogle if(playerInfo != nil) { HIVEProviderInfo *providerInfo = playerInfo.providerInfoData[@"GOOGLE"]; if(providerInfo != nil){ NSString *email = providerInfo.providerEmail; } } } }]; |
Checking Logged-in IdP Account on Device
Automatic Login is available to sign in with the token key of registered playerId
, and so as Explicit Login with various IdPs. In the case of these two cases, the IdP account (DevicePlayer) logged-in on user device may mismatch with the IdP of PlayerID, which user logged in. Considering the use of achievement or leaderboard, notification page is provided for users to match two accounts.
Followings are sample codes to confirm the IdP information.
API Reference: AuthV4 .Helper.syncAccount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using hive; AuthV4.ProviderType providerType = AuthV4.ProviderType.GOOGLE; AuthV4.Helper.syncAccount (providerType, delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) { switch (result.code) { case ResultAPI.Code.Success: // normal break; case ResultAPI.Code.AuthV4ConflictPlayer: // account conflict // ex) When using Hive UI // AuthV4.Helper.showConflict(...); //or // ex) When implementing GameUI // AuthV4.Helper.resolverConflict(...);// When selecting the current user // AuthV4.Helper.switchAccount(...);// When selecting user switch break; default: // other exception situations break; } }); |
API Reference: AuthV4 ::Helper::syncAccount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <HIVE_SDK_Plugin/HIVE_CPP.h> using namespace std; using namespace hive; ProviderType providerType = ProviderType::GOOGLE; AuthV4::Helper::syncAccount(providerType, [=](ResultAPI const & result, shared_ptr<PlayerInfo> playerInfo) { switch (result.code) { case ResultAPI::Success: // normal break; case ResultAPI::AuthV4ConflictPlayer: // account conflict // ex) When using Hive UI // AuthV4::Helper::showConflict(...); //or // ex) When implementing GameUI // AuthV4::Helper::resolverConflict(...);// When selecting the current user // AuthV4::Helper::switchAccount(...);// When switching user is selected break; default: // other exception situations break; } }); |
API Reference: AuthV4.Helper.syncAccount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import com.hive.AuthV4 import com.hive.ResultAPI val providerType = AuthV4.ProviderType.GOOGLE AuthV4.Helper.syncAccount(providerType, object : AuthV4.Helper.AuthV4HelperListener { override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) { when (result.code) { ResultAPI.Code.Success -> { // normal } ResultAPI.Code.AuthV4ConflictPlayer -> { // account conflict // ex) When using Hive UI // AuthV4.Helper.showConflict(...); //or // ex) When implementing GameUI // AuthV4.Helper.resolverConflict(...);// When selecting the current user // AuthV4.Helper.switchAccount(...);// When selecting user switch } else -> { // other exception situations } } } }) |
API Reference: AuthV4 .Helper.INSTANCE.syncAccount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import com.hive.AuthV4; import com.hive.ResultAPI; AuthV4.ProviderType providerType = AuthV4.ProviderType.GOOGLE; AuthV4.Helper.INSTANCE.syncAccount(providerType, (result, playerInfo) -> { switch (result.getCode()) { case Success: // normal break; case AuthV4ConflictPlayer: // account conflict // ex) When using Hive UI // AuthV4.Helper.INSTANCE.showConflict(...); //or // ex) When implementing GameUI // AuthV4.Helper.INSTANCE.resolverConflict(...);// When selecting the current user // AuthV4.Helper.INSTANCE.switchAccount(...);// When selecting user switch break; default: // other exception situations break; } }); |
API Reference: AuthV4Interface.helper().syncAccount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import HIVEService let providerType: ProviderType = .Google AuthV4Interface.helper().syncAccount(providerType) { result, playerInfo in switch result.getCode() { case .success: // normal case .authV4ConflictPlayer: // account conflict // ex) When using Hive UI // AuthV4Interface.helper().showConflict(...); //or // ex) When implementing GameUI // AuthV4Interface.helper().resolverConflict(...);// When selecting the current user // AuthV4Interface.helper().switchAccount(...);// When selecting user switch default: // other exception situations break } } |
API Reference: [ HIVEAuthV4 helper] syncAccount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#import <HIVEService/HIVEService-Swift.h> HIVEProviderType providerType = HIVEProviderTypeGoogle [[HIVEAuthV4 helper] syncAccount: providerType handler: ^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) { switch ([result getCode]) { case HIVEResultAPICodeSuccess: // normal break; case HIVEResultAPICodeAuthV4ConflictPlayer: // account conflict // ex) When using Hive UI // [[HIVEAuthV4 helper] showConflict: ...]; //or // ex) When implementing GameUI // [[HIVEAuthV4 helper] resolverConflict:...];// When selecting the current user // [[HIVEAuthV4 helper] switchAccount:...];// When selecting user switch break; default: // other exception situations break; } }]; |
Guest Login
Hive supports Guest Login to allow users to use the game as a guest without selecting an IdP. You can implement this function for user to choose guest from the Explicit Login UI provided by Hive SDK, or from the customized UI by game. The Windows environment does not support guest sign-in.
Make sure to comply with the following policy when logging in as a guest.
Guest Login Policy
-
- Build a game available for both guest users and Hive members equally.
Most features of Hive platform are available for guest users. So, implement your games the same for both guest users and IdP-connected users. For example, guest users are also able to purchase items and pay in the game. - Do not allow guest users to sign out.
If a user logs in as a guest and then logs out, the user can no longer sign in with the same PlayerID. Therefore, do not provide a logout button to prevent users from signing out when their state is the guest. - Guest Login Policy with Chinese IP.
If users access the game with Chinese IP, only authorized members can charge game money or purchase items (started from May 1, 2017). Therefore, IdP lists available with Chinese IP do not include Guest Login.
- Build a game available for both guest users and Hive members equally.
Implement signIn()
method with the parameter, ProviderType.GUEST
to execute Guest Login.
Followings are sample codes to execute Guest Login.
API Reference: hive.AuthV4.signIn
1 2 3 4 5 6 7 8 |
using hive; AuthV4.signIn(AuthV4.ProviderType.GUEST, (ResultAPI result, AuthV4.PlayerInfo playerInfo) => { if (result.isSuccess()) { // Authentication successful // playerInfo: Authenticated user information } }); |
API Reference: Auth4::signIn
1 2 3 4 5 6 7 8 9 10 |
#include <HIVE_SDK_Plugin/HIVE_CPP.h> using namespace std; using namespace hive; AuthV4::signIn(ProviderType::GUEST, [=](ResultAPI const & result, PlayerInfo const & playerInfo) { if (result.isSuccess()) { // Authentication successful // playerInfo: Authenticated user information } }); |
API Reference: AuthV4.signIn
1 2 3 4 5 6 7 8 9 10 11 |
import com.hive.AuthV4 import com.hive.ResultAPI AuthV4.signIn(AuthV4.ProviderType.GUEST, object : AuthV4.AuthV4SignInListener { override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) { if (result.isSuccess) { // Authentication successful // playerInfo: Authenticated user information } } }) |
API Reference: com.hive.Auth4.signIn
1 2 3 4 5 6 7 8 9 |
import com.hive.AuthV4; import com.hive.ResultAPI; AuthV4.INSTANCE.signIn(AuthV4.ProviderType.GUEST, (result, playerInfo) -> { if (result.isSuccess()) { // Authentication successful // playerInfo: Authenticated user information } }); |
API Reference: AuthV4Interface.signIn
1 2 3 4 5 6 7 8 |
import HIVEService AuthV4Interface.signIn(.Guest) { result, playerInfo in if result.isSuccess() { // Authentication successful // playerInfo: Authenticated user information } } |
API Reference: HIVEAuth4:signIn
1 2 3 4 5 6 7 8 |
#import <HIVEService/HIVEService-Swift.h> [HIVEAuthV4 signIn: HIVEProviderTypeGuest handler: ^(ResultAPI *result, HIVEPlayerInfo *playerInfo) { if ([result isSuccess]) { // Authentication successful // playerInfo: Authenticated user information } }]; |
Custom Login
Custom Login is a feature of implementing login with an external IdP that Hive SDK does not support. Follow the Auth V4 Custom Authentication guide to create an authKey that uses for calling the Custom Login API.
You can confirm the user’s information who signed in with custom login by accessing customProviderInfoData
with the PlayerInfo object which is passed as a callback of the Custom Login API. ProviderType(enum) of customProviderInfoData
are all set as CUSTOM
, and can be identified in detail with ProviderName(String).
- The information of IdP that implemented custom login in-game is not include as a result of calling
setup()
andshowSignIn()
method of AuthV4 class.- If you get the playerId and playerToken after first executing custom login, the Result API of
authV4SessionExist(code)
will be passed as a callback when you re-call the custom login API. In this case, implementsignIn()
method with the parameter,ProviderType.Auto
to execute automatic login with a previous login account.- The
connect()
anddisconnect()
method of AuthV4 class currently do not support additional connection and disconnection of a custom login IdP.- The additional sync or disconnection of IdPs for custom login are supported with the
connectWithAuthKey()
anddisconnectWithName()
methods.
Followings are sample codes to implement the custom login.
API Reference: hive.AuthV4.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// Twitter login implemented directly in the game Game.Login("CUSTOM_TWITTER", (string authKey) => { AuthV4.signInWithAuthKey(authKey, (ResultAPI result, PlayerInfo playerInfo) => { if (result. isSuccess()) { Dictionary<string, ProviderInfo> customProviderInfoData = playerInfo.customProviderInfoData; ProviderInfo providerInfo = customProviderInfoData["CUSTOM_TWITTER"]; // Check the following user linkage information providerInfo. providerType; // ProviderType.CUSTOM, customs have a fixed type, so you need to distinguish them by providerName providerInfo. providerName; // "CUSTOM_TWITTER" providerInfo. providerUserId; // user id used for self-implemented twitter login return; } else if (result.code == ResultAPI.Code.AuthV4SessionExist) { // If you need to log in automatically after having already issued playerId and playerToken // TODO: AuthV4.signIn(ProviderType.AUTO, (ResultAPI _result, PlayerInfo playerInfo) => {}); } else if (result.code == ResultAPI.Code.AuthV4NotInitialized) { // TODO: need to initialize SDK } else if (result.code == ResultAPI.Code.AuthV4InvalidParam) { // TODO: Need to check whether the passed authKey value is NULL or empty } else if (result. needExit()) { // TODO: implement app exit functionality // Example) Application.Quit(); } }); }); |
API Reference: Auth4::signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
using namespace std; using namespace hive; // Twitter login implemented directly in the game Game::Login("CUSTOM_TWITTER", [=](string authKey) { AuthV4::signInWithAuthKey(authKey, [=](ResultAPI const & result, PlayerInfo const & playerInfo) { if (result. isSuccess()) { map<string, ProviderInfo> customProviderInfoData = playerInfo.customProviderInfoData; ProviderInfo providerInfo = customProviderInfoData["CUSTOM_TWITTER"]; // Check the following user linkage information providerInfo. providerType; // ProviderType::CUSTOM, customs have a fixed type, so you need to distinguish them by providerName providerInfo. providerName; // "CUSTOM_TWITTER" providerInfo. providerUserId; // user id used for self-implemented twitter login return; } else if (result.code == ResultAPI::Code::AuthV4SessionExist) { // If you need to log in automatically after having already issued playerId and playerToken // TODO: AuthV4.signIn(ProviderType::AUTO, [=](ResultAPI const & _result, PlayerInfo const & playerInfo) {}); } else if (result.code == ResultAPI::Code::AuthV4NotInitialized) { // TODO: need to initialize SDK } else if (result.code == ResultAPI::Code::AuthV4InvalidParam) { // TODO: Need to check whether the passed authKey value is NULL or empty } else if (result. needExit()) { // TODO: implement app exit functionality // Users of the Cocos2d-x engine // ex) exit(0); // Unreal engine users // Example) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false); } }); }); |
API Reference: com.hive.Auth4.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// Twitter login implemented directly in the game Game.Login("CUSTOM_TWITTER") { authKey: String -> AuthV4.signInWithAuthKey(authKey, object : AuthV4.AuthV4SignInListener { override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) { if (result.isSuccess && playerInfo != null) { playerInfo.customProviderInfoData["CUSTOM_TWITTER"]?.let { providerInfo -> providerInfo.providerType // ProviderType.CUSTOM, since custom types are fixed, it is necessary to distinguish them by providerName providerInfo.providerName // "CUSTOM_TWITTER" providerInfo.providerUserId // user id used for Twitter login } } else if (result. needExit()) { // TODO: implement app exit functionality // ex) exitProcess(0) } else if (result.code == ResultAPI.Code.AuthV4SessionExist) { // If you need to log in automatically after having already issued playerId and playerToken // TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener) } else if (result.code == ResultAPI.Code.AuthV4NotInitialized) { // TODO: need to initialize SDK } else if (result.code == ResultAPI.Code.AuthV4InvalidParam) { // TODO: Need to check whether the passed authKey value is NULL or empty } } }) } |
API Reference: com.hive.Auth4.signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// Twitter login implemented directly in the game Game.Login("CUSTOM_TWITTER") { authKey: String -> AuthV4.INSTANCE.signInWithAuthKey(authKey, new AuthV4.AuthV4SignInListener() { @Override public void onAuthV4SignIn(@NonNull ResultAPI result, @Nullable AuthV4.PlayerInfo playerInfo) { if(result.isSuccess() && playerInfo != null) { HashMap<String, AuthV4.ProviderInfo> customProviderInfoData = playerInfo.getCustomProviderInfoData(); AuthV4.ProviderInfo providerInfo = customProviderInfoData.get("CUSTOM_TWITTER"); // Check the following user linkage information if (providerInfo != null){ providerInfo.getProviderType(); // AuthV4.ProviderType.CUSTOM, since custom types are fixed, it is necessary to differentiate by providerName providerInfo.getProviderName(); // "CUSTOM_TWITTER" providerInfo.getProviderUserId(); // user id used for self-implemented twitter login } } else if (result. needExit()) { // TODO: implement app exit functionality // ex) System.exit(0); } else if (result.getCode() == ResultAPI.Code.AuthV4SessionExist) { // If you need to log in automatically after having already issued playerId and playerToken // TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener) } else if (result.getCode() == ResultAPI.Code.AuthV4NotInitialized) { // TODO: need to initialize SDK } else if (result.getCode() == ResultAPI.Code.AuthV4InvalidParam) { // TODO: Need to check whether the passed authKey value is NULL or empty } } }); } |
API Reference: HIVEAuth4:signIn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// Twitter login implemented directly in the game Game.login("CUSTOM_TWITTER") { (authKey) in AuthV4Interface.signInWithAuthKey(authKey) { (result, playerInfo) in if result. isSuccess() { let customProviderInfoData = playerInfo?.customProviderInfoData; let providerInfo = customProviderInfoData?["CUSTOM_TWITTER"] // Check the following user linkage information providerInfo?.providerType; // AuthProviderType, since custom types are fixed, it is necessary to distinguish them by providerName providerInfo?.providerName; // "CUSTOM_TWITTER" providerInfo?.providerUserId; // user id used for self-implemented twitter login return } else if result.getCode() == .authV4SessionExist { // If you need to log in automatically after having already issued playerId and playerToken // TODO: AuthV4Interface.signIn(.auto) { (result, playerInfo) in } } else if result.getCode() == .authV4NotInitialized { // TODO: need to initialize SDK } else if result.getCode() == .authV4invalidParam { // TODO: Need to check whether the passed authKey value is nil or empty } else if result. needExit() { // TODO: Implement app shutdown functionality. // ex) exit(0) } } } |
API Reference: HIVEAuth4:signIn
Username
Due to issues such as the US COPPA, when accessing from the United States or its territories and logging in with an IdP, you must enter your username to enable authentication for additional user identification.
For reference, the countries included in the US territory are American Samoa (AS), Guam (GU), Northern Mariana Islands (MP), Puerto Rico (PR), US Minor Archipelago (UM), and US Virgin Islands (VI).
The username input screen for user identification is as follows.
- The username input screen is used only for user identification, so it is exposed only once when first linking with the IdP and is not exposed other than that.
- When logging in as a guest, the username input screen is not displayed.
Verifying Authentication Token Key
Game server can validate the authentication token key by using the returned token, playerId, and DID information after successful login. Hive Authentication allows multi-device logins and duplicate connections.
Unless your game allows duplicate access with one ID, game server exposes a notice on the logged-in device and terminates the game. Then, the secondly logged-in device keeps its login state for game play. If user keeps duplicate connections without terminating the game from one device, the game play may not be recorded concisely. Therefore, make sure to manage the token key that has been verified or implement the function by managing the session key of the game itself using the token key to process this function.
Implement the function by referring to Hive Server API >; Verifying Authentication v4 Token.
Obtaining Hive TalkPlus Login Token
To log in to Hive TalkPlus, you need the login token obtained by calling AuthV4.getHiveTalkPlusLoginToken API after login (signIn()
) via Auth v4 interface. (See Hive TalkPlus Login Guide)
1 2 3 4 5 6 |
AuthV4.getHiveTalkPlusLoginToken((ResultAPI result, String loginToken) => { if (result.isSuccess()) { // SUCCESS // TODO: Check the loginToken you received and execute HiveTalkPlus login } }); |
1 2 3 4 5 6 7 8 |
// Kotlin AuthV4.getHiveTalkPlusLoginToken(object : AuthV4.AuthV4GetHiveTalkPlusLoginTokenListener { override fun onAuthV4GetHiveTalkPlusLoginToken(resultApi: ResultAPI, loginToken: String?) { if (resultApi.isSuccess) { // SUCCESS } } } |
1 2 3 4 5 6 7 8 9 |
// Java com.hive.AuthV4.INSTANCE.getHiveTalkPlusLoginToken(new com.hive.AuthV4.AuthV4GetHiveTalkPlusLoginTokenListener() { @Override public void onAuthV4GetHiveTalkPlusLoginToken(@NotNull ResultAPI result, @Nullable String loginToken) { if (result.isSuccess()) { // SUCCESS } } }); |
1 2 3 4 5 6 |
// Swift AuthV4Interface.getHiveTalkPlusLoginToken { result, loginToken in if (result.isSuccess()) { // SUCCESS } } |
1 2 3 4 5 6 |
// Objective-c [HIVEAuthV4 getHiveTalkplusLoginToken:^(HIVEResultAPI* result, NSString* loginToken) { if ([result isSuccess]) { // SUCCESS } }]; |
Detecting Changes in IdP Account in the Background
Users can change their Apple Game Center or Google Play game accounts through device settings while playing the game. If you need to check whether the IdP account is matched with the account connected with the current PlayerID, implement setProviderChangedListener()
after initializing Hive SDK. If you implement the API, user can receive an event which notifies the changes in IdP account linked on the user device when game resumes.
iOS works when the account in Apple Game Center is changed, and Android works when the account in Google Play Games is changed. And The response will be delivered only if the currently logged in PlayerID is connected with the relevant IdP. If you receive the change event in IdP account, configure the UI which allows the user to choose whether to use the IdP account logged in on the device. If the user selects the IdP account logged in on the device, call signOut
to sign out and proceed with Implicit Login.
Followings are sample codes to receive events that IdP account setting on device is changed when the player resumes the game.
API Reference: hive.AuthV4.setProviderChangedListener
1 2 3 4 5 6 7 8 9 10 11 |
using hive; AuthV4.setProviderChangedListener((ResultAPI result, AuthV4.ProviderInfo providerInfo) => { if (!result.isSuccess()) { return; } if (providerInfo != null && providerInfo.providerType == AuthV4.ProviderType.APPLE) { // Change GameCenter user information } }); |
API Reference: AuthV4::setProviderChangedListener
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <HIVE_SDK_Plugin/HIVE_CPP.h> using namespace std; using namespace hive; AuthV4::setProviderChangedListener([=](ResultAPI const & result, ProviderInfo const & providerInfo) { if (!result.isSuccess()) { return; } if (providerInfo != null && providerInfo.providerType == ProviderType::GOOGLE) { // Change Google Play Game Service account } }); |
API Reference: AuthV4.setProviderChangedListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import com.hive.AuthV4 import com.hive.ResultAPI AuthV4.setProviderChangedListener(object : AuthV4.AuthV4CheckProviderListener { override fun onDeviceProviderInfo(result: ResultAPI, providerInfo: AuthV4.ProviderInfo?) { if (!result.isSuccess) { return } if (providerInfo != null && providerInfo.providerType == AuthV4.ProviderType.GOOGLE) { // Change Google Play Game Service account } } }) |
API reference : : com.hive.authv4.SetproviderChangeDlistener
1 2 3 4 5 6 7 8 9 10 11 12 |
import com.hive.AuthV4; import com.hive.ResultAPI; AuthV4.INSTANCE.setProviderChangedListener((result, providerInfo) -> { if (!result.isSuccess()) { return; } if (providerInfo != null && providerInfo.getProviderType() == AuthV4.ProviderType.GOOGLE) { // Change Google Play Game Service account } }); |
API Reference: AuthV4Interface .setProviderChangedListener
1 2 3 4 5 6 7 8 9 10 11 |
import HIVEService AuthV4Interface.setProviderChangedListener() { result, providerInfo in if !result.isSuccess() { return } if let providerInfo = providerInfo, providerInfo.providerType == .Apple { // Change GameCenter user information } } |
API Reference: HIVEAuthV4:setProviderChangedListener
1 2 3 4 5 6 7 8 9 10 |
#import <HIVEService/HIVEService-Swift.h> [HIVEAuthV4 setProviderChangedListener: ^(HIVEResultAPI *result, ProviderInfo *providerInfo) { if (![result isSuccess]) { return; } if (providerInfo != nil && providerInfo.providerType == HIVEProviderTypeApple) { // Change GameCenter user information } }]; |
Initializing Game Data
Make sure not to implement logout when initializing game data. PlayerID is not deleted through the initialization, therefore, crash among accounts may occur. Let user play the game with the currently signed-in account, and do not implement the logout function before user clearly request by tapping the logout button.
Logout
If Hive login is performed, PlayerID and authentication token key are already issued. Logout is responsible for initializing the PlayerID and the token key. If logout is completed by implementing signOut()
, move to the game title and execute the Explicit Login when user taps the title.
Followings are sample codes to implement sign-out.
API Reference: hive.AuthV4.signOut
1 2 3 4 5 6 7 8 9 10 11 12 |
using hive; AuthV4.Helper.signOut (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) { switch(result.code) { case ResultAPI.Code.Success: // Logout successful break; default: // other exception situations break; } }); |
API Reference: AuthV4::signOut
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <HIVE_SDK_Plugin/HIVE_CPP.h> using namespace std; using namespace hive; AuthV4::Helper::signOut([=](ResultAPI const & result, shared_ptr playerInfo) { switch (result.code) { case ResultAPI::Success: // Logout successful break; default: // other exception situations break; } }); |
API Reference: AuthV4.Helper.signOut
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import com.hive.AuthV4 import com.hive.ResultAPI AuthV4.Helper.signOut(object : AuthV4.Helper.AuthV4HelperListener { override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) { when (result.code) { ResultAPI.Code.Success -> { // Logout successful } else -> { // other exception situations } } } }) |
API Reference: AuthV4.Helper.INSTANCE.signOut
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import com.hive.AuthV4; import com.hive.ResultAPI; AuthV4.Helper.INSTANCE.signOut((result, playerInfo) -> { switch (result.getCode()) { case Success: // Logout successful break; default: // other exception situations break; } }); |
API Reference: AuthV4Interface.helper().signOut()
1 2 3 4 5 6 7 8 9 10 |
import HIVEService AuthV4Interface.helper().signOut() { result, playerInfo in switch result.getCode() { case .success: // Logout successful default: // other exception situations break }} |
API Reference: [HIVEAuthV4 helper] signOut
1 2 3 4 5 6 7 8 9 10 11 12 |
#import <HIVEService/HIVEService-Swift.h> [[HIVEAuthV4 helper] signOut: ^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) { switch ([result getCode]) { case HIVEResultAPICodeSuccess: // log-in succeed break; default: // other exception situations break; } }]; |
Notification phrases for Game Center Sign-in Disabled
Language | Phrase |
---|---|
Korean | Apple Game Center 로그인이 취소되었습니다. Game Center 계정과 연동하려면 [설정 >; Game Center]에서 로그인한 후 다시 시도해주세요. |
English | Your login to the Game Center has been canceled. Log in at [Settings >; Game Center] to sync to the Game Center Account and try again. |
Japanese | Apple Game Center ログインがキャンセルされました。 Game Center アカウントと連動するには [設定 >; Game Center] にログインした後、再度お試しください。 |
Chinese (Simplified) | Apple Game Center已退出登录。 若想与Game Center账号同步,请在设备[设置 >; Game Center]中重新登录后再试。 |
Chinese (Traditional) | 登入Apple Game Center已取消。 若想連動Game Center帳號,請至[設定 >; Game Center]登入後,再試一次。 |
French | Ta connexion au Game Center a été annulée. Connecte-toi dans [Réglages >; Game Center] pour synchroniser ton compte Game Center et essaie de nouveau. |
German | Das Einloggen ins Apple Game Center wurde abgebrochen. Die Synchronisation mit dem Game Center-Konto läuft über [Einstellungen >; Game Center]. Logge dich ein und versuche es erneut. |
Russian | Ваш авторизация в Game Center была отменена. Авторизуйтесь в Game Center через [Настройки >; Game Center] и повторите попытку. |
Spanish | Tu Inicio de Sesión en Game Center ha sido cancelado. Inicia Sesión en [Configuración >; Game Center] para sincronizar a la Cuenta de Game Center, e inténtalo de nuevo. |
Portuguese | O seu login no Game Center foi cancelado. Faça o login em [Configurações >; Game Center] para sincronizar com a Conta do Game Center e tente novamente. |
Indonesian | Login ke Apple Game Center telah dibatalkan. Hubungkan akun Game Center dengan login di [Pengaturan >; Game Center] dan coba lagi. |
Malay | Log masuk ke Game Center anda telah dibatalkan. Log masuk di [Tetapan >; Game Center] untuk disegerakkan ke Akaun Game Center dan cuba lagi. |
Vietnamese | Đã hủy bỏ đăng nhập vào Apple Game Center. Đăng nhập tại [Cài đặt >; Game Center] để đồng bộ với tài khoản Game Center và thử lại. |
Thai | การล็อกอินเข้า Game Center ของคุณถูกยกเลิก ล็อกอินที่ [การตั้งค่า >; Game Center] เพื่อเชื่อมต่อบัญชี Game Center และโปรดลองอีกครั้ง |
Italian | L’accesso all’Apple Game Center è stato annullato. Fai log-in su [Impostazioni >; Game Center] per sincronizzare il tuo account con il Game Center e riprova. |
Turkish | Apple Oyun Merkezine girişiniz iptal edilmiştir. Oyun Merkezi Hesabına ulaşmak için [Ayarlar >; Oyun Merkezi]’nden giriş yapın ve tekrar deneyin. |
Arabic | تم إلغاء تسجيل الدخول إلى مركز الألعاب. سجل الدخول إلى [الإعدادات >; مركز الألعاب] للمزامنة مع حساب مركز الألعاب وحاول مرة أخرى. |