iOS
This article guides you through setting up Garena as an identity provider, enabling your iOS game to access Player Network authentication services.
Prerequisites
1. Set up the Garena app
Contact the Garena team to activate the app and get the app ID and other related information.
To use Garena's platform account linking, request Garena to enable APP_PLATFORM_BIND
.
- Create an account for Player Network Console.
- Create a new project for your game, or join an existing one.
- Download the SDK.
- Integrate the SDK.
- Add Garena as an authentication method for your project on Player Network Console.
Step 1: Configure the SDK
Open the INTLConfig.ini file.
INTLConfig.ini[INTL environment]
# WARNING: You should change this URL to the production environment when you release your game.
INTL_URL = https://intlsdk-new-test.iegg.garena.com
GAME_ID = {INTL_GAME_ID}
SDK_KEY = {INTL_SDK_KEY}
[INTL Log]
LOG_LEVEL = 1
LOG_CONSOLE_OUTPUT_ENABLE = 1
LOG_FILE_OUTPUT_ENABLE = 1
LOG_ENCRYPT_ENABLE = 0
LOG_COMPRESS_ENABLE = 0
[Garena Channel Configurations]
GARENA_APP_SDK_ASSIGN_ID = {INTL_GARENA_APP_SDK_ASSIGN_ID}
GARENA_APP_SDK_KEY = {INTL_APP_KEY}- Set the Player Network SDK authentication domain to
INTL_URL = https://intlsdk-new-test.iegg.garena.com
, contact the Garena team for more details and to obtain the URL for the production environment. - Replace
{INTL_GAME_ID}
and{INTL_SDK_KEY}
with theGAME_ID
andSDK_KEY
assigned by Player Network Console. - Set
LOG_LEVEL = 1
,LOG_CONSOLE_OUTPUT_ENABLE = 1
,LOG_FILE_OUTPUT_ENABLE = 1
,LOG_ENCRYPT_ENABLE = 0
, andLOG_COMPRESS_ENABLE = 0
to output console logs and log files without encrypting or compressing the output. - Replace
{INTL_GARENA_APP_SDK_ASSIGN_ID}
with the registered Garena App ID. - Replace
{INTL_APP_KEY}
with the registered Garena App Key.
- Set the Player Network SDK authentication domain to
Add Garena to the
Info.plist
file.notePlayer Network SDK V1.15 and later versions need to add the
AppTrackingTransparency.framework
. Versions earlier than Player Network SDK V1.15 do not need this addition.The Garena SDK has been updated in Player Network SDK V1.22, requiring
FacebookClientToken
to be added toInfo.plist
, replacing{INTL_FACEBOOK_CLIENT_TOKEN}
with the respective value. In addition, due to DataDome SDK being added to the Garena SDK,DataDomeKey
andDataDomeProxyEnabled
will have to be added toInfo.plist
.The sub-channel
Google
has been added for iOS Garena login in Player Network SDK V1.24, requiringGIDClientID
and a custom URL scheme based on the reversed client ID to be added toInfo.plist
, replacing{INTL_GOOGLE_CLIENT_KEY_IOS}
and{INTL_GOOGLE_REVERSED_CLIENT_ID}
with the respective values.For configurations regarding
DateDomeKey
andDataDomeProxyEnabled
, see Garena: Upgrade to 4.0.21.- Unity
- Unreal Engine
noteBefore exporting the Xcode project from Unity, Check the predefined values in
INTLGarenaKit.projmods
and replace{INTL_FACEBOOK_APP_ID}
,{INTL_FACEBOOK_CLIENT_TOKEN}
,{INTL_FACEBOOK_APP_NAME}
,{INTL_GARENA_APP_SDK_ASSIGN_ID}
,{INTL_GOOGLE_CLIENT_KEY_IOS}
, and{INTL_GOOGLE_REVERSED_CLIENT_ID}
with the respective values of the app.INTLGarenaKit.projmods{
"group": "INTL",
"libs": [
"libz.tbd",
"libc++.tbd"
],
"frameworks": [
"Accelerate.framework",
"Accounts.framework",
"AdSupport.framework",
"AuthenticationServices.framework:weak",
"AVFoundation.framework",
"CoreGraphics.framework",
"CoreMedia.framework",
"CoreServices.framework",
"CoreTelephony.framework",
"Foundation.framework",
"JavaScriptCore.framework",
"LocalAuthentication.framework",
"MapKit.framework",
"MobileCoreServices.framework",
"Photos.framework",
"ReplayKit.framework",
"SafariServices.framework",
"Security.framework",
"Social.framework",
"StoreKit.framework",
"SystemConfiguration.framework",
"UIKit.framework",
"WebKit.framework",
"AppTrackingTransparency.framework:optional"
],
"embed_binaries": [
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/DataDomeSDK.framework"
],
"files": [
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/DataDomeSDK.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/AppAuth.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/FBAEMKit.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/FBSDKCoreKit_Basics.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/FBSDKCoreKit.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/FBSDKGamingServicesKit.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/FBSDKLoginKit.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/FBSDKShareKit.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKDebugSystem.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKFriends.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKLoginFacebook.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKLoginGarena.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKLoginGoogle.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKLoginSwift.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKNotification.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKParentalControl.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKPayment.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKSecurityVerifier.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKShareFacebook.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKShareGarena.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKShareLine.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKShareSwift.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GarenaMSDKUtilities.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GoogleSignIn.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GTMAppAuth.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/GTMSessionFetcher.framework",
"../../../Plugins/iOS/INTLSDK/INTLGarena/ThirdSDK/Sentry.framework"
],
"folders": ["../../../Plugins/iOS/INTLSDK"],
"excludes": [
"^.*.meta$",
"^.*.mdown$",
"^.*.pdf$"
],
"headerpaths":[],
"build_settings":
{
"OTHER_LDFLAGS": ["-ObjC"],
"ENABLE_BITCODE": "FALSE",
"SWIFT_VERSION":"5.0",
"LIBRARY_SEARCH_PATHS":["$(SDKROOT)/usr/lib/swift", "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME}"],
"LD_RUNPATH_SEARCH_PATHS":["/usr/lib/swift", "$(inherited)", "@executable_path/Frameworks"]
},
"system_capabilities": {
"com.apple.Push":"TRUE"
},
"Info.plist":{
"LSApplicationQueriesSchemes":
[
"fb-messenger-share-api",
"fbapi",
"fbauth2",
"fbshareextension",
"garenagc",
"gop{INTL_GARENA_APP_SDK_ASSIGN_ID}",
"facebook-reels",
"line",
"lineauth2"
],
"NSAppTransportSecurity":
{
"NSAllowsArbitraryLoads":true
},
"CFBundleURLTypes" :
[
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Garena",
"CFBundleURLSchemes":["fb{INTL_FACEBOOK_APP_ID}"]
},
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Garena",
"CFBundleURLSchemes":["gop{INTL_GARENA_APP_SDK_ASSIGN_ID}"]
},
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Google",
"CFBundleURLSchemes":["{INTL_GOOGLE_REVERSED_CLIENT_ID}"]
}
],
"FacebookAppID":"{INTL_FACEBOOK_APP_ID}",
"FacebookClientToken":"{INTL_FACEBOOK_CLIENT_TOKEN}",
"CFBundleName":"{INTL_FACEBOOK_APP_NAME}",
"GOPAppID":"{INTL_GARENA_APP_SDK_ASSIGN_ID}",
"DataDomeKey":"DEFAULT_KEY",
"DataDomeProxyEnabled":false,
"GIDClientID":{INTL_GOOGLE_CLIENT_KEY_IOS}
}Add the SDK configurations to the PLIST file.
- Player Network SDK 1.24 and later
- Before Player Network SDK 1.24
Open
INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLGarena.plist
to modify.<key>LSApplicationQueriesSchemes</key>
<array>
<string>fb-messenger-share-api</string>
<string>fbapi</string>
<string>facebook-reels</string>
<string>fbauth2</string>
<string>fbshareextension</string>
<string>garenagc</string>
<string>gop{INTL_GARENA_APP_SDK_ASSIGN_ID}</string>
<string>line</string>
<string>lineauth2</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Garena</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>gop{INTL_GARENA_APP_SDK_ASSIGN_ID}</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>Garena</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fb{INTL_FACEBOOK_APP_ID}</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>Google</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{INTL_GOOGLE_REVERSED_CLIENT_ID}</string>
</array>
</dict>
</array>
<key>GOPAppID</key>
<string>{INTL_GARENA_APP_SDK_ASSIGN_ID}</string>
<key>FacebookAppID</key>
<string>{INTL_FACEBOOK_APP_ID}</string>
<key>FacebookClientToken</key>
<string>{INTL_FACEBOOK_CLIENT_TOKEN}</string>
<key>CFBundleName</key>
<string>{INTL_FACEBOOK_APP_NAME}</string>
<key>DataDomeKey</key>
<string>DEFAULT_KEY</string>
<key>DataDomeProxyEnabled</key>
<false/>
<key>GIDClientID</key>
<string>{INTL_GOOGLE_CLIENT_KEY_IOS}</string><key>LSApplicationQueriesSchemes</key>
<array>
<string>fb-messenger-share-api</string>
<string>fbapi</string>
<string>fb-messenger-api</string>
<string>fbauth2</string>
<string>fbshareextension</string>
<string>garenagc</string>
<string>gop{INTL_GARENA_APP_SDK_ASSIGN_ID}</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Garena</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>gop{INTL_GARENA_APP_SDK_ASSIGN_ID}</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>Garena</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fb{INTL_FACEBOOK_APP_ID}</string>
</array>
</dict>
</array>
<key>GOPAppID</key>
<string>{INTL_GARENA_APP_SDK_ASSIGN_ID}</string>
<key>FacebookAppID</key>
<string>{INTL_FACEBOOK_APP_ID}</string>
<key>FacebookClientToken</key>
<string>{INTL_FACEBOOK_CLIENT_TOKEN}</string>
<key>CFBundleName</key>
<string>{INTL_FACEBOOK_APP_NAME}</string>
<key>DataDomeKey</key>
<string>DEFAULT_KEY</string>
<key>DataDomeProxyEnabled</key>
<false/>Add Capability in Xcode.
Step 2: Add Garena login
Add an observer to handle authentication callbacks.
- Unity
- Unreal Engine
// Add callbacks
public void AddAuthObserver()
{
INTLAPI.AddAuthResultObserver(OnAuthResultEvent);
}
// Remove callbacks
public void RemoveAuthObserver()
{
INTLAPI.RemoveAuthResultObserver(OnAuthResultEvent);
}
// Process the INTLAuthResult callback
public void OnAuthResultEvent(INTLAuthResult ret)
{
Debug.Log($"MethodID: {ret.MethodId}");
string methodTag = "";
if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_LOGIN)
{
methodTag = "Login";
}
else if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_BIND)
{
methodTag = "Bind";
}
else if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_AUTOLOGIN)
{
methodTag = "AutoLogin";
}
else if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_QUERY_USER_INFO)
{
methodTag = "QueryUserInfo";
}
else if (authRet.MethodId == (int)INTLMethodID.INTL_AUTH_GET_AUTH_RESULT)
{
methodTag = "GetAuthResult";
}
}C++ Event Handling (above v1.15)
//configure callback
FINTLAuthEvent authEvent;
authEvent.AddUObject(this, &OnAuthResult_Implementation);
UINTLSDKAPI::SetAuthResultObserver(authEvent);
// Remove callbacks
UINTLSDKAPI::GetAuthResultObserver().Clear();void OnAuthResult_Implementation(FINTLAuthResult ret)
{
UE_LOG(LogTemp, Warning, TEXT("MethodID: %d"), ret.MethodId);
}Unreal Event Handling
void OnAuthResult_Implementation(FINTLAuthResult ret)
{
UE_LOG(LogTemp, Warning, TEXT("MethodID: %d"), ret.MethodId);
}Call the
AutoLogin
method.- Unity
- Unreal Engine
INTLAPI.AutoLogin();
UINTLSDKAPI::AutoLogin();
Call the
Login
method to ask for user input if auto-login fails.noteCurrently, the Player Network SDK supported Garena sub-channels on iOS include
Guest
,Garena
,Facebook
,Apple
andGoogle
. To check the current sub-channel used to log in, check the sub-channel name returned in theExtraJson
field ofAuthResult
. For example,{"subChannel":"Facebook"}"
.Logging into the Facebook sub-channel of Garena:
- Unity
- Unreal Engine
INTLAPI.Login(INTLChannel.Garena, "", "{\"subChannel\":\"Facebook\"}");
UINTLSDKAPI::Login(EINTLLoginChannel::kChannelGarena, "", "{\"subChannel\":\"Facebook\"}");
- If app is installed, open the app to log in, otherwise open a webpage to log in.
- Garena Login
permission
parameter differs from the rest of the channels. Users need to pass in the numeric in string format. For example, "2" or "4". The permissions are defined as follows:
Sync client authentication state with the game's backend and wait for the final authentication result.
Step 3: Test the login function
Search for the keyword "AuthResult" in the Player Network SDK logs to verify if the correct channel name and OpenID are returned. If they are, it indicates a successful configuration and the login function has been added successfully.
Link
Due to Garena's restrictions:
- If the Facebook login has been used before, it cannot be used as the sub-channel for the Garena login. Otherwise, error code
1013
is returned. - After linking the Garena account successfully, you cannot link it again.
When calling the Bind
interface, the App of the sub-channel (or a webpage) is opened to perform login authentication. Player Network SDK will link the account of the sub-channel with the guest account after a successful authentication.
- Unity
- Unreal Engine
// Log in as guest
INTLAPI.Login(INTLChannel.Garena, "", "{\"subChannel\":\"Guest\"}");
// Bind Logic
INTLAPI.Bind(INTLChannel.Garena, "", "{\"subChannel\":\"Facebook\"}");
// Log in as guest
UINTLSDKAPI::Login(EINTLLoginChannel::kChannelGarena, "", "{\"subChannel\":\"Guest\"}");
// Bind Logic
UINTLSDKAPI::Bind(EINTLLoginChannel::kChannelGarena, "", "{\"subChannel\":\"Facebook\"}");
If linking a guest account to Garena fails, the game must call the guest login of Garena again.
After calling the Bind
interface, the session of Garena SDK is set to a new linked channel (with guest login state) no matter the result of the linking. If calling the Bind
interface again, the linking will fail because of session validation failure. Therefore, it is recommended to call the guest login again to return to the normal guest login state.
If you have trouble logging in through Garena, see Garena FAQs.