Skip to main content

Implement the Authentication using the Unreal Engine SDK

Last updated on

Overview

The Authentication service is part of the AccelByte services that provides multi-layer security via the OAuth 2.0 specification. This is described in detail in the Authentication and Authorization document.

Prerequisites

The examples in this document use AGS Starter’s UE SDK version 15.0.0. Any other version may not be compatible or may need different steps to implement.

Quick reference

References

#include "Api/AccelByteUserApi.h"
#include "Core/AccelByteRegistry.h"

Login

FRegistry::User.LoginWithUsername(
"Username",
"Password",
FVoidHandler::CreateWeakLambda(this, []()
{
// On Login Success
}),
FCustomErrorHandler::CreateWeakLambda(this, [](
int32 ErrorCode,
const FString& ErrorMessage,
const FJsonObject& ErrorJson)
{
// On Login Failed
}));

Logout

FRegistry::User.Logout(
FVoidHandler::CreateWeakLambda(this, []()
{
// On Logout Success
}),
FErrorHandler::CreateWeakLambda(this, [](
int32 ErrorCode,
const FString& ErrorMessage)
{
// On Logout Failed
}));

Quickstart guide

In this guide, you will learn how to use authentication from AccelByte Gaming Services (AGS) Starter’s IAM services.

  1. Create a user widget C++ class named AccelByteAuth which will specify the authentication flow between functions when creating an authentication system.

  2. Add the AccelByte header to ensure the functions will work correctly for the IAM services.

    .cpp

    ...
    #include "Api/AccelByteUserApi.h"
    #include "Core/AccelByteRegistry.h"
    ...
  1. Use the LoginWithUsername() function to create a new function to handle logins when players use their username or email.

    .cpp

    void UAccelByteAuth::OnLoginButtonClicked(FString Username, FString Password)
    {
    FRegistry::User.LoginWithUsername(
    Username,
    Password,
    FVoidHandler::CreateWeakLambda(this, []()
    {
    UE_LOG(LogTemp, Log, TEXT("Login success"));
    }),
    FCustomErrorHandler::CreateWeakLambda(this, [](
    int32 ErrorCode,
    const FString& ErrorMessage,
    const FJsonObject& ErrorJson)
    {
    UE_LOG(LogTemp, Error, TEXT("Login failed : %d, %s"), ErrorCode, *ErrorMessage);
    }));
    }

    .h

    ...
    /**
    * @brief Log an account using the AccelByte SDK. This is executed automatically on component construction unless otherwise configured.
    */
    UFUNCTION()
    void OnLoginButtonClicked(FString Username, FString Password);
    ...
  2. Create another new function to handle the logout flow using the Logout() function.

    .cpp

    void UAccelByteAuth::OnLogoutButtonClicked()
    {
    FRegistry::User.Logout(
    FVoidHandler::CreateWeakLambda(this, []()
    {
    UE_LOG(LogTemp, Log, TEXT("Logout success"));
    }),
    FErrorHandler::CreateWeakLambda(this, [](
    int32 ErrorCode,
    const FString& ErrorMessage)
    {
    UE_LOG(LogTemp, Error, TEXT("Logout failed : %d, %s"), ErrorCode, *ErrorMessage);
    }));
    }

    .h

```cpp
...
/**
* @brief Logout a session using the AccelByte SDK. This is executed automatically on component construction unless otherwise configured.
*/
UFUNCTION()
void OnLogoutButtonClicked();
...
```
  1. Test your login flow by calling it from any of the other classes or functions that will be loaded first. In this case, we will use the NativeConstruct() function which manages the construction of widgets at the very beginning. You can specify some sample credentials for Username_ _and Password for testing purposes.

    .cpp

    void UAccelByteAuth::NativeConstruct()
    {
    Super::NativeConstruct();

    OnLoginButtonClicked("tutorial+demo1@accelbyte.net","Password123");
    }

    .h

    ...
    virtual void NativeConstruct() override;
    ...
    TIP:

    If you get a Login failed message, check your login credentials or the API URLs supplied in the DefaultEngine.ini file. If the error is related to .JSON reading, check the format of your DefaultEngine.ini file.

    If you don’t have an account and are evaluating our product using a demo environment, you can use one of these sample accounts for testing, or you can register an account in our demo portal.

