Last Updated: 6/10/2022, 6:57:45 AM

# Authentication and Authorization

# Overview

Authorization and Authentication is a group of services that provide multi-layer security via the OAuth 2.0 specification. User accounts, OAuth clients, a robust permission system, and 3rd party login integration are some of the services provided. In this document, we’ll cover the basics of each system and how they fit together to provide secure, reliable access to our platform. Each service we discuss also has a more detailed guide

# Components

# Environment

An environment is the top-level container for applications and data of a single deployment of AccelByte’s platform. Applications in one environment cannot communicate with applications in other environments. Environments separate the services and data of different AccelByte customers from each other. Environments can also be used to isolate different builds of the platform from each other, such as when you use a “dev” environment for development, and a “prod” environment for live services.

# Namespaces

Namespaces are an authorization and grouping mechanism used to control access to services for each of the publisher’s games separately. When defining permissions for clients or roles, you can restrict that access to one or more specific namespaces, or allow access to all namespaces within the environment.

See the Namespaces documentation for more detailed information.

# IAM Clients

IAM clients can be thought of as the applications that access the platform, such as a game server or launcher. Any application that wants to interact with the AccelByte platform will do so through an IAM client. IAM clients are defined in specific namespaces.

See the IAM Clients documentation for more detailed information.

# Roles

A role is a way to assign and maintain the same set of permissions for multiple users at once. At its heart, a role is a simple collection of permissions. Roles are defined at the environment level, outside of any namespaces. Roles are assigned to user accounts per namespace, or can be configured to allow the same permissions in all namespaces. This allows you to easily assign groups of permissions to different users for different namespaces to create things like community managers.

See the Roles documentation for more detailed information.

# User Accounts

User accounts are the nexus of all other entities in the platform. Accounts are defined at the publisher namespace level, and contain information about every user that has registered with your platform. Accounts can contain personally identifiable information, so permission to access other users’ accounts should be closely controlled. User accounts also contain wallets, entitlements, ban and session information, and any 3rd party platforms the user has linked.

See the User Accounts documentation for more detailed information.

# Permissions

Permissions are how the platform controls and restricts access to resources. Each service and endpoint resource specifies which permission controls access to that resource. Permissions are represented as a tokenized string delimited by colons, along with a [[CRUD]] action. Permissions that have the same string but different actions are considered different permissions.

See the Permissions documentation for more detailed information.

# Putting it all Together

uam

Each environment will contain a single publisher namespace. Each publisher namespace will contain one or more game namespaces.

While IAM clients can be defined at either the publisher or the game namespace level, user accounts can only be defined under the publisher namespace. (Technically, you can also define user accounts at the game namespace level as well, but this is more of an advanced scenario outside the scope of this document. Please contact your account manager if you’d like to know more.)

You can create as many IAM clients as you’d like, but most developers only need a few such as game server, game client, dedicated server uploader, and launcher. More details about this can be found in the IAM Clients documentation

Roles will typically be assigned to multiple user accounts. Each user assignment is associated with a specific set of namespaces, indicating the role is applied to that user account only for those specific namespaces. Roles can also be configured to apply its permissions to all namespaces, and when configured this way, this applies to all users the role is assigned to.

Permissions can be defined on clients or roles.

  • Role permissions are applied when a user signs into their account, and the user’s session will contain a union of permissions from all roles assigned to that user for the namespace the user has signed into.
  • Client permissions are used only when no user account has signed in (such as a dedicated server). Typically used only by confidential clients. Client sessions will have whatever permissions were assigned to the client when the session began.

Permissions strings that begin with “ADMIN:” indicate Admin Portal resources. Roles that have the Set as Admin Role flag enabled are considered to be admin roles and are allowed to sign into the Admin Portal, but must be assigned admin permissions in order to access any specific resources within the Admin Portal. User accounts that have been assigned an admin role are considered admin users, and will appear on the Admins page that can be accessed via the Platform Configurations dropdown in the upper-right corner of the Admin Portal.

# 3rd Party Platform Login

When you publish your game through 3rd party platforms such as Steam, Epic, or PSN, you can enable players to log into your game or platform using 3rd party credentials. This will create a headless account in your game or platform for that player, with a user ID tied to it. For more information about using 3rd Party Platform logins, see the 3rd Party Platform Integration documentation.

# Connecting Custom Services to IAM using the Server SDK

# SDK Initialization

Before using the IAM service from the SDK, you will need to initialize your server-side SDK to make sure you are authorized and able to perform create, read, update, and delete actions.

# Golang SDK Initialization

Before using the IAM service from the Golang SDK, you will need to initialize the SDK by following the steps below:

Once completed, you can use the Golang SDK to access IAM (opens new window) services from your serverless app.

Golang test case files (opens new window)

