Authentication

Integrate Noctua Account

The Noctua SDK provides a simple yet powerful authentication system.


We provide a complete solution for authentication, including integration with social login providers such as Google, Facebook, and more. You can use this feature to allow players to sign in with their existing accounts without the need to implement the login flow yourself.

Welcome Toast
Welcome Toast
Login Options
Login Options

A welcome toast will be shown when the player is authenticated. Guest account will be created automatically if no account is found. You can integrate Switch Account button for players to switch account and authenticate with different accounts including social login providers. See Switch Account for more information.

How It Works

The main function you'll use is Noctua.Auth.AuthenticateAsync(). This function handles both guest and Noctua account logins automatically. When you call this function, the following process occurs:

  1. Your game calls Noctua.Auth.AuthenticateAsync().
  2. The SDK checks for existing account information and attempts an automatic login.
  3. Depending on the account status, one of two things happens:
  • For new users or those without a Noctua account, a guest login is performed.
  • For returning users with a Noctua account, the login is updated.
  1. The Auth Server returns a UserBundle object.
  2. The SDK returns a UserBundle object to your game, containing the user's information.
  3. Your game calls Noctua.Auth.UpdateUserAsync() to update the user's role ID and server ID.
  • If there is an exception

Implementation

Here's how to implement authentication in your game:

using com.noctuagames.sdk;
using Cysharp.Threading.Tasks;
using UnityEngine;

public class AuthenticationManager : MonoBehaviour
{
    private void Awake()
    {
        StartCoroutine(Authenticate().ToCoroutine());
    }

    private async UniTask Authenticate()
    {
        // Authenticate
        try {
            var user = await Noctua.Auth.AuthenticateAsync();
            // Handle the user information
            // Use the Player.Id to identify the user
            var playerId = user.Player.Id;
            Debug.Log("PlayerId: " + playerId);
        } catch (Exception e) {
            if (e is NoctuaException noctuaEx)
            {
                Debug.Log("NoctuaException: " + noctuaEx.ErrorCode + " : " + noctuaEx.Message);
            } else {
                Debug.Log("Exception: " + e);
            }
        }

        // Update role ID and server ID
        var playerData = new PlayerAccountData
        {
            IngameUsername = "CoolGamer123",
            IngameServerId = "Server001",
            IngameRoleId = "Role789",
            Extra = new Dictionary<string, string>
            {
                { "level", "42" },
                { "xp", "9876" }
            }
        };

        try {
            await Noctua.Auth.UpdatePlayerAccountAsync(playerData);

        } catch (Exception e) {

            // Handle Authentication Failures

            if (e is NoctuaException noctuaEx)
            {
                Debug.Log("NoctuaException: " + noctuaEx.ErrorCode + " : " + noctuaEx.Message);
            } else {
                Debug.Log("Exception: " + e);
            }
        }
    }
}

Call the Noctua.Auth.AuthenticateAsync() method when you want to authenticate the user, typically at the start of your game or when entering a launcher screen.

Authentication failures

When implementing authentication, it's crucial to handle error cases properly, especially when dealing with banned users. The SDK is already implement proper error messaging to inform users about the reason for authentication failure. Your responsibility is to prevent the user from proceeding to the game to ensure that unauthorized users cannot access your game content and maintains the integrity of your player ecosystem.

In the case of banned user, a dialog will appear to notify user about their account status and the exception will be fired once the user clicked "OK" button of the banned dialog.

Banned User
Banned User

Banned user has specific error code: 2202. The following is an example of how to handle banned user.

            try
            {
                await Noctua.InitAsync();

                await Noctua.Auth.AuthenticateAsync();
            }
            catch (Exception e)
            {
                NoctuaException noctuaEx = e as NoctuaException;
                Debug.Log("SplashScript AuthenticateAsync " + noctuaEx.ErrorCode + " : " + noctuaEx.Message);

                if (noctuaEx != null && noctuaEx.ErrorCode == 2202)
                {
                    // Prevent user from entering the gameplay.
                }
                else
                {
                    // Handle other errors following your use cases.
                }
            }

Best Practices

  1. Error Handling: Always check for errors in the callback and handle them appropriately.
  2. Persistence: The SDK handles token storage automatically, so you don't need to manage this yourself.
  3. Unique User Identification: Always use the UserBundle.Player.Id to identify users. This value is guaranteed to be unique for each user.

Note

