Implement custom account login
To implement custom account login with the recipe code, complete the following procedure 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 | Check the Client ID and Client Secret |
| 2 | Hive Axyl SDK | Install the authentication module and the secure storage module |
| 3 | Hive Axyl SDK | Initialize the SDK and register modules |
| 4 | Recipe code | Copy the recipe folder |
| 5 | App code | Prepare ClientId and DeviceKey |
| 6 | App server | Authenticate the user and determine the user identifier |
| 7 | Hive Axyl Server API, App server | Issue an authentication token and a grant key |
| 8 | App code, Recipe code | Call custom account login |
| 9 | App code | Handle login results |
| 10 | App code | Verify the behavior |
Process everything from grant key issuance to the login call without interruption
A grant key expires 60 seconds after it is issued. Do not issue a grant key in advance or hold it while waiting for user input; issue it right before the call in step 8.
1. Check values in the Hive Console
- Hive Console Configure or check this in the Hive Console.
In the Hive Console, check the Client ID and Client Secret of the security key. The app client uses the Client ID when it logs in, and the app server uses both values when it gets a Hive Axyl Server API authentication token.
| Item to check | Required | Where used | Where to check |
|---|---|---|---|
| Client ID | Required | Token issuance in step 7 and the recipe call in step 8 | Get the security key |
| Client Secret | Required | Token issuance in step 7 | Security key |
You do not enable custom account login or register credentials for it on the Login settings screen. This is because the party that authenticates users is the app server, not an external authentication provider.
Use the Client Secret only on the app server
Put only the Client ID in the app client, and do not put the Client Secret in it. The Client Secret is a secret value that the app server uses only to get a Hive Axyl Server API authentication token. If it leaks from the app client, malicious users can call the API without authorization.
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 secure storage module in your Unity project. The secure storage module is used to keep the DeviceKey in the device's secure storage.
| Package | Needed | Role |
|---|---|---|
com.com2usplatform.hiveaxyl.core | Required | SDK initialization and login session management |
com.com2usplatform.hiveaxyl.auth | Required | Custom account login and token issuance |
com.com2usplatform.hiveaxyl.storage | Recommended | Keeping the DeviceKey in secure storage |
Custom account login does not need a login method-specific Add-on. If you also provide other login methods, install only the Add-ons those methods need. For which Add-on each method needs, see Install and initialize the module.
If your app already uses secure storage, you do not need to install com.com2usplatform.hiveaxyl.storage. Even in this case, the app must be able to read the DeviceKey again after it restarts.
3. Initialize the SDK
-
Hive Axyl SDK Call the Hive Axyl SDK from the app.
Detailed procedure: Initialize the SDK, Register the secure storage module
Initialize the SDK once at the app's entry point, and register the authentication, token, and secure storage modules. The recipe does not initialize the SDK, so calling it without initialization fails with a FailedPrecondition error.
The following example code registers the modules needed for custom account login and initializes the SDK.
For {appId}, enter the App ID you created in the prerequisites.
If you do not register AddAuth() and AddToken(), the recipe fails with a FailedPrecondition error. If your app uses another secure storage, you do not need to register AddSecureStorage().
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
- CustomLogin/:
CustomLoginRecipeand result types
To call recipes from your app code, add the following assembly 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 your 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.Storage contains AddSecureStorage(). If you do not register AddSecureStorage(), you do not need to list Hive.Axyl.Storage.
The code does not compile if you copy only CustomLogin/
CustomLoginRecipe uses the PKCE generation code and the session preparation code in Helper/. Copy Helper/, Recipes.asmdef, and AssemblyInfo.cs together.
5. Prepare ClientId and DeviceKey
-
App code Implement this in the app.
Detailed procedure: Prepare the call parameter values, Client ID, deviceKey
The constructor of CustomLoginRecipe takes ClientId and DeviceKey, and throws an ArgumentException if either value is empty. ClientId is the value you checked in step 1, which the Hive Console issues for each project. DeviceKey is the value the Hive Axyl authentication server uses to distinguish login sessions by device, and the app creates and keeps it itself. You do not need to prepare PKCE values, because the recipe creates a pair itself on each call and passes them separately to the login call and the token issuance call.
The recipe does not create or save DeviceKey, so create and manage it according to the following conditions.
- A different value for each device. A random value such as a UUID is recommended
- A value created and saved once on first launch and reused for every later login
- A length of 22 to 64 characters
- A value made up only of ASCII characters, excluding spaces and control characters
Do not overwrite it with a new DeviceKey just because the storage could not be read
The value may not be gone; only the read may have failed. First fix the storage access problem or try reading again.
6. Authenticate users on the app server
-
App server Implement this on the app server.
Detailed procedure: Custom account login flow
The app server authenticates the user with its own authentication system and determines the identifier that points to that user. This identifier is the basis that connects the Hive Axyl account to the account in the app's authentication system, so it must be fixed, one per user.
The app server does the following.
- Receives a login request from the app client.
- Authenticates the user with the app's authentication system.
- Determines the identifier of the authenticated user. This value becomes
providerUserIdin step 7 and must be 1 to 255 characters long.
Hive Axyl is not involved in this process. The app decides how to authenticate users and in what format to create identifiers. When the same user logs in again, the same identifier must be sent so that the login continues with the same Player ID.
7. Issue an authentication token and a grant key
-
Hive Axyl Server API Call the Hive Axyl Server API from the app server.
App server Implement this on the app server.
Detailed procedure: Issue a pre-authorization key
Have the app server call the Hive Axyl Server API to get a grant key and pass that value to the app client. The app client logs in with only this grant key, so without this call, you cannot proceed to step 8.
This call first requires a Hive Axyl Server API authentication token. For how to get a token with the Client ID and Client Secret from step 1, see Issue a token.
For custom account login, specify CUSTOM_LOGIN in authType, put the user identifier determined in step 6 in providerUserId, and make the call. The values to put in each request field are as follows.
authType:CUSTOM_LOGINproviderId:CUSTOM_PROVIDERproviderUserId: The user identifier of 1 to 255 characters determined in step 6
For the call URL, request headers, and call example, see the detailed procedure. Put the App ID you created in the prerequisites in the X-App-Id header, and the Hive Axyl Server API authentication token you got earlier in the Authorization header.
This step is complete when you pass data.grantKey from the response to the app client.
If grant key issuance fails with 400, distinguish the cause with the code value in the response. In this case, pass the failure to the app client instead of a grant key so that it does not start step 8. For how to handle each error code, see the error codes by API in Issue a pre-authorization key and Account and authentication responses and errors.
The grant key is sensitive information
A grant key is a value that approves a login, so do not leave it in logs or error messages. When you pass it to the app client, use encrypted communication such as HTTPS.
8. Call custom account login
-
App code Implement this in the app.
Recipe code Call the recipe code from the app.
Pass the grant key received from the app server to LoginWithCustomAsync(). This single call completes login, token issuance, and session activation.
Also prepare a CancellationTokenSource so that you can stop waiting when the user closes the screen or cancels login.
The app creates its own communication code that gets the grant key from the app server. The app server only needs to return the data.grantKey it received in step 7 as is. The example code below calls this communication code appServerClient.
using System.Threading;
using Hive.Axyl.Samples.Recipes;
var recipe = new CustomLoginRecipe(clientId, deviceKey);
var cancellation = new CancellationTokenSource();
CancellationToken token = cancellation.Token;
// Get the grant key that the app server obtained through steps 6-7.
string grantKey = await appServerClient.RequestCustomLoginGrantKeyAsync(token);
LoginWithCustomOutcome outcome = await recipe.LoginWithCustomAsync(grantKey, token);
if (outcome.Status == LoginWithCustomStatus.Success)
{
long playerId = outcome.PlayerId;
// The session is ready. Move to the post-login screen.
}
Call cancellation.Cancel() when the screen closes or the user chooses to cancel, and clean up with cancellation.Dispose() when the call finishes.
The recipe performs the following tasks internally.
| Category | Call | Where to check |
|---|---|---|
| Recipe code | Creates a pair of PKCE values and passes them separately to the login call and the token issuance call | Prepare the call parameter values |
| Hive Axyl SDK | Submits the grant key with LoginCustomProviderAsync() and gets an authorization code | Log in with a custom account |
| Hive Axyl SDK | Exchanges the authorization code for an access token and a refresh token with IssueTokenAsync() | Issue tokens and activate the session |
| Hive Axyl SDK | Activates the login session with SetSession() | Issue tokens and activate the session |
Before it calls the server, the recipe first checks that the grant key it received is not empty and that the SDK modules registered in step 3 are ready. If either has a problem, it ends immediately with a failure without calling the server.
When Success is returned, the session is already ready, so do not call the token issuance or session activation code separately.
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 for you, such as creating PKCE values. Refer to them only to check what each call sends and receives.
9. Handle login results
-
App code Implement this in the app.
Detailed procedure: HiveError information
LoginWithCustomOutcome reports the login result through Status. FailedStep is a diagnostic value, so do not use it as the basis for branching the app's normal flow.
Status | Value to check | App handling |
|---|---|---|
Success | PlayerId, IsBlocked | If the account is not under a usage restriction, move to the post-login screen. |
BusinessOutcome | BusinessOutcome, UnknownOutcomeCode | Branch according to the rejection reason, and handle and record unknown values as failures. |
Failure | Error.Code, Error.TraceId | Record the technical problem and provide a retry flow. |
If IsBlocked is true, the user is under a usage restriction. For how to check the restriction reason and period and block entry to the app, see Usage restriction.
The recipe does not tell you whether the account is newly created or already existed. If your app needs to distinguish the two, compare the PlayerId you linked to the user identifier from step 6 with the returned PlayerId. This is because if the rule for creating user identifiers changes, a new PlayerId is issued even for the same user, and Hive Axyl does not return an error in this case.
Handle each rejection reason
If Status is BusinessOutcome, distinguish the rejection reason with the BusinessOutcome value. Whether you can try again differs for each reason, so check the value and branch.
BusinessOutcome | Meaning | App handling |
|---|---|---|
InvalidGrantKey | The grant key has expired or has already been used, or it is a value the server does not recognize or that does not match the request information. | Go through steps 6-7 again to get a new grant key, and try again. If the same result repeats, check the providerId and providerUserId values in step 7. |
TemporarilyUnavailable | The grant key was used, but token issuance is temporarily unavailable. | After a while, get a new grant key and try again from the beginning. |
IpBlocked | The connecting IP is blocked. | Display a screen to the user that says access is restricted. |
ServiceTerminated | The app's service has been terminated. | Display a service termination notice to the user, and ask the app operator to check the service operation status. |
InvalidClient, AppNotFound, ProviderConfigNotFound, ProviderNotSupported | The app's console settings do not match the request. | Check the Client ID from step 1 and the Login settings. |
UnsupportedGrantType, InvalidAuthorizationCode, ExpiredAuthorizationCode, CodeChallengeMismatch, InvalidRefreshToken | Rejected at the token issuance step. | Get a new grant key and start login again. |
Unrecognized | A result this recipe does not interpret. | Handle it as a failure and record it. |
Do not call again with the same grant key
A grant key can be used only once. If IsGrantKeyRejected is true, the server rejected the grant key, so you need a new value. A value of false does not mean that you can reuse the value you passed. Even if token issuance fails or the call is canceled, the grant key may already have been used, so always get a newly issued one when you retry.
If you cancel login with a CancellationToken, Status becomes Failure, and if the recipe handled the cancellation, Error.Code becomes HiveErrorCode.Cancelled.
Do not show UnknownOutcomeCode and RawJson to users. Use them only when you need to record app errors, and do not assume that an unknown result is a known one. If UnknownOutcomeCode is not empty, the server sent a result this SDK version does not recognize; if it is empty, the result is one the recipe does not handle yet.
10. Verify the behavior
- App code Verify the behavior in the app.
Verify that the same user always continues with the same PlayerId whenever they log in, and that a used grant key is not reused. To verify DeviceKey storage and reuse as well, check on a real device. In the Unity Editor, there is no device secure storage, so ISecureStorage is not registered.
- Log in for the first time with an account from the app's authentication system, and check
Successand thePlayerId. - Quit the app completely, and then run it again.
- Log in again with the same account, and check that the same
PlayerIdas in item 1 is returned. - Get one grant key, call
LoginWithCustomAsync()twice in a row, and check thatIsGrantKeyRejectedistruefor the second call.
Finish check 4 within 60 seconds, before the grant key expires. Even then, keep the grant key only in memory and do not leave it in logs.
Next steps
To let logged-in users skip the login screen when they relaunch the app, see Automatic login.
To let users leave the logged-in account and log in with a different account, see the Logout practical guide.
If you need to link a custom account to a Player ID that is already in use, see Link a custom account.