iOS
This article guides you through setting up Discord as an identity provider, enabling your iOS game to access Player Network authentication services.
As authentication through the Discord App has been deprecated in the Discord SDK, using Discord App for authentication may encounter problems in the future. To ensure that Discord authentication remains reliable, we recommend using WebView instead for web authentication for Discord. For more details, see the configuration DISCORD_LOGIN_USING_WEB.
From Spring 2024, developers will have to clearly describe data use in the privacy manifest, showing how required reason APIs will be utilized in apps that are updated or uploaded to Apple App Store Connect. For more information, see Upcoming third-party SDK requirements.
As Discord has yet to publish their privacy manifest, such content is not available in the Player Network SDK privacy manifest, see iOS 17 Privacy Manifest for more information.
Prerequisites
1. Set up the Discord app on the Discord Developer Platform
For multi-store packages, a separate REDIRECT_URL_SCHEME
is required. One app ID supports 10 Redirect URLs (about 4 multi-store packages). Apply for more app IDs if games require more than 4 multi-store packages. To use multiple app IDs, games need to configure multiple app IDs in INTLConfig.ini
and register multiple Discord apps on the Player Network Console.
1. Create a Discord app
Before creating the Discord app, register an account on the Discord official website and complete the account authentication (by email) according to the prompts.
Go to the Discord Developer Platform.
On the first login, users might have to verify that they are not bots. You may complete it after the email verification.On the top right corner of the Applications page, click New Application.
In the app creation popup, enter the application name and click Create.
On the General Information page, view the APPLICATION ID.
Users must configure the app ID in the INTLConfig.ini file.
2. Configure the app
The authentication feature on Player Network for Discord requires the identify
scope from Discord. The social feature on Player Network requires the relationships.read
and activities.write
scope from Discord. The For more information, see OAuth2 Scopes.
Go to the Discord Developer Platform.
On the Applications page, click the app to configure.
Click OAuth2 in the left side navigation bar and go to OAuth2 > General.
Under Redirects, fill in the below redirect URLs, which are used to receive callbacks after Discord web authorization. Click Add Another to add more empty fields if required:
- https://common-web.intlgame.com/jssdk/discordlogincallback.html
- https://test-common-web.intlgame.com/jssdk/discordlogincallback.html
noteTo use the Discord app instead of Discord web for authorization on mobile devices, a redirect URL for the Discord app is required for callback after authorization. Redirect URL rules:
- Use all lowercase.
- The scheme should start with "intl".
- The URL should include the host and path.
Example: intlmoba://auth/callback
noteFor INTLConfig.ini's
DISCORD_UNIVERSAL_LINK_IOS
- Configure a universal link to open the game.
- Add the link to Redirect URL
noteFor multi-store packages:
A separate
REDIRECT_URL_SCHEME
is required to support multi-store packages. One app ID supports 10 Redirect URLs (about 4 multi-store packages). Apply for more app IDs if games require more than 4 multi-store packages. To use multiple app IDs, games need to configure multiple app IDs inINTLConfig.ini
and register multiple Discord app on Player Network.Click Rich Presence in the left side navigation bar and go to the Rich Presence Art Assets page.
Click Add Image(s) to configure the image resources of the app.
infoAll image resources used in the app must be configured on this page, including cover photos for friend invitations.
- 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 Discord as an authentication method for your project on Player Network Console.
Step 1: Configure the SDK for Discord login
Discord SDK is only compatible with iOS SDK 11 and later.
Unreal Engine should first find the bundle resource path in the Plugins/INTLSDK/Source/INTLCore/INTLCore.Build.cs
file:
AdditionalBundleResources.Add(new BundleResource(Path.Combine(ModuleDirectory, "Libs/iOS/INTLCore/INTLSDK.bundle"), bShouldLog: false));
1. Load required permissions and plugins
- Unity
- Unreal Engine
XUPorter automatically adds dependency libraries and source code files when exporting Xcode projects to facilitate packaging.
Player Network SDK optimizes the original version of XUPorter which avoids the conflict between the XUPorter solution and the Player Network SDK solution.
- The
INTLSDKEditor
namespace is added to avoid naming conflicts when other components also use XUPorter. - The search path to mods files is changed. In this way, Player Network SDK XUPorter only searches for mods files in the
INTLSDK/
directory, rather than repeatedly adding the configurations of other components. - The lifecycle is added into
UnityAppController.mm
.
Player Network SDK XUPorter solution
INTL{Plugin}Kit.projmods
is Player Network SDK Info.plist
confiugration file. Player Network SDK reads the INTL{Plugin}Kit.projmods
file in the INTLSDK/Editor/XUPorter/Mods
directory and adds the imported bundle, framework, and other dependency packages in Xcode.
As each INTL{Plugin}Kit.projmods
file corresponds to a plugin, games need to update each file according to game requirements for the plugin, and replace the {placeholder} text with values from the INTLConfig.ini configuration file.
For example, update INTLDiscordKit.projmods
for required configurations.
"Info.plist":{
"LSApplicationQueriesSchemes":
[
"com.hammerandchisel.discord"
],
"NSAppTransportSecurity":
{
"NSAllowsArbitraryLoads":true
},
"CFBundleURLTypes" :
[
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Discord",
"CFBundleURLSchemes":["{INTL_DISCORD_REDIRECT_SCHEME}"]
}
]
}
Add Player Network SDK related configurations in the configuration file, modify the Discord configuration according to your game.
- Player Network SDK 1.18 or later
- Before Player Network SDK 1.18
Open and modify the file that corresponds to your SDK version:
- For V1.24 or later:
INTLSDK/Source/INTLDiscord/Libs/iOS/INTLDiscord_UPL.xml
- For V1.18 to V1.23:
INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLDiscord.plist
<key>CFBundleURLSchemes</key>
<array>
<string>{YOUR_DISCORD_REDIRECT_SCHEME}</string>
</array>
Go to Unreal Engine > Settings > Project Settings > Platforms > iOS > Extra Plist Data to modify the configuration and add SDK in the Plist file.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>Discord</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{YOUR_DISCORD_REDIRECT_SCHEME}</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>com.hammerandchisel.discord</string>
</array>
iOS Usage Description
According to the requirements for iOS permissions, when requesting sensitive permissions, fill in usage description, when the system pops up and prompts the user for this information.
- Unity
- Unreal Engine
In,
Assets/INTLSDK/Editor/XUPorter/Mods~/INTLCoreKit.projmods
, the following permissions have been upgraded:"NSPhotoLibraryUsageDescription"
"NSCameraUsageDescription"
"NSLocationWhenInUseUsageDescription"
"NSPhotoLibraryAddUsageDescription"
"NSMicrophoneUsageDescription"When integrating, users can modify the contents according to their needs.
In
Assets/INTLSDK/Editor/XUPorter/Mods~/INTLADTrackingKit.projmods
, the following permission has been upgraded:"NSUserTrackingUsageDescription"
cautionWhen integrating, users can modify the contents according to their needs, and confirm with the legal team if the contents are compliant. If there are no modifications, replace INTLSample with the game name.
In
Plugins/INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLCore.plist
, the following permissions have been upgraded:<key>NSPhotoLibraryUsageDescription</key>
<key>NSCameraUsageDescription</key>
<key>NSLocationWhenInUseUsageDescription</key>
<key>NSPhotoLibraryAddUsageDescription</key>
<key>NSMicrophoneUsageDescription</key>In
Plugins/INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLADTracking.plist
, the following permission has been upgraded:<key>NSUserTrackingUsageDescription</key>
cautionWhen integrating, users can modify the contents according to their needs, and confirm with the legal team if the contents are compliant. If there are no modifications, replace INTLSample with the game name.
2. Adapt to the Swift SDK
There will be mixed editing issue for iOS Swift and Objective-C if the module uses the Swift SDK. Take the following steps to create a bridge layer to align the class names of the two programming languages:
Create a new file and choose the Swift File type.
Specify the file name as needed and make sure that the extension is .swift. Then click on Create.
Click Create Bridging Header.
noteMake sure to select Create Bridging Header. Otherwise, Xcode will not create a bridge layer file.
Make sure two files are created in the Xcode project (one is the .swift file created in step 2, and the other is the automatically created project_name-Bridging-Header.h file).
infoThe file content remains unchanged.
- Unity
- Unreal Engine
Not applicable.
The iOS swift module cannot be directly added to Unreal Engine, and the engine configuration must be modified.
When using Xcode 12 or a later version, you must add the following code in
/Plugins/INTLSDK/Source/INTLCore/INTLCore.Build.cs
.PublicSystemLibraryPaths.Add("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos");
PublicSystemLibraryPaths.Add("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos");noteBecause Player Network SDK has already set the following configuration in advance, you can skip this step when using other Xcode versions.
Because the following error will be reported when compiling Unreal Engine with Swift lib of Xcode 12 and later versions, this step is only required to solve the problem when using Xcode 12 and later versions.
Modify the local Unreal Engine source code.
Add the following code in the
private void AppendProjectBuildConfiguration(StringBuilder Content, string ConfigName, string ConfigGuid)
function of /Your_UE_Installation_Path/Engine/Source/Programs/UnrealBuildTool/ProjectFiles/Xcode/XcodeProject.cs.// Enable Swift
Content.Append("\t\t\t\tCLANG_ENABLE_MODULES = YES;" + ProjectFileGenerator.NewLine);
Content.Append("\t\t\t\tSWIFT_VERSION = 5.0;" + ProjectFileGenerator.NewLine);
Content.Append("\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\";" + ProjectFileGenerator.NewLine);
if (ConfigName == "Debug")
{
Content.Append("\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";" + ProjectFileGenerator.NewLine);
}
Content.Append("\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;" + ProjectFileGenerator.NewLine);
Content.Append("\t\t\t\tEMBEDDED_CONTENT_CONTAINS_SWIFT = YES;" + ProjectFileGenerator.NewLine);Add the following code in the
string GetLinkArguments_Global(LinkEnvironment LinkEnvironment)
function of /Your_UE_Installation_Path/Engine/Source/Programs/UnrealBuildTool/Platform/IOS/IOSToolChain.cs.
- Before XCode 12
- XCode 12 and later
// enable swift support
Result += " -rpath \"/usr/lib/swift\"";
Result += " -rpath \"@executable_path/Frameworks\"";
// /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/swift/
String swiftLibPath = String.Format(" -L {0}Platforms/{1}.platform/Developer/SDKs/{1}{2}.sdk/usr/lib/swift",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName : Settings.Value.SimulatorPlatformName, Settings.Value.IOSSDKVersion);
Result += swiftLibPath;
Log.TraceInformation("Add swift lib path : {0}", swiftLibPath);
///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
swiftLibPath = String.Format(" -L {0}Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/{1}",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName.ToLower() : Settings.Value.SimulatorPlatformName.ToLower());
Result += swiftLibPath;
Log.TraceInformation("Add swift lib path : {0}", swiftLibPath);
///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos
swiftLibPath = String.Format(" -L {0}Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/{1}",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName.ToLower() : Settings.Value.SimulatorPlatformName.ToLower());
Result += swiftLibPath;
// This line of code must be prepended (see the sample image below for the position of the prepended code)
// enable swift support, make sure '/usr/lib/swift' goes before '@executable_path/Frameworks'
Result += " -rpath \"/usr/lib/swift\"";
// enable swift support
Result += " -rpath \"@executable_path/Frameworks\"";
// /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/swift/
String swiftLibPath = String.Format(" -L {0}Platforms/{1}.platform/Developer/SDKs/{1}{2}.sdk/usr/lib/swift",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName : Settings.Value.SimulatorPlatformName, Settings.Value.IOSSDKVersion);
Result += swiftLibPath;
Log.TraceInformation("Add swift lib path : {0}", swiftLibPath);
///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos
swiftLibPath = String.Format(" -L {0}Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/{1}",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName.ToLower() : Settings.Value.SimulatorPlatformName.ToLower());
Result += swiftLibPath;
Log.TraceInformation("Add swift lib path : {0}", swiftLibPath);
///Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos
swiftLibPath = String.Format(" -L {0}Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/{1}",
Settings.Value.XcodeDeveloperDir, bIsDevice? Settings.Value.DevicePlatformName.ToLower() : Settings.Value.SimulatorPlatformName.ToLower());
Result += swiftLibPath;
// Xcode 12 adds the swiftCompatibility51 library, so you need to add the following code
if (Settings.Value.IOSSDKVersionFloat >= 14.0f)
{
Result += String.Format(" -lswiftCompatibility51");
}
- Open the solutions and recompile
/Users/intl/UE4/UE_4.25/Engine/Source/Programs/UnrealBuildTool/UnrealBuildTool.sln
.
3. Complete Player Network SDK configurations
Open the project's INTLConfig.ini:
[Discord channel configuration]
DISCORD_APP_ID = {INTL_DISCORD_APP_ID}
DISCORD_REDIRECT_URL = {INTL_DISCORD_REDIRECT_URL}
DISCORD_UNIVERSAL_LINK_IOS = {INTL_DISCORD_UNIVERSAL_LINK_IOS}
- Replace
{INTL_DISCORD_APP_ID}
with the applying Discord App ID. - Replace
{INTL_DISCORD_REDIRECT_URL}
with the Redirect URL configured for you on the developer platform. - Replace
{INTL_DISCORD_UNIVERSAL_LINK_IOS}
with the Redirect universal link configurated on the developer platform.
- Add Discord to the
Info.plist
file.
- Unity
- Unreal Engine
When using Unity to export Xcode projects, configure the .projmods file.
Player Network SDK has already written these configurations into the INTLCoreKit.projmods
file, so the game team simply need to check the configurations.
{
"group": "INTL",
"Info.plist":{
"CFBundleURLTypes" :
[
{
"CFBundleTypeRole":"Editor",
"CFBundleURLName":"Discord",
"CFBundleURLSchemes":["{INTL_DISCORD_REDIRECT_SCHEME}"]
}
]
},
}
- Player Network SDK 1.18 or later
- Before Player Network SDK 1.18
Open and modify the file that corresponds to your SDK version:
- For V1.24 or later:
INTLSDK/Source/INTLDiscord/Libs/iOS/INTLDiscord_UPL.xml
- For V1.18 to V1.23:
INTLSDK/Source/INTLConfig/Configs/iOS/Plist/INTLDiscord.plist
<key>CFBundleURLSchemes</key>
<array>
<string>{INTL_DISCORD_REDIRECT_SCHEME}</string>
</array>
Go to Unreal Engine > Settings > Project Settings > Platforms > iOS > Extra Plist Data to modify the configuration and add SDK in the PLIST file.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Discord</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{INTL_DISCORD_REDIRECT_SCHEME}</string>
</array>
</dict>
</array>
Replace {INTL_DISCORD_REDIRECT_SCHEME}
with the scheme configured in the Redirect URL.
For example, if the Redirect URL configured on the Discord Developer Platform is intlsample://auth/callback
:
{INTL_DISCORD_REDIRECT_SCHEME}
= intlsample
Step 2: Add Discord login
Discord does not require an app installation before login. If the app has already been installed, open the app to log in. Otherwise, the web login interface will open.
Discord login permission
requires identify
to be added. If the Discord sharing function is required, relationships.read,activities.write
should be added.
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.- Unity
- Unreal Engine
INTLAPI.Login(INTLChannel.Discord, "identify", "");
INTLAPI.Login(INTLChannel.Discord, "identify,relationships.read,activities.write", ""); //Friend functionsUINTLSDKAPI::Login(EINTLLoginChannel::Discord, "identify", "");
UINTLSDKAPI::Login(EINTLLoginChannel::Discord, "identify,relationships.read,activities.write", ""); //Friend functionsSync 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.