The Noctua.Auth.AuthenticateAsync() function is designed to work seamlessly for both new and returning users. You don't need to differentiate between guest and Noctua account logins in your initial authentication call.

UserBundle object

The UserBundle object contains the user's information. It is returned by the Noctua.Auth.AuthenticateAsync() function.

Note

You don't need to manage the UserBundle object yourself. It is automatically handled by the SDK. We display it here for your reference. You might only need to use the Player object.

PropertyTypeDescription
UserUserThe user associated with this bundle.
CredentialCredentialThe credential associated with this bundle.
PlayerPlayerThe player associated with this bundle.
LastUsedDateTimeThe date and time when this bundle was last used.
IsGuestboolIndicates whether this is a guest user.
IsRecentboolIndicates whether this bundle was recently used.
PlayerAccountsList<Player>A list of player accounts associated with this user.

Player

The Player class represents a player in the game system.

PropertyTypeDescription
AccessTokenstringThe access token for the player.
IdintThe unique identifier for the player.
RoleIdstringThe role identifier for the player.
ServerIdstringThe server identifier the player is associated with.
UsernamestringThe in-game username of the player.
GameIdintThe identifier of the game the player is associated with.
GameNamestringThe name of the game the player is associated with.
GamePlatformIdintThe identifier of the game platform.
GamePlatformstringThe name of the game platform.
GameOSstringThe operating system of the game.
BundleIdstringThe bundle identifier associated with the player.
UserUserThe user associated with this player.
UserIdintThe identifier of the user associated with this player.

Unique User Identifier

The Player.Id is the most important property to use for identifying users. It is guaranteed to be unique for each user.

User

The User class represents a user in the system.

PropertyTypeDescription
IdintThe unique identifier for the user.
NicknamestringThe user's nickname or display name.
EmailAddressstringThe user's email address.
PhoneNumbersstringThe user's phone number(s).

User.Id

Don't use User.Id to identify users. Use Player.Id instead.

JsonProperty

All classes use the JsonProperty attribute to specify the JSON property names for serialization and deserialization.

Server-Side Validation

To ensure secure access to your game, the Noctua SDK offers a robust server-side validation mechanism for user credentials. This process uses JSON Web Key Sets (JWKS) for token validation.

JWKS Overview

JWKS (JSON Web Key Set) is a standard for securely transmitting cryptographic keys. You can learn more about JWKS in the RFC 7517 specification.

Validation Process

To implement server-side validation:

  1. Retrieve the Player.AccessToken from the client-side.
  2. Send this token to your backend server.
  3. On your server, fetch the JWKS from our endpoint:
    https://sdk-api-v2.noctuaprojects.com/api/v1/auth/jwks
    
  4. Use the JWKS to validate the token.

Here's a simple example of how to validate the token.

<?php

use Jose\Component\Core\JWK;
use Jose\Component\Core\JWKSet;
use Jose\Component\Signature\JWSVerifier;
use Jose\Component\Signature\Algorithm\ES256;
use Jose\Component\Signature\Serializer\CompactSerializer;

// Fetch JWKS from the server
$jwksJson = file_get_contents('https://sdk-api-v2.noctuaprojects.com/api/v1/auth/jwks');
$jwks = JWKSet::createFromJson($jwksJson);

$access_token = 'DUMMY_ACCESS_TOKEN';

// Parse the token
$serializer = new CompactSerializer();
$jws = $serializer->unserialize($access_token);

// Get the key ID from the token header
$headers = $jws->getSignature(0)->getProtectedHeader();
$kid = $headers['kid'] ?? null;

if ($kid === null) {
    throw new Exception('No "kid" found in token header');
}

// Find the corresponding key in the JWKS
$jwk = $jwks->get($kid);

if ($jwk === null) {
    throw new Exception('No matching key found in JWKS');
}

// Verify the signature
$algorithm = new ES256();
$algorithmManager = new \Jose\Component\Core\AlgorithmManager([$algorithm]);
$jwsVerifier = new JWSVerifier($algorithmManager);

if (!$jwsVerifier->verifyWithKey($jws, $jwk, 0)) {
    throw new Exception('Token signature verification failed');
}

// If we reach here, the token is valid
$payload = json_decode($jws->getPayload(), true);

// Now $payload contains the decoded token data

JWKS Caching

To improve efficiency when doing server-side validation of access tokens, it is highly recommended to cache the JWKS in your backend server.

Previous
Installation