# Python SDK Initialization

Before using the IAM service from the Python SDK, you will need to initialize the SDK by following the steps below:

Once completed, you can use the Golang SDK to access IAM (opens new window) services from your serverless app.

Python test case files (opens new window)

# Authorize

To authorize (opens new window), use the following function.

# Authenticate

To authenticate (opens new window), use the following function.

# Log in as a Client

Make sure you have the necessary client credentials to generate an access token (opens new window). You will need this token to log in as a client using the following function:

For simplicity, we have used a wrapper called **login_client **in the SDK so you don't have to call multiple functions. The SDK automatically detects the values you've set for logging in as a client.

# Log in as a User

This login function is used to log in as a user using a username and password. For Golang, make sure you’ve Authorized and Authenticated before performing the following function.

In Python, this function can be used to log in as a user. For simplicity, we have used a wrapper called login_user in the SDK so you don't have to call multiple functions. The SDK automatically detects the values you've set for logging in as a user.

# Logout

The Logout function is used to revoke or invalidate user tokens. To implement logout, use the following function:

# Implementing IAM using the Unity SDK

# Quick Reference

References
using AccelByte.Api;
using AccelByte.Core;
using AccelByte.Models;
Login
User user = AccelBytePlugin.GetUser();

user.LoginWithUsername(username, password,
result =>
{
    if (result.IsError)
    {
         Debug.Log("Login failed");
         // some actions
    }
    else
    {
        Debug.Log("Login successful");
         // some actions
    }
});
Check if a Player is Logged In
AccelBytePlugin.GetUser().Session.IsValid();

# Quickstart Guide

In this section, you will learn how to log in and connect to the IAM Services.

  1. Create a script called LoginHandler.cs and add the following AccelByte libraries to the top of the script:
using AccelByte.Api;
using AccelByte.Models;
using AccelByte.Core;
  1. Set up the Login logic using the Username and Password method. In the script, add the following:
// Function called to Login by email to AccelByte's IAM services.
public void OnLoginClick(string username, string password)
{
    // Grab a current User reference, even if it has not logged in yet.
    User user = AccelBytePlugin.GetUser();

    // Call the Login Function and supplying a asynchronous callback to act based upon success or failure
    user.LoginWithUsername(username,password,
        result =>
        {
            if (result.IsError)
            {    
            // Print the Error Code and Message if error happened
                Debug.Log($"Login failed : {result.Error.Code}: {result.Error.Message}");
            }
            else
            {
                Debug.Log("Login successful");
            }
        });
}
  1. Test your script by calling it from elsewhere in MonoBehaviour and supplying sample credentials.
void Start()
{
    OnLoginClick("user@example.net","SuperPassword");
}
  1. Attach your script to a new GameObject. In the example below, we have named this object AccelByteHandler. Test your object by pressing Play. If you have followed these steps correctly, you will see the message Login successfully appear in your Console Log.
  2. Check whether the Player is logged in by checking if their session is valid.
AccelBytePlugin.GetUser().Session.IsValid();

For testing purposes, place this code in the Update function of your script:

void Update()
{
    if (AccelBytePlugin.GetUser().Session.IsValid())
    {
        Debug.Log("Logged in");
    }
}

When you press Play, you should now see that the player is correctly logged in and the stored credentials are valid. Once completed, remove this debug check from your script.

TROUBLESHOOTING

Troubleshooting If you encounter a Login failed message, check your login credentials or the API URLs supplied in the AccelByteSDKConfig.json file. If the error is related to .JSON reading, check the format of your AccelByteSDKConfig.json file.

Congratulations! You have successfully learnt how to log in.

Continue on for a step by step example of the UI and code implementation. Otherwise, you are now ready to move on to the Lobby (opens new window).

# Step by Step Guide

UI Implementation
  1. Create an empty object (such as AccelByteHandler in Step 4 of the Quickstart Guide above) to hold all of the script components of the IAM services implementation.
  2. For the Login Page, create a new panel or scene with the following objects:
  • Username input field
  • Password input field
  • Login button
  • Status text

Authentication

Code Implementation
  1. Add the following code to the top of your LoginHandler.cs class:
using UnityEngine.UI;

Inside the class, add references to the UI components you have just created:

[SerializeField]
Button loginButton;
[SerializeField]
Text statusText;
[SerializeField]
InputField usernameInputField;
[SerializeField]
InputField passwordInputField;
[SerializeField]
RectTransform loginPanel;
  1. In the Start() function, remove the OnLoginClick() call and create two new functions, OnEnable() and OnDisable().
private void OnEnable()
{
    // When we Activate, set the Text of the Login Status
    // and add the Login Call to the Button's listener
    statusText.text = "Please Login";
    loginButton.onClick.AddListener(()
        =>
    {
        statusText.text = "Attempting Login";
        OnLoginClick(usernameInputField.text, passwordInputField.text);
    });
}