<table>
<tr>
<td>
<strong>Username</strong>
</td>
<td><strong>Password</strong>
</td>
</tr>
<tr>
<td>tutorial+demo1@accelbyte.net
</td>
<td>Password123
</td>
</tr>
<tr>
<td>tutorial+demo2@accelbyte.net
</td>
<td>Password123
</td>
</tr>
<tr>
<td>tutorial+demo3@accelbyte.net
</td>
<td>Password123
</td>
</tr>
<tr>
<td>tutorial+demo4@accelbyte.net
</td>
<td>Password123
</td>
</tr>
<tr>
<td>tutorial+demo5@accelbyte.net
</td>
<td>Password123
</td>
</tr>
<tr>
<td>tutorial+demo6@accelbyte.net
</td>
<td>Password123
</td>
</tr>
</table>
  1. To test your logout flow, call it inside the login delegate success and then check the log for both login and logout functionality. Below is some sample code. Don’t forget to remove this code after testing.

    .cpp

    FRegistry::User.LoginWithUsername(
    ...
    FVoidHandler::CreateWeakLambda(this, []()
    {
    ...
    OnLogoutButtonClicked();
    }),
    ...

Congratulations! You have successfully learnt how to implement Authentication.

Continue on for a step-by-step example of the associated widget and code implementation. Otherwise, you are now ready to move on to the Lobby.

Step-by-step guide

IMPORTANT

The logout screen menu is not included in this guide. To log out, use the logout function.

Implement the UI

  1. Create a widget blueprint class named WB_LoginMenu and re-parent the WB_LoginMenu widget blueprint to the AccelByteAuth C++ class.

  2. Create a Login Page with the following object components:

    • Editable text box for username input
    • Editable text box for password input
    • Button for the login action
    • Text block for the login status text.

Implement the code

  1. Include the widget-related classes at the top of the class for widget implementation.

    ...
    #include "Components/Button.h"
    #include "Components/EditableTextBox.h"
    #include "Components/TextBlock.h"
  2. Specify all the widget components in the AccelByteAuth header file.

    .h

    ...

    UPROPERTY(meta = (BindWidget))
    UEditableTextBox* Etb_Username;

    UPROPERTY(meta = (BindWidget))
    UEditableTextBox* Etb_Password;

    UPROPERTY(meta = (BindWidget))
    UButton* Btn_Login;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* T_LoginStatus;
    ...
  1. Remove the OnLoginButtonClicked() call in the NativeConstruct() function. Then, set the Login’s Canvas Panel to be visible and bind the Login button to its function.

    .cpp

    void UAccelByteAuth::NativeConstruct()
    {
    Super::NativeConstruct();

    UE_LOG(LogTemp, Log, TEXT("Login with Username"));

    T_LoginStatus->SetText(FText::FromString("Please Login"));
    Btn_Login->OnClicked.AddUniqueDynamic(this, &UAccelByteAuth::OnLoginButtonClicked);
    }
  1. In OnLoginButtonClicked(), delete the function’s parameters and update the function to retrieve credentials from widgets instead.

  2. To make it easier to differentiate the responses, create two new functions and then create two UObject delegate functions to subscribe to the delegate if the response succeeds or fails.

    .cpp

```cpp
void UAccelByteAuth::OnLoginButtonClicked()
{
T_LoginStatus->SetText(FText::FromString("Logging in..."));

FRegistry::User.LoginWithUsername(
Etb_Username->GetText().ToString(),
Etb_Password->GetText().ToString(),
FVoidHandler::CreateUObject(this, &UAccelByteAuth::LoginSuccess),
FCustomErrorHandler::CreateUObject(this, &UAccelByteAuth::LoginFailed));
}
```
  1. Both of the UObject delegate functions can be used to call other functions after a successful or failed login. Set the text for the Login Status to inform the user about where they are in the process.

    ...
    void UAccelByteAuth::LoginSuccess()
    {
    UE_LOG(LogTemp, Log, TEXT("Login success"));
    T_LoginStatus->SetText(FText::FromString("Login successful"));
    }

    void UAccelByteAuth::LoginFailed(int32 ErrorCode, const FString& ErrorMessage, const FJsonObject& ErrorJson)
    {
    UE_LOG(LogTemp, Error, TEXT("Login failed : %d , %s"), ErrorCode, *ErrorMessage);
    T_LoginStatus->SetText(FText::FromString(FString::Printf(TEXT("Login Failed : %d , %s"), ErrorCode, *ErrorMessage)));
    }
  1. In OnLogoutButtonClicked(), modify the logout function’s parameter to call UObject delegate functions to subscribe to the delegate if the response succeeds or fails.

    .cpp

    void UAccelByteAuth::OnLogoutButtonClicked()
    {
    FRegistry::User.Logout(
    FVoidHandler::CreateUObject(this, &UAccelByteAuth::LogoutSuccess),
    FErrorHandler::CreateUObject(this, &UAccelByteAuth::LogoutFailed));
    }
  1. Both of the UObject delegate functions can be used to call other functions after a successful or failed logout. For now, add a log to inform the user of the Login query response.

    ...
    void UAccelByteAuth::LogoutSuccess()
    {
    UE_LOG(LogTemp, Log, TEXT("Logout success"));
    }

    void UAccelByteAuth::LogoutFailed(int32 ErrorCode, const FString& ErrorMessage)
    {
    UE_LOG(LogTemp, Error, TEXT("Logout failed : %d , %s"), ErrorCode, *ErrorMessage);
    }
  1. Save the class, build the project, press Play, and type in your credentials.

    The results of the process will be displayed in the Login Status box. If your credentials are incorrect, an error message will appear in the status box, such as in the example below.

Congratulations! You have now fully implemented Logins, which are the gateway to all other AccelByte Cloud services.

Go to the next section to learn how to implement AccelByte Cloud’s Lobby service.

Full code

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

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "AccelByteAuth.generated.h"

class UVerticalBox;
class UEditableTextBox;
class UButton;
class ATutorialMenuHUD;
class UTextBlock;

/**
* Component for logging in a user with the AccelByte back end as well as methods for grabbing information relating to that user.
* This code covers AccelByte services including :
*
* - Login with username
*/

UCLASS()
class TUTORIALPROJECT_API UAccelByteAuth : public UUserWidget
{
GENERATED_BODY()

protected:

virtual void NativeConstruct() override;

/**
* @brief Editable Text Box for Username inside MainMenu Widget.
*/
UPROPERTY(meta = (BindWidget))
UEditableTextBox* Etb_Username;

/**
* @brief Editable Text Box for Password inside MainMenu Widget.
*/
UPROPERTY(meta = (BindWidget))
UEditableTextBox* Etb_Password;

/**
* @brief Take Button Login inside MainMenu Widget.
*/
UPROPERTY(meta = (BindWidget))
UButton* Btn_Login;

/**
* @brief Text Block to display Login Status
*/
UPROPERTY(meta = (BindWidget))
UTextBlock* T_LoginStatus;

public:

/**
* @brief Log an account in using the AccelByte SDK. This is executed automatically on component construction unless
* otherwise configured.
*/
UFUNCTION()
void OnLoginButtonClicked();

/**
* @brief Logout a session using the AccelByte SDK. This is executed automatically on component construction unless
* otherwise configured.
*/
UFUNCTION()
void OnLogoutButtonClicked();

private:

/**
* @brief Function behaviour when Login success. This function called inside AccelByte Login OnSuccess
* delegates inside lambda. Can be improved or changed how login behaviour works inside this function.
*/
void LoginSuccess();

/**
* @brief Function behaviour when Login failed. This function called inside AccelByte Login OnFailed
* delegates inside lambda. Can be improved or changed how login behaviour works inside this function.
*
* @param ErrorCode error code HTTP request. e.g 404.
* @param ErrorMessage error message HTTP request. e.g Unauthorized.
* @param ErrorJson error message for OAuth
*/
void LoginFailed(int32 ErrorCode, const FString& ErrorMessage, const FJsonObject& ErrorJson);

/**
* @brief Function behaviour when Logout success. This function called inside AccelByte Logout OnSuccess
* delegates inside lambda. Can be improved or changed how Logout behaviour works inside this function.
*/
void LogoutSuccess();

/**
* @brief Function behaviour when Logout failed. This function called inside AccelByte Logout OnFailed
* delegates inside lambda. Can be improved or changed how Logout behaviour works inside this function.
*
* @param ErrorCode error code HTTP request. e.g 404.
* @param ErrorMessage error message HTTP request. e.g Unauthorized.
*/
void LogoutFailed(int32 ErrorCode, const FString& ErrorMessage);

};
AccelByteAuth.cpp
// Copyright (c) 2021 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.

#include "AccelByteAuth.h"
#include "Api/AccelByteUserApi.h"
#include "Core/AccelByteRegistry.h"
#include "Components/Button.h"
#include "Components/EditableTextBox.h"
#include "Components/TextBlock.h"

void UAccelByteAuth::NativeConstruct()
{
Super::NativeConstruct();

UE_LOG(LogTemp, Log, TEXT("Login with Username"));

T_LoginStatus->SetText(FText::FromString("Please Login"));
Btn_Login->OnClicked.AddUniqueDynamic(this, &UAccelByteAuth::OnLoginButtonClicked);
}

void UAccelByteAuth::OnLoginButtonClicked()
{
T_LoginStatus->SetText(FText::FromString("Logging in..."));

FRegistry::User.LoginWithUsername(
Etb_Username->GetText().ToString(),
Etb_Password->GetText().ToString(),
FVoidHandler::CreateUObject(this, &UAccelByteAuth::LoginSuccess),
FCustomErrorHandler::CreateUObject(this, &UAccelByteAuth::LoginFailed));
}

void UAccelByteAuth::OnLogoutButtonClicked()
{
FRegistry::User.Logout(
FVoidHandler::CreateUObject(this, &UAccelByteAuth::LogoutSuccess),
FErrorHandler::CreateUObject(this, &UAccelByteAuth::LogoutFailed));
}

void UAccelByteAuth::LoginSuccess()
{
UE_LOG(LogTemp, Log, TEXT("Login Success"));
T_LoginStatus->SetText(FText::FromString("Login successful"));
}

void UAccelByteAuth::LoginFailed(int32 ErrorCode, const FString& ErrorMessage, const FJsonObject& ErrorJson)
{
UE_LOG(LogTemp, Error, TEXT("Login Failed : %d , %s"), ErrorCode, *ErrorMessage);
T_LoginStatus->SetText(FText::FromString(FString::Printf(TEXT("Login Failed : %d , %s"), ErrorCode, *ErrorMessage)));
}

void UAccelByteAuth::LogoutSuccess()
{
UE_LOG(LogTemp, Log, TEXT("Logout Success"));
}

void UAccelByteAuth::LogoutFailed(int32 ErrorCode, const FString& ErrorMessage)
{
UE_LOG(LogTemp, Error, TEXT("Logout Failed : %d , %s"), ErrorCode, *ErrorMessage);
}