Implement external authentication provider linking
To implement external authentication provider linking with the recipe code, complete the following steps in order.
Before you begin, complete the common prerequisites.
Overall flow
What you configure and call in each step is as follows.
| Step | Category | What you do |
|---|---|---|
| 1 | Hive Console | Register credentials for the login method to link |
| 2 | Hive Axyl SDK | Install the authentication module and the Add-on for each login method |
| 3 | Hive Axyl SDK | Initialize the SDK and register modules |
| 4 | Recipe code | Copy the recipe folders |
| 5 | Recipe code, App code | Prepare the credential source |
| 6 | Recipe code | Call linking |
| 7 | App code | Handle linking results |
| 8 | App code | Clean up guest credentials |
| 9 | App code | Verify the behavior |
Do not run other account operations after linking starts
The recipe compares the session access token from before it displays the authentication screen with the one from just before it requests linking. If a login, logout, or account switch happens in between and the value changes, the recipe stops without sending the linking request. After the user selects the link button, block the entry points for other account operations.
1. Configure the Hive Console
- Hive Console Configure or check this in the Hive Console.
Register the credentials of the login method to link in the Hive Console. If you request linking with a login method that is not registered, the request is rejected with ProviderConfigNotFound or ProviderClientInfoNotExists.
For each login method, you must first get credentials from the external console. Check the issuance procedure and the Hive Console registration procedure below.
- Google: Register credentials in the Hive Console
- Apple: Register credentials in the Hive Console
- Google Play Games: Register credentials in the Hive Console
- Steam: Register credentials in the Hive Console
- X: Register credentials in the Hive Console
If the app already provides login with that login method, this step is already done. Linking uses the same settings as login.
2. Install SDK modules
-
Hive Axyl SDK Call the Hive Axyl SDK from the app.
Detailed procedure: Install modules
Install the authentication module and the Add-on for the login method to link in your Unity project. An Add-on is a Hive Axyl SDK extension package that displays the authentication screen of an external authentication provider, and the credential source you prepare in step 5 calls this Add-on. Without the Add-on package, the credential source is excluded from compilation, so you cannot use it in your app code.
| Package | Needed | Role |
|---|---|---|
com.com2usplatform.hiveaxyl.core | Required | SDK initialization and login session management |
com.com2usplatform.hiveaxyl.auth | Required | Linking login methods |
Also install the Add-on that matches the login method to link.
- Google, Android native account selection screen:
com.com2usplatform.hiveaxyl.auth.addon.credentialmanager - Google, browser login:
com.com2usplatform.hiveaxyl.auth.addon.webauth - Apple, native login screen:
com.com2usplatform.hiveaxyl.auth.addon.apple - Apple, browser login:
com.com2usplatform.hiveaxyl.auth.addon.webauth - Google Play Games:
com.com2usplatform.hiveaxyl.auth.addon.gpg - Steam, Steamworks authentication ticket:
com.com2usplatform.hiveaxyl.auth.addon.steam - Steam, browser login:
com.com2usplatform.hiveaxyl.auth.addon.webauth - X:
com.com2usplatform.hiveaxyl.auth.addon.webauth
If you offer multiple login methods as linking targets, install all of the corresponding Add-ons.
3. Initialize the SDK
-
Hive Axyl SDK Call the Hive Axyl SDK from the app.
Detailed procedure: Initialize modules
Initialize the SDK once at the app's starting point, and register the authentication module and the Add-on. The recipe does not initialize the SDK, so if you call it without initializing the SDK, it fails with a FailedPrecondition error.
The following is example initialization code for an app that links an Apple account.
In {appId}, enter the App ID you created in the Hive Console.
Linking itself uses only IAuthService, which you register with AddAuth(). AddToken() is needed for the login that happens before linking, so it must also be registered. Check the Add-on registration method for each login method in Initialize the Add-on for each login method.
4. Install the recipe code
- Recipe code Copy the recipe code into your project.
A recipe is source code that you copy into your project instead of installing as a package. Copy the following items from the axyl-samples-unity repository to Assets/Recipes/ in your Unity project.
The items to copy and their roles are as follows.
- Recipes.asmdef: Common assembly definition for recipes
- AssemblyInfo.cs: Setting that exposes internal helpers to other recipe assemblies
- Helper/: Common code shared by multiple recipes
- ProviderLogin/: The
IProviderCredentialSourcecontract and credential handling code - LinkProvider/:
LinkProviderRecipeand result types - GuestLogin/:
GuestCredential, needed to perform step 8 when you provide guest login
Also copy the credential source folder for the login method to link.
- Google, Android native account selection screen: ProviderLogin.CredentialManager/
- Google, browser login: ProviderLogin.WebAuth/
- Apple, native login screen: ProviderLogin.Apple/
- Apple, browser login: ProviderLogin.WebAuth/
- Google Play Games: ProviderLogin.Gpg/
- Steam, Steamworks authentication ticket: ProviderLogin.Steam/
- Steam, browser login: ProviderLogin.WebAuth/
- X: ProviderLogin.WebAuth/
ProviderLogin.WebAuth/ uses Newtonsoft Json for JSON processing, so when you copy this folder, also install the com.unity.nuget.newtonsoft-json package.
The code does not compile if you copy only LinkProvider/
LinkProviderRecipe uses the credential handling code in ProviderLogin/ and the common code in Helper/. Copy Helper/, Recipes.asmdef, AssemblyInfo.cs, and ProviderLogin/ together.
To call recipes from your app code, add the following assemblies to references in your app's assembly definition. Because autoReferenced in the original Recipes.asmdef is false, your app assemblies do not reference it automatically.
Replace MyApp with the assembly name your app uses, and keep the existing settings and references. Unity assemblies do not pass references on transitively, so you must list here every assembly that your app code uses directly. Hive.Axyl.Core contains CoreConfig and HiveError, Hive.Axyl.Auth contains AddAuth() and AddToken(), and Hive.Axyl.Auth.Addon.Apple contains AddAppleSignIn(). If you link with another login method, replace the last two items with the Add-on assembly and the credential source assembly of that login method.
5. Prepare the credential source
-
Recipe code Call the recipe code from the app.
App code Implement this in the app.
To call LinkProviderAsync(), you first need the authentication result of the account to link, so you must prepare an IProviderCredentialSource object that displays the authentication screen and receives that value. This object is called a credential source. Linking uses the same credential source as login, so if the app already provides login with that login method, use the code that creates the source for login as is. The source class and the constructor arguments differ for each login method. Prepare the values to put in the arguments by following the login implementation procedures linked in the table below.
| Login method and authentication method | Source class | Constructor arguments |
|---|---|---|
| Google, Android native account selection screen | GoogleCredentialManagerCredentialSource | The Web application type OAuth client ID created in the Google Cloud Console. It is a different value from the Android type OAuth client ID. For how to prepare it, see the Android Credential Manager method in Google login. |
| Google, browser login | GoogleCredentialSource | WebAuthOptions. A value that holds the OAuth client ID, the request scope, and the redirect URI. For the values to put in it, see the Browser-based method in Google login. |
| Apple, native login screen | AppleCredentialSource | AppleSignInOptions. Pass it only when you request the email and name. For the values to put in it, see the Native method in Apple login. |
| Apple, browser login | AppleWebCredentialSource | WebAuthOptions and the app callback URL {appId}://oauth-callback. Pass the app callback URL only on Android. For the values to put in them, see the Browser-based method in Apple login. For how the authentication result returns to the app through the Hive Axyl relay URL and how to register the Android app callback scheme, see Hive Axyl relay URL. |
| Google Play Games | GooglePlayGamesCredentialSource | The Web application type OAuth client ID created in the Google Cloud Console. For how to prepare it, see Prepare the Play Games credential source in Google Play Games login. |
| Steam, Steamworks authentication ticket | SteamCredentialSource | The authentication ticket identity string and the Steam ID64. For how to prepare the two values, see the Steam client method in Steam login. |
| Steam, browser login | SteamOpenIdCredentialSource | returnTo, the URL that Steam sends the user back to, and the app callback URL {appId}://oauth-callback. returnTo is the Hive Axyl relay URL with the app callback URL and a random value appended, so create it anew with SteamRelayReturnTo.Build() every time you attempt linking. For how to create it and how to register the Android app callback scheme, see the Browser-based method in Steam login. |
| X | XCredentialSource | WebAuthOptions. For the values to put in it, see Prepare ClientId, DeviceKey, and OAuth settings in X login. |
The following example code creates a credential source for linking with the Apple native login screen. It does not request the email and name, so it omits AppleSignInOptions.
6. Call linking
- Recipe code Call the recipe code from the app.
Pass the prepared credential source to LinkProviderAsync(). The recipe displays the authentication screen to receive credentials and links those credentials to the currently logged-in account.
Also prepare a CancellationTokenSource so that you can stop waiting when the user closes the screen or cancels linking.
Call cancellation.Cancel() when the screen closes or the user chooses to cancel, and when the call finishes, clean up with cancellation.Dispose().
The recipe performs the following tasks internally.
| Category | Call | Where to check |
|---|---|---|
| Recipe code | Check the login session and compare the session access token before and after authentication | None |
| Add-on | Display the authentication screen with the credential source and obtain ProviderUserId and ProviderToken | Prepare the call parameter values |
| Hive Axyl SDK | For Google Play Games and for browser login with Google, Apple, and X, exchange the received authorization code for ProviderUserId and ProviderToken with ExchangeProviderTokenAsync(). In browser login, put the redirect URI used in the authorization request as is in RedirectUri, and for Google and X, put the PKCE value created by the recipe in CodeVerifier. For Google and X with tokenEndpoint specified, exchange directly with the external authentication provider instead of making this call | Exchange external authorization codes |
| Hive Axyl SDK | Link the login method to the current Player ID with LinkProviderAsync() | Link accounts and get linked login methods |
The detailed procedures in the table above are written for calling the Hive Axyl SDK methods directly. Do not reimplement in the app the steps that the recipe handles on your behalf, such as obtaining credentials. Refer to them only to check what each call sends and receives.
7. Handle linking results
-
App code Implement this in the app.
Detailed procedure: HiveError information
LinkProviderOutcome reports the linking result through Status. FailedStep is a diagnostic value, so do not use it as a basis for branching in the app's normal flow.
Status | Value to check | App handling |
|---|---|---|
Success | PlayerId, ProviderUserId | Refresh the linking list on the screen and run step 8. |
BusinessOutcome | IsConflict, BusinessOutcome, UnknownOutcomeCode | Branch by distinguishing conflicts from rejections, and treat unknown values as failures and record them. |
UserCanceled | None | The user closed the authentication screen, so return to the previous screen. |
Failure | Error.Code, Error.TraceId | Branch according to Error.Code and record the technical problem. |
The list of linked login methods comes only in the login response, so after linking, have the app add ProviderUserId to the on-screen list directly to refresh it.
When you record errors, also record FailedStep. It has four values, None, Resolve, AcquireCredential, and Link, and tells you at which step the process stopped.
7.1. Handle conflicts
A conflict does not mean that the request was wrong; it is the result of a clash with the current state of the account. The three results in which IsConflict is true return the same answer even if you retry, so do not present them as linking failures; show a screen that matches the state.
BusinessOutcome | Meaning | App handling |
|---|---|---|
ProviderOwnedByOther | The account to link is already linked to another Player ID | Ask the user to choose which account to use. For how to handle this, see Handle account linking conflicts. |
ProviderTypeAlreadyExists | A login method of the same kind is already linked to the current account | Guide the user to unlink the existing link and then link again. For how to unlink, see Unlink accounts. |
ProviderAlreadyConnected | The same account is already linked | The requested linking is already in place, so update the screen to the linking-completed state. |
Do not let the app resolve conflicts on its own
ProviderOwnedByOther means the user has two accounts, and ProviderTypeAlreadyExists means it has not been decided which of the two login methods of the same kind to keep. If the app chooses on the user's behalf and logs in with the other account or disconnects the existing link, the user loses the progress of one of the accounts.
7.2. Handle rejection reasons
BusinessOutcome values other than conflicts are the reasons why linking was rejected, and the settings, input, and account state the app must check differ for each value. The recipe combines the rejection reasons from the linking call and the external authorization code exchange call into one value and returns it, and of the names used in the detailed procedures, it changes only TerminateService to ServiceTerminated. Check the meaning of each value and how to respond below, according to the call that produced the rejection reason.
LinkProviderAsync(): Account linking response statusExchangeProviderTokenAsync(): External authorization code exchange response status. Called for Google Play Games and for browser login with Google, Apple, and X
If the recipe receives a result it cannot interpret, BusinessOutcome is Unrecognized. ProviderTokenExchangeNotSupported from the external authorization code exchange is also a result the recipe has not named, so it comes back as Unrecognized. In this case, distinguish the two cases with UnknownOutcomeCode. If it has a value, this SDK version does not know the result code the server sent; if it is empty, the SDK knows the result but the recipe has not named it. In either case, do not look it up in the two places above; record UnknownOutcomeCode and RawJson, treat the result as a failure, and do not display these two values to users.
7.3. Handle failures and cancellation
Failure is the result of linking not running to completion because of a technical problem, so identify the cause with Error.Code and handle it.
Error.Code | Meaning | App handling |
|---|---|---|
FailedPrecondition | The SDK is not initialized, or there is no login session. Also occurs on Android when you do not pass the app callback URL for Apple browser login | Check the initialization and login state and the constructor arguments in step 5, and then display the link button again. |
Aborted | The session access token changed while the authentication screen was open. This occurs even without an account change when the same user's access token is refreshed, so blocking the linking entry points cannot prevent it | The linking request was not sent, so do not present this as a failure. Check the currently logged-in account, and then start over from the beginning. |
Cancelled | The app stopped waiting with the cancellation token | Follow the cancellation handling below. |
Cancellation does not roll back linking in progress. If you canceled after the request reached the Hive Axyl authentication server, the linking may already be complete, so run linking again with the same login method to check the result. If ProviderAlreadyConnected comes back, the account is linked. In this case, follow the guidance in step 8 to clean up the guest credentials.
8. Clean up guest credentials
-
App code Implement this in the app.
Detailed procedure: Prepare the guest credential store
Once the first linking to a guest account is complete, the Hive Axyl authentication server invalidates the guest token of that Player ID. If you do not delete the saved guest credentials, the app attempts to log in with an unusable value on the next launch and is rejected with InvalidGuestToken.
The response has no value that tells you whether this is the first linking, so delete the saved guest credentials when linking succeeds. Before deleting them, compare LinkProviderOutcome.PlayerId with the saved GuestCredential.PlayerId to check that they are the same. If the user logged in with another account before linking, the saved credentials may not belong to the account just linked, and deleting them removes the way into an account unrelated to the linking.
guestCredentialStore is the store created in Prepare the guest credential store. Apps that do not provide guest login have no values to delete, so skip this step.
Linking confirmed after cancellation is not cleaned up by the branch above
If linking that you run again after cancellation returns ProviderAlreadyConnected, Status is BusinessOutcome and PlayerId is 0. In this case, compare the currently logged-in Player ID with the saved GuestCredential.PlayerId, and delete the credentials only if they are the same.
9. Verify the behavior
- App code Verify the behavior in the app.
Verify linking and logging in again on a real device. In the Unity Editor, Add-ons are not registered and the credential source returns an Unavailable error, so you cannot verify anything from the authentication screen onward.
- Log in as a guest, and then run linking. On Android, if the app does not return after browser login is complete, check the Android scheme registration in the login implementation procedure linked in step 5.
- Check
Success, and check that the saved guest credentials were deleted. - Quit the app completely, relaunch it, and log in with the linked login method.
- Check that the
PlayerIdof the linking result and the Player ID of the login result are the same. - Run linking once more with the same account, and check that
ProviderAlreadyConnectedis returned.
Next steps
There is no recipe for disconnecting a linked login method. To implement it by calling the Hive Axyl SDK methods directly, see Unlink accounts.
To let users leave the linked account and log in with another account, see the Logout practical guide.