Unreal Engine SDK を使用した認証
Overview
This topic is specific to the AccelByte Gaming Services (AGS) Shared Cloud tier.
The Authentication service is part of the AccelByte services that provides multilayer security via the OAuth 2.0 specification. This is described in detail in the Access service section.
Prerequisites
The examples in this document use the latest version of AGS Shared Cloud's UE SDK and AGS Shared Cloud's UE OSS.
Other versions may need different steps to implement. See AGS OSS for Unreal Engine for more information on setting up the OSS.
Quick reference
References
#include "OnlineIdentityInterfaceAccelByte.h"
#include "OnlineSubsystemUtils.h"
Login
IdentityInterface->AddOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM,
FOnLoginCompleteDelegate::CreateLambda([this, IdentityInterface]
(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
IdentityInterface->ClearOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM, OnLoginCompleteDelegateHandle);
if (bWasSuccessful)
{
LoginSuccess();
}
else
{
LoginFailed(Error);
}
}));
const FOnlineAccountCredentialsAccelByte OnlineAccountCredentialsAccelByte
{EAccelByteLoginType::AccelByte, "Username", "Password"};
IdentityInterface->Login(USER_LOCAL_NUM, OnlineAccountCredentialsAccelByte);
Logout
IdentityInterface->AddOnLogoutCompleteDelegate_Handle(USER_LOCAL_NUM,
FOnLogoutCompleteDelegate::CreateLambda([this, IdentityInterface](int32 LocalUserNum, bool bWasSuccessful)
{
IdentityInterface->ClearOnLogoutCompleteDelegate_Handle(USER_LOCAL_NUM, OnLogoutCompleteDelegateHandle);
if (bWasSuccessful)
{
LogoutSuccess();
}
else
{
LogoutFailed();
}
}));
IdentityInterface->Logout(USER_LOCAL_NUM);
Quickstart
In this section, you will learn how to enable authentication using AccelByte Gaming Services (AGS) Shared Cloud's IAM services.
Create a user widget C++ class named
AccelByteAuth
which will specify the authentication flow between functions when creating an authentication system.Add the AccelByte header to ensure the functions will work correctly for the IAM services.
.cpp
...
#include "OnlineIdentityInterfaceAccelByte.h"
#include "OnlineSubsystemUtils.h"
...Use the
LoginWithUsername()
function to create a new function to handle logins when players use their username or email..cpp
void UAccelByteAuth::OnLoginButtonClicked()
{
T_LoginStatus->SetText(FText::FromString("Logging in..."));
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
ensure(Subsystem != nullptr);
const FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(Subsystem->GetIdentityInterface());
ensure(IdentityInterface.IsValid());
OnLoginCompleteDelegateHandle = IdentityInterface->AddOnLoginCompleteDelegate_Handle(
USER_LOCAL_NUM, FOnLoginCompleteDelegate::CreateLambda([this, IdentityInterface]
(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
IdentityInterface->ClearOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM, OnLoginCompleteDelegateHandle);
if (bWasSuccessful)
{
LoginSuccess();
}
else
{
LoginFailed(Error);
}
}));
const FString& Username = Etb_Username->GetText().ToString();
const FString& Password = Etb_Password->GetText().ToString();
const FOnlineAccountCredentialsAccelByte OnlineAccountCredentialsAccelByte
{EAccelByteLoginType::AccelByte, Username, Password};
IdentityInterface->Login(USER_LOCAL_NUM, OnlineAccountCredentialsAccelByte);
}.h
...
/**
* @brief Log an account in using the AccelByte SDK. This is executed automatically on component construction unless
* otherwise configured.
*/
UFUNCTION()
void OnLoginButtonClicked();
...Create another new function to handle the logout flow using the
Logout()
function..cpp
void UAccelByteAuth::OnLogoutButtonClicked()
{
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
ensure(Subsystem != nullptr);
const FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(Subsystem->GetIdentityInterface());
ensure(IdentityInterface.IsValid());
OnLogoutCompleteDelegateHandle = IdentityInterface->AddOnLogoutCompleteDelegate_Handle(
USER_LOCAL_NUM, FOnLogoutCompleteDelegate::CreateLambda([this, IdentityInterface](int32 LocalUserNum, bool bWasSuccessful)
{
IdentityInterface->ClearOnLogoutCompleteDelegate_Handle(USER_LOCAL_NUM, OnLogoutCompleteDelegateHandle);
if (bWasSuccessful)
{
LogoutSuccess();
}
else
{
LogoutFailed();
}
}));
IdentityInterface->Logout(USER_LOCAL_NUM);
}.h
...
/**
* @brief Log out a session using the AccelByte SDK. This is executed automatically on component construction unless
* otherwise configured.
*/
UFUNCTION()
void OnLogoutButtonClicked();
...Test your login flow by calling it from any of the other classes or functions that will be loaded first. In this case, you 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();
Btn_Login->OnClicked.AddUniqueDynamic(this, &UAccelByteAuth::OnLoginButtonClicked);
}.h
...
virtual void NativeConstruct() override;
...TIP:If you get a Login failed message, check your login credentials and the API URLs supplied in the
DefaultEngine.ini
file. If the error is related to.JSON
reading, check the format of yourDefaultEngine.ini
file.Log in to the AGS Shared Cloud Admin Portal to set up your game backend online features.
Username | Password |
---|---|
tutorial+demo1@accelbyte.net | Password123 |
tutorial+demo2@accelbyte.net | Password123 |
tutorial+demo3@accelbyte.net | Password123 |
tutorial+demo4@accelbyte.net | Password123 |
tutorial+demo5@accelbyte.net | Password123 |
tutorial+demo6@accelbyte.net | Password123 |
Congratulations! You have successfully learned 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
The logout screen menu is not included in this guide. To log out, use the logout function.
Implement the UI
Create a widget blueprint class named
WB_LoginMenu
and re-parent theWB_LoginMenu
widget blueprint to theAccelByteAuth
C++ class.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
Include the widget-related classes at the top of the class for widget implementation.
- cpp
- h
...
#include "Components/Button.h"
#include "Components/EditableTextBox.h"
#include "Components/TextBlock.h"class UVerticalBox;
class UEditableTextBox;
class UButton;
class UTextBlock;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;
...Remove the
OnLoginButtonClicked()
call in theNativeConstruct()
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);
}In
OnLoginButtonClicked()
, delete the function's parameters and update the function to retrieve credentials from widgets instead.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
void UAccelByteAuth::OnLoginButtonClicked()
{
T_LoginStatus->SetText(FText::FromString("Logging in..."));
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
ensure(Subsystem != nullptr);
const FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(Subsystem->GetIdentityInterface());
ensure(IdentityInterface.IsValid());
OnLoginCompleteDelegateHandle = IdentityInterface->AddOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM, FOnLoginCompleteDelegate::CreateLambda([this, IdentityInterface]
(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
IdentityInterface->ClearOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM, OnLoginCompleteDelegateHandle);
if (bWasSuccessful)
{
LoginSuccess();
}
else
{
LoginFailed(Error);
}
}));
const FString& Username = Etb_Username->GetText().ToString();
const FString& Password = Etb_Password->GetText().ToString();
const FOnlineAccountCredentialsAccelByte OnlineAccountCredentialsAccelByte
{EAccelByteLoginType::AccelByte, Username, Password};
IdentityInterface->Login(USER_LOCAL_NUM, OnlineAccountCredentialsAccelByte);
}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.- cpp
- h
...
void UAccelByteAuth::LoginSuccess()
{
UE_LOG(LogTemp, Log, TEXT("Login Success"));
T_LoginStatus->SetText(FText::FromString("Login successful"));
}
void UAccelByteAuth::LoginFailed(const FString& ErrorMessage)
{
UE_LOG(LogTemp, Error, TEXT("Login Failed : %s"), *ErrorMessage);
T_LoginStatus->SetText(FText::FromString(FString::Printf(TEXT("Login Failed : %s"), *ErrorMessage)));
}
......
/**
* @brief Function behavior when login is successful. This function, which is called from inside AccelByte Login OnSuccess,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*/
void LoginSuccess();
/**
* @brief Function behavior when login fails. This function, which is called from inside AccelByte Login OnFailed,
* delegates inside lambda. How the login behavior works inside this function can changed.
*be
* @param ErrorMessage error message HTTP request, e.g., Unauthorized.
*/
void LoginFailed(const FString& ErrorMessage);
...In
OnLogoutButtonClicked()
, modify the logout function's parameter to callUObject
delegate functions to subscribe to the delegate if the response succeeds or fails..cpp
void UAccelByteAuth::OnLogoutButtonClicked()
{
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
ensure(Subsystem != nullptr);
const FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(Subsystem->GetIdentityInterface());
ensure(IdentityInterface.IsValid());
OnLogoutCompleteDelegateHandle = IdentityInterface->AddOnLogoutCompleteDelegate_Handle(
USER_LOCAL_NUM, FOnLogoutCompleteDelegate::CreateLambda([this, IdentityInterface](int32 LocalUserNum, bool bWasSuccessful)
{
IdentityInterface->ClearOnLogoutCompleteDelegate_Handle(USER_LOCAL_NUM, OnLogoutCompleteDelegateHandle);
if (bWasSuccessful)
{
LogoutSuccess();
}
else
{
LogoutFailed();
}
}));
IdentityInterface->Logout(USER_LOCAL_NUM);
}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 Logout query response.- cpp
- h
...
void UAccelByteAuth::LogoutSuccess()
{
UE_LOG(LogTemp, Log, TEXT("Logout Success"));
}
void UAccelByteAuth::LogoutFailed()
{
UE_LOG(LogTemp, Error, TEXT("Logout Failed"));
}
.../**
* @brief Function behavior when logout is successful. This function, which is called from inside AccelByte Logout OnSuccess
* delegates inside lambda.
*/
void LogoutSuccess();
/**
* @brief Function behavior when logout fails. This function is called from inside AccelByte Logout OnFailed
* delegates inside lambda.
*/
void LogoutFailed(int32 ErrorCode, const FString& ErrorMessage);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.
Congratulations! You have now fully implemented Logins, which are the gateway to all of AGS.
Full code for reference
AccelByteAuth.h
// Copyright (c) 2024 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 backend 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;
/**
* @brief Instantiate all casting to the main menu HUD
*/
UPROPERTY()
ATutorialMenuHUD* TutorialMenuHUD;
/**
* @brief Delegate on login complete
*/
FDelegateHandle OnLoginCompleteDelegateHandle;
/**
* @brief Delegate on logout complete
*/
FDelegateHandle OnLogoutCompleteDelegateHandle;
public:
/**
* @brief Log in an account using the AccelByte SDK. This is executed automatically on component construction unless
* otherwise configured.
*/
UFUNCTION()
void OnLoginButtonClicked();
/**
* @brief Logo ut a session using the AccelByte SDK. This is executed automatically on component construction unless
* otherwise configured.
*/
UFUNCTION()
void OnLogoutButtonClicked();
private:
/**
* @brief Function behavior when login is successful. This function, which is called from inside AccelByte Login OnSuccess,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*/
void LoginSuccess();
/**
* @brief Function behavior when login fails. This function, which is called from inside AccelByte Login OnFailed,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*
* @param ErrorMessage error message HTTP request. e.g Unauthorized.
*/
void LoginFailed(const FString& ErrorMessage);
/**
* @brief Function behavior when logout is successful. This function, which is called from inside AccelByte Logout OnSuccess,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*/
void LogoutSuccess();
/**
* @brief Function behavior when logout fails. This function, which is called from inside AccelByte Logout OnFailed,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*/
void LogoutFailed();
};
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 "OnlineIdentityInterfaceAccelByte.h"
#include "OnlineSubsystemUtils.h"
#include "Components/Button.h"
#include "Components/EditableTextBox.h"
#include "Components/TextBlock.h"
#define USER_LOCAL_NUM 0
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..."));
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
ensure(Subsystem != nullptr);
const FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(Subsystem->GetIdentityInterface());
ensure(IdentityInterface.IsValid());
OnLoginCompleteDelegateHandle = IdentityInterface->AddOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM, FOnLoginCompleteDelegate::CreateLambda([this, IdentityInterface]
(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
IdentityInterface->ClearOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM, OnLoginCompleteDelegateHandle);
if (bWasSuccessful)
{
LoginSuccess();
}
else
{
LoginFailed(Error);
}
}));
const FString& Username = Etb_Username->GetText().ToString();
const FString& Password = Etb_Password->GetText().ToString();
const FOnlineAccountCredentialsAccelByte OnlineAccountCredentialsAccelByte
{EAccelByteLoginType::AccelByte, Username, Password};
IdentityInterface->Login(USER_LOCAL_NUM, OnlineAccountCredentialsAccelByte);
}
void UAccelByteAuth::OnLogoutButtonClicked()
{
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
ensure(Subsystem != nullptr);
const FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(Subsystem->GetIdentityInterface());
ensure(IdentityInterface.IsValid());
OnLogoutCompleteDelegateHandle = IdentityInterface->AddOnLogoutCompleteDelegate_Handle(USER_LOCAL_NUM, FOnLogoutCompleteDelegate::CreateLambda([this, IdentityInterface](int32 LocalUserNum, bool bWasSuccessful)
{
IdentityInterface->ClearOnLogoutCompleteDelegate_Handle(USER_LOCAL_NUM, OnLogoutCompleteDelegateHandle);
if (bWasSuccessful)
{
LogoutSuccess();
}
else
{
LogoutFailed();
}
}));
IdentityInterface->Logout(USER_LOCAL_NUM);
}
void UAccelByteAuth::LoginSuccess()
{
UE_LOG(LogTemp, Log, TEXT("Login Success"));
T_LoginStatus->SetText(FText::FromString("Login successful"));
}
void UAccelByteAuth::LoginFailed(const FString& ErrorMessage)
{
UE_LOG(LogTemp, Error, TEXT("Login Failed : %s"), *ErrorMessage);
T_LoginStatus->SetText(FText::FromString(FString::Printf(TEXT("Login Failed : %s"), *ErrorMessage)));
}
void UAccelByteAuth::LogoutSuccess()
{
UE_LOG(LogTemp, Log, TEXT("Logout Success"));
}
void UAccelByteAuth::LogoutFailed()
{
UE_LOG(LogTemp, Error, TEXT("Logout Failed"));
}