Skip to content

Commit dccb386

Browse files
chore: add pkce support for windows
1 parent d2db0c6 commit dccb386

File tree

8 files changed

+719
-85
lines changed

8 files changed

+719
-85
lines changed

Source/Immutable/Private/Immutable/Actions/ImtblConnectImxAsyncAction.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void UImtblConnectionAsyncActions::DoConnect(TWeakObjectPtr<UImtblJSConnector> J
7373
{
7474
if (bIsPKCE)
7575
{
76-
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
76+
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
7777
Passport->ConnectPKCE(bIsConnectImx, UImmutablePassport::FImtblPassportResponseDelegate::CreateUObject(this, &UImtblConnectionAsyncActions::OnConnect));
7878
#endif
7979
}

Source/Immutable/Private/Immutable/ImmutableDataTypes.cpp

+22-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
#include "Immutable/ImmutableDataTypes.h"
44

5+
#if PLATFORM_WINDOWS
6+
#include "Immutable/Windows/ImmutablePKCEWindows.h"
7+
#endif
58

69
FString FImmutablePassportInitData::ToJsonString() const
710
{
@@ -29,20 +32,20 @@ FString FImmutablePassportInitData::ToJsonString() const
2932
TOptional<FImmutablePassportInitDeviceFlowData> FImmutablePassportInitDeviceFlowData::FromJsonString(const FString& JsonObjectString)
3033
{
3134
FImmutablePassportInitDeviceFlowData PassportConnect;
32-
35+
3336
if (!FJsonObjectConverter::JsonObjectStringToUStruct(JsonObjectString, &PassportConnect, 0, 0))
3437
{
3538
IMTBL_WARN("Could not parse response from JavaScript into the expected " "Passport connect format")
3639
return TOptional<FImmutablePassportInitDeviceFlowData>();
3740
}
38-
41+
3942
return PassportConnect;
4043
}
4144

4245
FString FImmutablePassportZkEvmRequestAccountsData::ToJsonString() const
4346
{
4447
FString OutString;
45-
48+
4649
FJsonObjectConverter::UStructToJsonObjectString(*this, OutString, 0, 0, 0, nullptr, false);
4750

4851
return OutString;
@@ -56,7 +59,7 @@ TOptional<FImmutablePassportZkEvmRequestAccountsData> FImmutablePassportZkEvmReq
5659
IMTBL_WARN("Could not parse response from JavaScript into the expected " "Passport ZkEvm request accounts format")
5760
return TOptional<FImmutablePassportZkEvmRequestAccountsData>();
5861
}
59-
62+
6063
return RequestAccounts;
6164
}
6265

@@ -71,7 +74,7 @@ TOptional<FImmutablePassportZkEvmRequestAccountsData> FImmutablePassportZkEvmReq
7174
IMTBL_ERR("Could not parse response from JavaScript into the expected " "Passport ZkEvm request accounts format")
7275
return TOptional<FImmutablePassportZkEvmRequestAccountsData>();
7376
}
74-
77+
7578
return RequestAccounts;
7679
}
7780

@@ -92,3 +95,17 @@ FString FImmutablePassportZkEvmGetBalanceData::ToJsonString() const
9295

9396
return OutString;
9497
}
98+
99+
void UImmutablePKCEData::BeginDestroy()
100+
{
101+
Reset();
102+
103+
UObject::BeginDestroy();
104+
}
105+
106+
void UImmutablePKCEData::Reset()
107+
{
108+
#if PLATFORM_WINDOWS
109+
UImmutablePKCEWindows::Reset(this);
110+
#endif
111+
}

Source/Immutable/Private/Immutable/ImmutablePassport.cpp

+85-35
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#include "GenericPlatform/GenericPlatformProcess.h"
2424
#include "Mac/ImmutableMac.h"
2525
#endif
26+
#if PLATFORM_WINDOWS
27+
#include "Immutable/Windows/ImmutablePKCEWindows.h"
28+
#endif
2629

2730
#define PASSPORT_SAVE_GAME_SLOT_NAME TEXT("Immutable")
2831

@@ -101,10 +104,22 @@ void UImmutablePassport::Connect(bool IsConnectImx, bool TryToRelogin, const FIm
101104
}
102105
}
103106

