Last active
February 9, 2024 07:41
-
-
Save kirre-bylund/aff9f478879547655b6ef2df8810b324 to your computer and use it in GitHub Desktop.
Full example implementation of Google Sign In class for Unreal Sign In
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "GoogleSignIn.h" | |
#include "FromScratchSignIn.h" | |
#include "Interfaces/OnlineIdentityInterface.h" | |
#include "OnlineSubsystem.h" | |
IOnlineSubsystem* UGoogleSignIn::mOnlineSubsystem = nullptr; | |
FDelegateHandle UGoogleSignIn::LoginDelegateHandle = FDelegateHandle(); | |
bool UGoogleSignIn::SignInWithGoogle(int LocalUserNumber, const FLoginCompletedCallback Callback) | |
{ | |
if(!HasGoogleOnlineSubsystem()) | |
{ | |
return false; | |
} | |
if(mOnlineSubsystem->GetSubsystemName() != GOOGLE_SUBSYSTEM) | |
{ | |
return false; | |
} | |
if(LoginDelegateHandle.IsValid()) | |
{ | |
// Login is already in progress | |
return false; | |
} | |
const IOnlineIdentityPtr IdentityInterface = mOnlineSubsystem->GetIdentityInterface(); | |
if(IdentityInterface == nullptr || !IdentityInterface.IsValid()) | |
{ | |
return false; | |
} | |
if(IdentityInterface->GetLoginStatus(LocalUserNumber) == ELoginStatus::LoggedIn) | |
{ | |
// User is already logged in | |
return false; | |
} | |
// Add our method to be called upon login process completion and keep track of the handle | |
LoginDelegateHandle = IdentityInterface->AddOnLoginCompleteDelegate_Handle( | |
LocalUserNumber, FOnLoginCompleteDelegate::CreateLambda( | |
[Callback](int LocalUserNumber, bool wasSuccessful, const FUniqueNetId& UserId, const FString& Error) | |
{ | |
LoginCompletedHandler(LocalUserNumber, wasSuccessful, UserId, Error, Callback); | |
})); | |
IdentityInterface->Login(LocalUserNumber, FOnlineAccountCredentials{}); | |
return true; | |
} | |
void UGoogleSignIn::LoginCompletedHandler(int LocalUserNumber, bool wasSuccessful, const FUniqueNetId& UserId, const FString& Error, const FLoginCompletedCallback Callback) | |
{ | |
if (!HasGoogleOnlineSubsystem()) | |
{ | |
Callback.ExecuteIfBound(FLoginCompletedResponse{ false, TEXT("No Subsystem set"), LocalUserNumber }); | |
return; | |
} | |
const IOnlineIdentityPtr IdentityInterface = mOnlineSubsystem->GetIdentityInterface(); | |
if (IdentityInterface == nullptr || !IdentityInterface.IsValid()) | |
{ | |
Callback.ExecuteIfBound(FLoginCompletedResponse{ false, TEXT("Could not get Identity Interface"), LocalUserNumber }); | |
return; | |
} | |
if (!LoginDelegateHandle.IsValid()) | |
{ | |
Callback.ExecuteIfBound(FLoginCompletedResponse{ false, TEXT("Login handle was invalid"), LocalUserNumber }); | |
return; | |
} | |
// Clear the login handle and stop listening to callbacks for it | |
IdentityInterface->ClearOnLoginCompleteDelegate_Handle(LocalUserNumber, LoginDelegateHandle); | |
LoginDelegateHandle.Reset(); | |
if (!wasSuccessful) { | |
AsyncTask(ENamedThreads::GameThread, [Callback, wasSuccessful, Error, LocalUserNumber]() | |
{ | |
Callback.ExecuteIfBound(FLoginCompletedResponse{ wasSuccessful, Error, LocalUserNumber }); | |
}); | |
return; | |
} | |
const TSharedPtr<FUserOnlineAccount> UserAccount = IdentityInterface->GetUserAccount(UserId); | |
if(UserAccount == nullptr || !UserAccount.IsValid()) | |
{ | |
Callback.ExecuteIfBound(FLoginCompletedResponse{ false, TEXT("UserAccount was invalid"), LocalUserNumber }); | |
return; | |
} | |
FGoogleUserData UserData{ | |
UserAccount->GetRealName(), | |
UserAccount->GetDisplayName(), | |
"", | |
UserAccount->GetUserId()->ToString(), | |
"", | |
"", | |
"" | |
}; | |
UserAccount->GetAuthAttribute(AUTH_ATTR_ID_TOKEN, UserData.IdToken); | |
FLoginCompletedResponse LoginResponse{ | |
wasSuccessful, | |
Error, | |
LocalUserNumber, | |
UserData | |
}; | |
Callback.ExecuteIfBound(LoginResponse); | |
} | |
bool UGoogleSignIn::Initialize() | |
{ | |
if (IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get(GOOGLE_SUBSYSTEM)) | |
{ | |
if (OnlineSubsystem == nullptr) | |
{ | |
return false; | |
} | |
if (!OnlineSubsystem->Init()) | |
{ | |
return false; | |
} | |
mOnlineSubsystem = OnlineSubsystem; | |
return true; | |
} | |
return false; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "CoreMinimal.h" | |
#include "OnlineSubsystem.h" | |
#include "GoogleSignIn.generated.h" | |
/** | |
* | |
*/ | |
USTRUCT(BlueprintType) | |
struct FGoogleUserData | |
{ | |
GENERATED_BODY() | |
/* | |
* The real name of the signed in user | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FString RealName; | |
/* | |
* The display name of the signed in user | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FString DisplayName; | |
/* | |
* The preferred display name of the signed in user | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FString PreferredDisplayName; | |
/* | |
* The ID of the signed in user | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FString ID; | |
/* | |
* The email of the signed in user | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FString Email; | |
/* | |
* The alias of the signed in user | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FString Alias; | |
/* | |
* The ID Token of the signed in user | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FString IdToken; | |
}; | |
/** | |
* Response from a login process | |
*/ | |
USTRUCT(BlueprintType) | |
struct FLoginCompletedResponse | |
{ | |
GENERATED_BODY() | |
/* | |
* Did the login process succeed | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category="Sign In | Google") | |
bool success; | |
/* | |
* If the process did not succeed, this field holds any errors | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FString Error; | |
/* | |
* Which local user is this for | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
int LocalUseNumber; | |
/* | |
* On successful login, this holds the signed in user's data | |
*/ | |
UPROPERTY(BlueprintReadWrite, Category = "Sign In | Google") | |
FGoogleUserData UserData; | |
}; | |
/* | |
* Delegate for responses upon login process completion | |
*/ | |
DECLARE_DYNAMIC_DELEGATE_OneParam(FLoginCompletedCallback, FLoginCompletedResponse, LoginResponse); | |
UCLASS(Blueprintable) | |
class UGoogleSignIn : public UObject | |
{ | |
GENERATED_BODY() | |
public: | |
/** | |
* Initialize the Google subsystem to enable Google authentication | |
* Returns true if initialization succeeded | |
*/ | |
UFUNCTION(BlueprintCallable, Category = "Sign In | Google") | |
static bool Initialize(); | |
/** | |
* Does the Google Subsystem exist and is initialized | |
*/ | |
UFUNCTION(BlueprintCallable, Category = "Sign In | Google") | |
static bool HasGoogleOnlineSubsystem() { return mOnlineSubsystem != nullptr; } | |
/** | |
* Do sign in using Google asynchronously and call callback on completion | |
* | |
* <param name="LocalUserNumber">Which local user to do sign in for</param> | |
* <param name="Callback">Callback utilized when method is called from Blueprints</param> | |
*/ | |
UFUNCTION(BlueprintCallable, Category = "Sign In | Google") | |
static bool SignInWithGoogle(int LocalUserNumber, const FLoginCompletedCallback Callback); | |
private: | |
static void LoginCompletedHandler(int LocalUserNumber, bool wasSuccessful, const FUniqueNetId& UserId, const FString& Error, const FLoginCompletedCallback BPCallback); | |
// Handle for keeping track of a google subsystem login process | |
static FDelegateHandle LoginDelegateHandle; | |
static IOnlineSubsystem* mOnlineSubsystem; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Add the generic Online Subsystem to your project | |
PrivateDependencyModuleNames.AddRange(new string[] { "OnlineSubsystem" }); | |
// Dynamically add Google Online Subsystem for platforms where you intend to use it | |
if (Target.Platform == UnrealTargetPlatform.Android) | |
{ | |
DynamicallyLoadedModuleNames.Add("OnlineSubsystemGoogle"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment