Authorization

Authorization is one of the main systems in multiplayer games and apps. Let's look at how to quickly create your own authorization in the game using the examples that come with the framework.

Drag and drop the MasterServer and Client scenes to hierarchy panel, these scenes are located in the MasterServerToolkit -> Demo -> BasicAuthorization -> Scenes folder. In these scenes everything is set up to see how the authorization system works and test it in practice.

Select --CLIENT_MANAGER and open the AuthBehaviour component associated with It. This component contains all the basic methods for working with authorization.

protected override void OnInitialize()
{
    Mst.Events.Invoke(MstEventKeys.showLoadingInfo, "Connecting to master... Please wait!");

    // If we want to use default credentials for signin or signup views
    if (useDefaultCredentials && Mst.Runtime.IsEditor)
    {
        var credentials = new MstProperties();
        credentials.Set(MstDictKeys.USER_NAME, defaultUsername);
        credentials.Set(MstDictKeys.USER_PASSWORD, defaultPassword);
        credentials.Set(MstDictKeys.USER_EMAIL, defaultEmail);

        Mst.Events.Invoke(MstEventKeys.setSignInDefaultCredentials, credentials);
        Mst.Events.Invoke(MstEventKeys.setSignUpDefaultCredentials, credentials);
    }

    Mst.Client.Auth.RememberMe = rememberUser;

    MstTimer.Instance.WaitForSeconds(0.5f, () =>
    {
        // Listen to connection events
        Connection.AddConnectionOpenListener(OnClientConnectedToServer);
        Connection.AddConnectionCloseListener(OnClientDisconnectedFromServer, false);

        if (!Connection.IsConnected && !Connection.IsConnecting)
        {
            Connector.StartConnection();
        }
    });
}

Let's take a look at the OnInitialize method, which initializes all the necessary systems to work with authorization at startup.

public virtual ClientToMasterConnector Connector
{
    get
    {
        if (!clientToMasterConnector)
            clientToMasterConnector = FindObjectOfType<ClientToMasterConnector>();

        if (!clientToMasterConnector)
        {
            var connectorObject = new GameObject("--CLIENT_TO_MASTER_CONNECTOR");
            clientToMasterConnector = connectorObject.AddComponent<ClientToMasterConnector>();
        }

        return clientToMasterConnector;
    }
}

In order for our authorization to work, we need to connect to the master server. In our case, in the Connector property, we are just trying to find the connection helper or, if we didn't find it in the scene, create it.

Next, in the initialization method, we set the default credentials. We do this only for the editor mode, just to avoid entering your data constantly. We use the built-in event system to send this data to those who subscribe to it. In our case, these are two Windows. The first login window, and the second registration window.

// If we want to use default credentials for signin or signup views
if (useDefaultCredentials && Mst.Runtime.IsEditor)
{
    var credentials = new MstProperties();
    credentials.Set(MstDictKeys.USER_NAME, defaultUsername);
    credentials.Set(MstDictKeys.USER_PASSWORD, defaultPassword);
    credentials.Set(MstDictKeys.USER_EMAIL, defaultEmail);

    Mst.Events.Invoke(MstEventKeys.setSignInDefaultCredentials, credentials);
    Mst.Events.Invoke(MstEventKeys.setSignUpDefaultCredentials, credentials);
}

Then, if necessary, we tell the authorization system that we want to remember the entered data and use the authorization token the next time we log in. This functionality does not work in guest mode.

The next thing we do is establish a connection to the master server if it is not already established, subscribe to the connection and disconnection events.

MstTimer.Instance.WaitForSeconds(0.5f, () =>
{
    // Listen to connection events
    Connection.AddConnectionOpenListener(OnClientConnectedToServer);
    Connection.AddConnectionCloseListener(OnClientDisconnectedFromServer, false);

    if (!Connection.IsConnected && !Connection.IsConnecting)
    {
        Connector.StartConnection();
    }
});

In the OnClientConnectedToServer event handler, we check whether the user is authorized or not. We also check whether an unauthorized user has an authorization token and, if the token is found, we authorize the player using this token. If the token is not found we open the authorization window.

protected virtual void OnClientConnectedToServer(IClientSocket client)
{
    Mst.Events.Invoke(MstEventKeys.hideLoadingInfo);

    if (Mst.Client.Auth.IsSignedIn)
    {
        OnSignedInEvent?.Invoke();
    }
    else
    {
        if (Mst.Client.Auth.HasAuthToken())
        {
            MstTimer.Instance.WaitForSeconds(0.2f, () =>
            {
                SignInWithToken();
            });
        }
        else
        {
            Mst.Events.Invoke(MstEventKeys.showSignInView);
        }
    }
}

The event handler of disconnection from the master server unregisters from event connections, and then exits the system and initialise all the necessary systems again.

protected virtual void OnClientDisconnectedFromServer(IClientSocket client)
{
    Connection.RemoveConnectionOpenListener(OnClientConnectedToServer);
    Connection.RemoveConnectionCloseListener(OnClientDisconnectedFromServer);

    Mst.Events.Invoke(MstEventKeys.hideLoadingInfo);
    Mst.Events.Invoke(MstEventKeys.showOkDialogBox,
        new OkDialogBoxEventMessage("The connection to the server has been lost. "
        + "Please try again or contact to the developers of the game or your internet provider.",
        () =>
        {
            SignOut();
            OnInitialize();
        }));
}

Next go the authorization event handlers. I think everything is clear there.

/// <summary>
/// Invokes when user signed in
/// </summary>
protected virtual void Auth_OnSignedInEvent()

/// <summary>
/// Invokes when user signed up
/// </summary>
protected virtual void Auth_OnSignedUpEvent()

/// <summary>
/// Invokes when user signed out
/// </summary>
protected virtual void Auth_OnSignedOutEvent()

/// <summary>
/// Invokes when user changed his password
/// </summary>
protected virtual void Auth_OnPasswordChangedEvent()

/// <summary>
/// Invokes when user has confirmed his email
/// </summary>
protected virtual void Auth_OnEmailConfirmedEvent()

The SignIn method performs authorization and verification of confirmation of the user's email address, if required. Also, if the Mst.Client.Auth.RememberMe check box was set, this method remembers the user's authorization token that will be needed for quick login.

Next go methods for logging in in guest mode, registering, resetting your password, and confirming your email address.

Test the current demo scene and see how the authorization system works using the methods mentioned above. UI components located in the scene allow you to perform various tasks required for authorization. Open each UI component and see how they work to see how they work.

All questions related to user authorization can be asked in my discord channel, which is indicated in the main menu of the site.