104-
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
107+
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
105108
void UImmutablePassport::ConnectPKCE(bool IsConnectImx, const FImtblPassportResponseDelegate& ResponseDelegate)
106109
{
107110
SetStateFlags(IPS_CONNECTING | IPS_PKCE);
111+
112+
#if PLATFORM_WINDOWS
113+
// Verify PKCEData is null before initializing to ensure we're not overriding an active PKCE operation.
114+
// A non-null value indicates another PKCE operation is already in progress.
115+
ensureAlways(!PKCEData);
116+
PKCEData = UImmutablePKCEWindows::Initialise(InitData);
117+
if (PKCEData)
118+
{
119+
PKCEData->DynamicMulticastDelegate_DeepLinkCallback.AddDynamic(this, &ThisClass::OnDeepLinkActivated);
120+
}
121+
#endif
122+
108123
if (IsConnectImx)
109124
{
110125
SetStateFlags(IPS_IMX);
@@ -117,7 +132,16 @@ void UImmutablePassport::ConnectPKCE(bool IsConnectImx, const FImtblPassportResp
117132

118133
void UImmutablePassport::Logout(bool DoHardLogout, const FImtblPassportResponseDelegate& ResponseDelegate)
119134
{
120-
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
135+
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
136+
// Verify PKCEData is null before initializing to ensure we're not overriding an active PKCE operation.
137+
// A non-null value indicates another PKCE operation is already in progress.
138+
ensureAlways(!PKCEData);
139+
PKCEData = UImmutablePKCEWindows::Initialise(InitData);
140+
if (PKCEData)
141+
{
142+
PKCEData->DynamicMulticastDelegate_DeepLinkCallback.AddDynamic(this, &ThisClass::OnDeepLinkActivated);
143+
}
144+
121145
if (IsStateFlagsSet(IPS_PKCE))
122146
{
123147
PKCELogoutResponseDelegate = ResponseDelegate;
@@ -392,7 +416,7 @@ TOptional<UImmutablePassport::FImtblPassportResponseDelegate> UImmutablePassport
392416

393417
void UImmutablePassport::OnInitializeResponse(FImtblJSResponse Response)
394418
{
395-
if (auto ResponseDelegate = GetResponseDelegate(Response))
419+
if (TOptional<FImtblPassportResponseDelegate> ResponseDelegate = GetResponseDelegate(Response))
396420
{
397421
FString Error;
398422

@@ -470,43 +494,55 @@ void UImmutablePassport::OnLogoutResponse(FImtblJSResponse Response)
470494

471495
return;
472496
}
473-
474-
FString Url;
475-
FString ErrorMessage;
497+
498+
auto Logout = [this](const FImtblJSResponse& Response)
499+
{
500+
TOptional<FImtblPassportResponseDelegate> ResponseDelegate = GetResponseDelegate(Response);
501+
502+
FString Url;
503+
Response.JsonObject->TryGetStringField(TEXT("result"), Url);
504+
505+
FString ErrorMessage;
506+
FPlatformProcess::LaunchURL(*Url, nullptr, &ErrorMessage);
507+
508+
if (ErrorMessage.Len())
509+
{
510+
ErrorMessage = "Failed to launch browser: " + ErrorMessage;
511+
IMTBL_ERR("%s", *ErrorMessage);
512+
ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{false, ErrorMessage, Response});
513+
}
514+
};
476515

477516
ResetStateFlags(IPS_HARDLOGOUT);
517+
518+
FString Url;
478519
Response.JsonObject->TryGetStringField(TEXT("result"), Url);
520+
479521
if (!Url.IsEmpty())
480522
{
481-
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
523+
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
482524
if (IsStateFlagsSet(IPS_PKCE))
483525
{
484-
OnHandleDeepLink = FImtblPassportHandleDeepLinkDelegate::CreateUObject(this, &UImmutablePassport::OnDeepLinkActivated);
526+
OnHandleDeepLink.AddUObject(this, &UImmutablePassport::OnDeepLinkActivated);
485527
#if PLATFORM_ANDROID
486528
LaunchAndroidUrl(Url);
487529
#elif PLATFORM_IOS
488530
[[ImmutableIOS instance] launchUrl:TCHAR_TO_ANSI(*Url)];
489531
#elif PLATFORM_MAC
490532
[[ImmutableMac instance] launchUrl:TCHAR_TO_ANSI(*Url) forRedirectUri:TCHAR_TO_ANSI(*InitData.logoutRedirectUri)];
533+
#endif
534+
#if PLATFORM_WINDOWS
535+
Logout(Response);
491536
#endif
492537
}
493538
else
494539
{
495540
#endif
496-
FPlatformProcess::LaunchURL(*Url, nullptr, &ErrorMessage);
497-
if (ErrorMessage.Len())
498-
{
499-
Message = "Failed to connect to Browser: " + ErrorMessage;
500-
501-
IMTBL_ERR("%s", *Message);
502-
ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ false, Message, Response });
503-
504-
return;
505-
}
541+
Logout(Response);
506542
Analytics->Track(UImmutableAnalytics::EEventName::COMPLETE_LOGOUT);
507543
IMTBL_LOG("Logged out")
508544
ResponseDelegate->ExecuteIfBound(FImmutablePassportResult{ Response.success });
509-
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
545+
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
510546
}
511547
#endif
512548
}
@@ -517,7 +553,7 @@ void UImmutablePassport::OnLogoutResponse(FImtblJSResponse Response)
517553
ResetStateFlags(IPS_CONNECTED);
518554
}
519555

520-
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
556+
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC | PLATFORM_WINDOWS
521557
void UImmutablePassport::OnGetPKCEAuthUrlResponse(FImtblJSResponse Response)
522558
{
523559
if (PKCEResponseDelegate.IsBound())
@@ -532,7 +568,7 @@ void UImmutablePassport::OnGetPKCEAuthUrlResponse(FImtblJSResponse Response)
532568
else
533569
{
534570
// Handle deeplink calls
535-
OnHandleDeepLink = FImtblPassportHandleDeepLinkDelegate::CreateUObject(this, &UImmutablePassport::OnDeepLinkActivated);
571+
OnHandleDeepLink.AddUObject(this, &UImmutablePassport::OnDeepLinkActivated);
536572

537573
Msg = Response.JsonObject->GetStringField(TEXT("result")).Replace(TEXT(" "), TEXT("+"));
538574
#if PLATFORM_ANDROID
@@ -542,6 +578,17 @@ void UImmutablePassport::OnGetPKCEAuthUrlResponse(FImtblJSResponse Response)
542578
[[ImmutableIOS instance] launchUrl:TCHAR_TO_ANSI(*Msg)];
543579
#elif PLATFORM_MAC
544580
[[ImmutableMac instance] launchUrl:TCHAR_TO_ANSI(*Msg) forRedirectUri:TCHAR_TO_ANSI(*InitData.redirectUri)];
581+
#elif PLATFORM_WINDOWS
582+
FString ErrorMessage;
583+
FPlatformProcess::LaunchURL(*Msg, nullptr, &ErrorMessage);
584+
if (!ErrorMessage.IsEmpty())
585+
{
586+
ErrorMessage = "Failed to launch browser: " + ErrorMessage;
587+
IMTBL_ERR("%s", *ErrorMessage);
588+
PKCEResponseDelegate.ExecuteIfBound(FImmutablePassportResult{false, ErrorMessage});
589+
PKCEResponseDelegate.Unbind();
590+
ResetStateFlags(IPS_PKCE | IPS_CONNECTING);
591+
}
545592
#endif
546593
}
547594
}
@@ -583,7 +630,6 @@ void UImmutablePassport::OnConnectPKCEResponse(FImtblJSResponse Response)
583630
}
584631
ResetStateFlags(IPS_COMPLETING_PKCE);
585632
}
586-
#endif
587633