private void OnDisable()
{
    // When we disable, clear all of the Listeners from the Login Button
    loginButton.onClick.RemoveAllListeners();
}
  1. Within the OnLoginClick() function, add the following basic login components and status text which will be visible to the player when they are logging in:
public void OnLoginClick(string username, string password)
{
    // Disable Interaction with the Login Button so the player cannot spam click it and send multiple requests
    loginButton.interactable = false;
    statusText.text = "Logging in...";
    ...

    user.LoginWithUsername(username, password,
        result =>
        {
            if (result.IsError)
            {
                // If we error, grab the Error Code and Message to print in the Log
                Debug.Log($"Login failed : {result.Error.Code}: {result.Error.Message}");
        // Set the Status Text to display the Error if there is any
                statusText.text = $"Login failed : {result.Error.Code}: {result.Error.Message}";
            }
            else
            {
                Debug.Log("Login successful");

        // Set the loginPanel to be inactive, (In later tutorials, we'll also use this functionality to display the Lobby/Main Menu)
                loginPanel.gameObject.SetActive(false);
            }

            // Enable interaction with the Button again
            loginButton.interactable = true;
        });
...
  • Set the loginButton to be disabled whilst awaiting the result of the login request (so that the player cannot spam login requests).
  • Set the statusText to display a message (such as Logging in…) to display to the player while the login request is processing.
  • Set the statusText to show the relevant error code and message should the login attempt fail.
  • Set the loginPanel to be disabled if the player logs in successfully.
  • Enable intractability on the loginButton after the login result is determined.
  1. Save and return to the Editor. In the AccelByteHandler gameObject, drag the corresponding objects into the five exposed variables in your LoginHandler.cs script.

Authentication

  1. Save your scene, press Play, and type in your credentials. If your credentials are incorrect, an error message will appear in the log and status text.

Authentication

If your credentials are correct, the scene will become blank as the LoginPanel disappears.

Congratulations! You have now fully implemented the Login, which is the gateway to all other AccelByte services.

Proceed to the next section to learn how to implement Lobby Services (opens new window).

# Full Code

LoginHandler.cs
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using AccelByte.Api;
using AccelByte.Models;
using AccelByte.Core;
using UnityEngine.Serialization;
using UnityEngine.UI;

public class LoginHandler : MonoBehaviour
{
    [SerializeField]
    Button loginButton;
    [SerializeField]
    Text statusText;
    [SerializeField]
    InputField usernameInputField;
    [SerializeField]
    InputField passwordInputField;
    [SerializeField]
    RectTransform loginPanel;

    // Start is called before the first frame update
    void Start()
    {
    }

    private void OnEnable()
    {
        // When we Activate, set the Text of the Login Status
        // and add the Login Call to the Button's listener
        statusText.text = "Please Login";
        loginButton.onClick.AddListener(()
            =>
        {
            statusText.text = "Attempting Login";
            OnLoginClick(usernameInputField.text, passwordInputField.text);
        });
    }

    private void OnDisable()
    {
        // When we disable, clear all of the Listeners from the Login Button
        loginButton.onClick.RemoveAllListeners();
    }

    // Update is called once per frame
    void Update()
    {
        // if (AccelBytePlugin.GetUser().Session.IsValid())
        // {
        //     Debug.Log("Logged in");
        // }
    }

    /// <summary>
    /// Function called to Login to AccelByte's IAM services
    /// </summary>
    /// <param name="username">The Username (typically an email address) of the user</param>
    /// <param name="password">The password of the user</param>
    public void OnLoginClick(string username, string password)
    {
        // Disable Interaction with the Login Button so the player cannot spam click it and send multiple requests
        loginButton.interactable = false;
        statusText.text = "Logging in...";
        // Grab a reference to the current User, even though they have not been logged in yet.
        // This also acts as the initialisation point for the whole AccelByte plugin.
        User user = AccelBytePlugin.GetUser();
        // Calling the Login Function and supplying a callback to act upon based upon success or failure
        // You will almost certainly want to extend this functionality further
        // Note that this callback is asynchronous
        user.LoginWithUsername(username, password,
            result =>
            {
                if (result.IsError)
                {
                    // If we error, grab the Error Code and Message to print in the Log
                    Debug.Log($"Login failed : {result.Error.Code}: {result.Error.Message}");
                    //Set the Status Text to display the Error if there is any
                    statusText.text = $"Login failed : {result.Error.Code}: {result.Error.Message}";
                }
                else
                {
                    Debug.Log("Login successful");

                    loginPanel.gameObject.SetActive(false);
                }

                //Enable interaction with the Button again
                loginButton.interactable = true;
            });
    }    
}