-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
All-in-one Login with Oauth Flow (#20)
* All-in-one Login with Oauth Flow * Update Thirdweb.Transactions.Tests.cs --------- Signed-off-by: Firekeeper <[email protected]>
- Loading branch information
1 parent
d0d24d7
commit bd059d4
Showing
5 changed files
with
261 additions
and
31 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
using Newtonsoft.Json; | ||
using Nethereum.RPC.Eth.DTOs; | ||
using Nethereum.Hex.HexTypes; | ||
using System.Diagnostics; | ||
|
||
DotEnv.Load(); | ||
|
||
|
@@ -22,32 +23,45 @@ | |
|
||
// Create wallets (this is an advanced use case, typically one wallet is plenty) | ||
var privateKeyWallet = await PrivateKeyWallet.Create(client: client, privateKeyHex: privateKey); | ||
var inAppWallet = await InAppWallet.Create(client: client, email: "[email protected]"); // or email: null, phoneNumber: "+1234567890" | ||
|
||
// // Reset InAppWallet (optional step for testing login flow) | ||
// if (await inAppWallet.IsConnected()) | ||
// { | ||
// await inAppWallet.Disconnect(); | ||
// } | ||
// var inAppWallet = await InAppWallet.Create(client: client, email: "[email protected]"); // or email: null, phoneNumber: "+1234567890" | ||
var inAppWallet = await InAppWallet.Create(client: client, authprovider: AuthProvider.Google); // or email: null, phoneNumber: "+1234567890" | ||
|
||
// Reset InAppWallet (optional step for testing login flow) | ||
if (await inAppWallet.IsConnected()) | ||
{ | ||
await inAppWallet.Disconnect(); | ||
} | ||
|
||
// Relog if InAppWallet not logged in | ||
if (!await inAppWallet.IsConnected()) | ||
{ | ||
await inAppWallet.SendOTP(); | ||
Console.WriteLine("Please submit the OTP."); | ||
var otp = Console.ReadLine(); | ||
(var inAppWalletAddress, var canRetry) = await inAppWallet.SubmitOTP(otp); | ||
if (inAppWalletAddress == null && canRetry) | ||
{ | ||
Console.WriteLine("Please submit the OTP again."); | ||
otp = Console.ReadLine(); | ||
(inAppWalletAddress, _) = await inAppWallet.SubmitOTP(otp); | ||
} | ||
if (inAppWalletAddress == null) | ||
{ | ||
Console.WriteLine("OTP login failed. Please try again."); | ||
return; | ||
} | ||
var address = await inAppWallet.LoginWithOauth( | ||
isMobile: false, | ||
(url) => | ||
{ | ||
var psi = new ProcessStartInfo { FileName = url, UseShellExecute = true }; | ||
_ = Process.Start(psi); | ||
}, | ||
"thirdweb://", | ||
new InAppWalletBrowser() | ||
); | ||
Console.WriteLine($"InAppWallet address: {address}"); | ||
// await inAppWallet.SendOTP(); | ||
// Console.WriteLine("Please submit the OTP."); | ||
// var otp = Console.ReadLine(); | ||
// (var inAppWalletAddress, var canRetry) = await inAppWallet.SubmitOTP(otp); | ||
// if (inAppWalletAddress == null && canRetry) | ||
// { | ||
// Console.WriteLine("Please submit the OTP again."); | ||
// otp = Console.ReadLine(); | ||
// (inAppWalletAddress, _) = await inAppWallet.SubmitOTP(otp); | ||
// } | ||
// if (inAppWalletAddress == null) | ||
// { | ||
// Console.WriteLine("OTP login failed. Please try again."); | ||
// return; | ||
// } | ||
} | ||
|
||
// Create smart wallet with InAppWallet signer | ||
|
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
public interface IThirdwebBrowser | ||
{ | ||
Task<BrowserResult> Login(string loginUrl, string redirectUrl, Action<string> browserOpenAction, CancellationToken cancellationToken = default); | ||
} | ||
|
||
public enum BrowserStatus | ||
{ | ||
Success, | ||
UserCanceled, | ||
Timeout, | ||
UnknownError, | ||
} | ||
|
||
public class BrowserResult | ||
{ | ||
public BrowserStatus status { get; } | ||
|
||
public string callbackUrl { get; } | ||
|
||
public string error { get; } | ||
|
||
public BrowserResult(BrowserStatus status, string callbackUrl) | ||
{ | ||
this.status = status; | ||
this.callbackUrl = callbackUrl; | ||
} | ||
|
||
public BrowserResult(BrowserStatus status, string callbackUrl, string error) | ||
{ | ||
this.status = status; | ||
this.callbackUrl = callbackUrl; | ||
this.error = error; | ||
} | ||
} |
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
103 changes: 103 additions & 0 deletions
103
Thirdweb/Thirdweb.Wallets/InAppWallet/InAppWalletBrowser.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
using System.Net; | ||
|
||
namespace Thirdweb | ||
{ | ||
public class InAppWalletBrowser : IThirdwebBrowser | ||
{ | ||
private TaskCompletionSource<BrowserResult> _taskCompletionSource; | ||
|
||
private readonly string closePageResponse = | ||
@" | ||
<html> | ||
<head> | ||
<style> | ||
body { | ||
font-family: Arial, sans-serif; | ||
background-color: #2c2c2c; | ||
color: #ffffff; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
height: 100vh; | ||
flex-direction: column; | ||
} | ||
.container { | ||
background-color: #3c3c3c; | ||
padding: 20px; | ||
border-radius: 10px; | ||
box-shadow: 0 0 10px rgba(0,0,0,0.3); | ||
text-align: center; | ||
} | ||
.instruction { | ||
margin-top: 20px; | ||
font-size: 18px; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class='container'> | ||
<b>DONE!</b> | ||
<div class='instruction'> | ||
You can close this tab/window now. | ||
</div> | ||
</div> | ||
</body> | ||
</html>"; | ||
|
||
public async Task<BrowserResult> Login(string loginUrl, string redirectUrl, Action<string> browserOpenAction, CancellationToken cancellationToken = default) | ||
{ | ||
_taskCompletionSource = new TaskCompletionSource<BrowserResult>(); | ||
|
||
cancellationToken.Register(() => | ||
{ | ||
_taskCompletionSource?.TrySetCanceled(); | ||
}); | ||
|
||
using var httpListener = new HttpListener(); | ||
|
||
try | ||
{ | ||
redirectUrl = AddForwardSlashIfNecessary(redirectUrl); | ||
httpListener.Prefixes.Add(redirectUrl); | ||
httpListener.Start(); | ||
_ = httpListener.BeginGetContext(IncomingHttpRequest, httpListener); | ||
|
||
Console.WriteLine($"Opening browser with URL: {loginUrl}"); | ||
browserOpenAction.Invoke(loginUrl); | ||
|
||
var completedTask = await Task.WhenAny(_taskCompletionSource.Task, Task.Delay(TimeSpan.FromSeconds(30), cancellationToken)); | ||
return completedTask == _taskCompletionSource.Task ? await _taskCompletionSource.Task : new BrowserResult(BrowserStatus.Timeout, null, "The operation timed out."); | ||
} | ||
finally | ||
{ | ||
httpListener.Stop(); | ||
} | ||
} | ||
|
||
private void IncomingHttpRequest(IAsyncResult result) | ||
{ | ||
var httpListener = (HttpListener)result.AsyncState; | ||
var httpContext = httpListener.EndGetContext(result); | ||
var httpRequest = httpContext.Request; | ||
var httpResponse = httpContext.Response; | ||
var buffer = System.Text.Encoding.UTF8.GetBytes(closePageResponse); | ||
|
||
httpResponse.ContentLength64 = buffer.Length; | ||
var output = httpResponse.OutputStream; | ||
output.Write(buffer, 0, buffer.Length); | ||
output.Close(); | ||
|
||
_taskCompletionSource.SetResult(new BrowserResult(BrowserStatus.Success, httpRequest.Url.ToString())); | ||
} | ||
|
||
private string AddForwardSlashIfNecessary(string url) | ||
{ | ||
string forwardSlash = "/"; | ||
if (!url.EndsWith(forwardSlash)) | ||
{ | ||
url += forwardSlash; | ||
} | ||
return url; | ||
} | ||
} | ||
} |