Skip to content

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

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.

using Hive.Axyl.Auth;
using Hive.Axyl.Core;
using Hive.Axyl.Core.Unity;
using Hive.Axyl.Storage;

var config = CoreConfig.CreateBuilder("{appId}").Build();

HiveBootstrap.Initialize(config, builder =>
{
    builder
        .AddAuth()
        .AddToken()
        .AddSecureStorage();
});

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.

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.

{
  "name": "MyApp",
  "references": [
    "Hive.Axyl.Core",
    "Hive.Axyl.Auth",
    "Hive.Axyl.Storage",
    "Hive.Axyl.Samples.Recipes"
  ]
}

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

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

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.

  1. Receives a login request from the app client.
  2. Authenticates the user with the app's authentication system.
  3. Determines the identifier of the authenticated user. This value becomes providerUserId in 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_LOGIN
  • providerId: CUSTOM_PROVIDER
  • providerUserId: 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

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.

  1. Log in for the first time with an account from the app's authentication system, and check Success and the PlayerId.
  2. Quit the app completely, and then run it again.
  3. Log in again with the same account, and check that the same PlayerId as in item 1 is returned.
  4. Get one grant key, call LoginWithCustomAsync() twice in a row, and check that IsGrantKeyRejected is true for 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.