588634
void UImmutablePassport::OnConfirmCodeResponse(FImtblJSResponse Response)
589635
{
@@ -666,11 +712,9 @@ void UImmutablePassport::LoadPassportSettings()
666712
}
667713
}
668714

669-
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
670-
void UImmutablePassport::OnDeepLinkActivated(FString DeepLink)
715+
void UImmutablePassport::OnDeepLinkActivated(const FString& DeepLink)
671716
{
672-
IMTBL_LOG_FUNC("URL : %s", *DeepLink);
673-
OnHandleDeepLink = nullptr;
717+
OnHandleDeepLink.Clear();
674718
if (DeepLink.StartsWith(InitData.logoutRedirectUri))
675719
{
676720
// execute on game thread to prevent call to Passport instance from another thread
@@ -690,6 +734,8 @@ void UImmutablePassport::OnDeepLinkActivated(FString DeepLink)
690734
{
691735
CompleteLoginPKCEFlow(DeepLink);
692736
}
737+
738+
PKCEData = nullptr;
693739
}
694740

695741
void UImmutablePassport::CompleteLoginPKCEFlow(FString Url)
@@ -739,30 +785,34 @@ void UImmutablePassport::CompleteLoginPKCEFlow(FString Url)
739785
FImtblJSResponseDelegate::CreateUObject(this, &UImmutablePassport::OnConnectPKCEResponse));
740786
}
741787
}
742-
743788
#endif
744789

745-
#if PLATFORM_ANDROID | PLATFORM_IOS | PLATFORM_MAC
746790
#if PLATFORM_ANDROID
747791
// Called from Android JNI
748792
void UImmutablePassport::HandleDeepLink(FString DeepLink) const
749-
{
750-
#elif PLATFORM_IOS | PLATFORM_MAC
751-
793+
#endif
794+
#if PLATFORM_IOS | PLATFORM_MAC
752795
// Called from iOS Objective C
753796
void UImmutablePassport::HandleDeepLink(NSString* sDeepLink) const
797+
#endif
798+
#if PLATFORM_WINDOWS
799+
void UImmutablePassport::HandleDeepLink(FString DeepLink) const
800+
#endif
754801
{
802+
#if PLATFORM_IOS | PLATFORM_MAC
755803
FString DeepLink = FString(UTF8_TO_TCHAR([sDeepLink UTF8String]));
756804
IMTBL_LOG("Handle Deep Link: %s", *DeepLink);
757805
#endif
758-
759-
if (!OnHandleDeepLink.ExecuteIfBound(DeepLink))
806+
#if PLATFORM_WINDOWS
807+
if (PKCEData)
760808
{
761-
IMTBL_WARN("OnHandleDeepLink delegate was not called");
809+
UImmutablePKCEWindows::HandleDeepLink(PKCEData, DeepLink);
762810
}
763-
}
764811
#endif
765812

813+
OnHandleDeepLink.Broadcast(DeepLink);
814+
}
815+
766816
#if PLATFORM_ANDROID
767817
void UImmutablePassport::HandleOnLoginPKCEDismissed()
768818
{

0 commit comments

Comments
 (0)