Implement username login
To implement username 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 enable username login |
| 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 code | Handle username and password input |
| 7 | App code | Prepare the additional security key |
| 8 | Recipe code | Call username login |
| 9 | App code | Handle login results |
| 10 | App code | Verify the behavior |
Entering a wrong username creates a new account
If no account exists for the entered username, the recipe creates an account with that username. Check IsNewAccount in the Success result, and be sure to tell the user when a new account was created.
1. Configure the Hive Console
- Hive Console Configure or check this in the Hive Console.
In the Hive Console, check the Client ID to use for login and enable username login. If the login method is disabled, the recipe call is rejected.
| Setting | Required | Where to check |
|---|---|---|
| Check the Client ID | Required | Get the security key |
| Enable username login | Required | Check the login activation status in the console |
Do not put the Client Secret in the app client
The recipe uses only the Client ID. If the Client Secret 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 encrypt and keep the DeviceKey on the device.
| Package | Needed | Role |
|---|---|---|
com.com2usplatform.hiveaxyl.core | Required | SDK initialization and login session management |
com.com2usplatform.hiveaxyl.auth | Required | Username login, account creation, and token issuance |
com.com2usplatform.hiveaxyl.storage | Recommended | Encrypted storage of the DeviceKey |
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 username login and initializes the SDK.
For {appId}, enter the App ID you created in the Hive Console.
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
- UsernameLogin/:
UsernameLoginRecipeand 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 UsernameLogin/
UsernameLoginRecipe uses the password hashing code, 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: DeviceKey
The constructor of UsernameLoginRecipe takes ClientId and DeviceKey. 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.
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. Handle username and password input
Pass the username and the original password that the user entered on the login screen to the recipe as they are. The recipe converts the password into a SHA-256 hexadecimal string, so if you hash it in advance in your app code, the user cannot log in to the existing account created with the same username.
The allowed characters and length rules for the username are the same as when you call the Hive Axyl SDK methods directly. The password follows exactly the SHA-256 hexadecimal format that the linked procedure describes, but the recipe performs the conversion for you, so check only the format in the app and do not implement conversion code.
If the username is empty or contains only whitespace, or if the password is empty, the recipe does not call the server and returns a result whose Status is Failure and whose Error.Code is HiveErrorCode.InvalidArgument. In this case, IsUsernameOrPasswordIncorrect is false, so filter out empty input on the app screen first, before the login button is selected.
Do not save the original password or the converted value, and do not include them in error records.
7. Prepare the additional security key
-
App code Implement this in the app.
Detailed procedure: Create a username account
Apps that apply additional security to account creation must also pass a GrantKey. This value is a pre-approval value that the app server gets from the Hive Axyl server and sends down to the app client.
The recipe uses the GrantKey only when it creates a new account, not when it logs in to an existing account. Apps that do not apply additional security do not need to pass this value, and an empty string or a value with only whitespace is treated as not passed. Even when additional security is turned off, a GrantKey you pass is always validated and consumed. After the setting is turned on, account creation requests without a GrantKey are rejected, so if you plan to turn on additional security later, implement the app to always pass it from the start.
Do not create or keep the GrantKey in the app client
The app server prepares a new GrantKey for each account creation attempt. The app client must only pass along the value it receives as is. The Client Secret and credentials used for issuance must not be put in the app client either.
8. Call username login
- Recipe code Call the recipe code from the app.
Call LogInOrSignUpAsync() when the login button is selected. The recipe first tries to log in to an existing account, and creates an account only when no account exists for that username.
Also prepare a CancellationTokenSource so that you can stop waiting when the user closes the screen or cancels login.
Apps that apply additional security must also pass the grantKey received in step 7.
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 | Converts the original password into a SHA-256 hexadecimal string | Password |
| Recipe code | Creates PKCE values and passes them separately to the login call and the token issuance call | Prepare the call parameters |
| Hive Axyl SDK | Logs in to an existing account with LoginUsernameAsync() | Log in with a username |
| Hive Axyl SDK | Creates a new account with CreateUsernameAsync() when no account exists | Create a username account |
| Hive Axyl SDK | Exchanges the authorization code for an access token and a refresh token with IssueTokenAsync() | Issue an access token and a refresh token |
| Hive Axyl SDK | Activates the login session with SetSession() | Activate the session |
When the recipe logs in to an existing account, it does not call CreateUsernameAsync(). When it creates a new account, the recipe creates PKCE values once more. This is because a rejected call does not return an authorization code, so the recipe avoids reusing values it has already sent.
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 password conversion and PKCE generation. 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
LoginWithUsernameOutcome 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, IsNewAccount, IsBlocked | Tell the user whether it is a new account, and if the account is not under a usage restriction, move to the post-login screen. |
BusinessOutcome | BusinessOutcome, IsUsernameOrPasswordIncorrect, 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 while keeping the login screen. |
IsBlocked is filled in only when the user logs in to an existing account. Right after a new account is created, it is always false.
9.1. Handle each rejection reason
If Status is BusinessOutcome, distinguish the rejection reason with the BusinessOutcome value. Whether you ask the user to enter the input again or send the same request again depends on the reason.
BusinessOutcome | Meaning | App handling |
|---|---|---|
UsernameOrPasswordIncorrect | An account exists for the entered username, but the password does not match. IsUsernameOrPasswordIncorrect comes with it as true. | Ask the user to enter the username and password again. |
GrantKeyRequired | The app, which applies additional security, tried to create a new account without a GrantKey. | Get a GrantKey from the app server, pass it as described in step 7, and call again. |
InvalidGrantKey | The GrantKey you passed was rejected. A value you pass is validated even when additional security is turned off. | Get a new GrantKey from the app server and call again. |
TemporarilyUnavailable | At the token issuance step, the Hive Axyl authentication server temporarily could not access its internal storage and could not reach a decision, and the request left no effect. | Call again with the same username and password. Do not resend immediately; leave an interval. The recipe recommends increasing the interval to about 1, 3, and 6 seconds and adding a small variation to each interval. |
Unrecognized | A result this recipe does not interpret. | Handle and record it as a failure, and do not assume it is a known value. Use UnknownOutcomeCode and RawJson only for records, and do not show them to users. |
| Other values | Rejections that are not resolved by correcting the input or sending the same request again. These include app configuration errors, service termination, IP blocking, and rejections at the token issuance step. | Record the rejection reason and display a message that the user cannot log in. |
IsUsernameOrPasswordIncorrect is true only when the rejection reason is UsernameOrPasswordIncorrect, and it is always false in results whose Status is Failure. When you ask the user to re-enter input, do not tell them which of the username and password was incorrect. Telling them that the password was wrong reveals that the username is registered.
9.2. Handle new accounts and different accounts
If IsNewAccount is true, a new account was created with the entered username. The user may have mistyped the username while trying to log in to an existing account, so clearly tell the user that a new account was created.
If your app keeps data linked to the PlayerId that was previously logged in, compare the PlayerId returned on successful login with the previous value. If the values differ, do not continue to use the previous account's data as is; prepare the screens and data for the current account.
9.3. Cancel login
When the screen closes or the user chooses to cancel, stop the running login with cancellation.Cancel(). The cancellation result is returned as a value whose Status is Failure and whose Error.Code is HiveErrorCode.Cancelled.
If a new account was created before the cancellation, the account remains. Guide the user to log in again with the same username and password, and do not automatically create an account with a different username right after the cancellation.
10. Verify the behavior
- App code Verify the behavior in the app.
In an app build, verify new account creation, existing account login, and incorrect password entry. In the Unity Editor, there is no device secure storage and ISecureStorage is not registered, so to verify DeviceKey reuse as well, check on a real device.
- Run login with a username and password that are not yet in use, and check for
SuccessandIsNewAccount == true. - Quit the app completely, log in with the same username and password, and check for
SuccessandIsNewAccount == false. - Enter a different password for the same username, and check for
BusinessOutcomeandIsUsernameOrPasswordIncorrect == true. - On a test account, enter a wrong username and check that the new account notice is displayed.
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.