Skip to content

Commit e631a5d

Browse files
authored
Backend Wallet Auth (#120)
1 parent 0891058 commit e631a5d

File tree

6 files changed

+84
-16
lines changed

6 files changed

+84
-16
lines changed

Thirdweb.Console/Program.cs

+12
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,18 @@
325325

326326
#endregion
327327

328+
#region Backend Wallet Auth
329+
330+
// var inAppWalletBackend = await InAppWallet.Create(client: client, authProvider: AuthProvider.Backend, walletSecret: "very-secret");
331+
// if (!await inAppWalletBackend.IsConnected())
332+
// {
333+
// _ = await inAppWalletBackend.LoginWithBackend();
334+
// }
335+
// var inAppWalletBackendAddress = await inAppWalletBackend.GetAddress();
336+
// Console.WriteLine($"InAppWallet Backend address: {inAppWalletBackendAddress}");
337+
338+
#endregion
339+
328340
#region Account Linking
329341

330342
// var inAppWalletMain = await InAppWallet.Create(client: client, authProvider: AuthProvider.Telegram);

Thirdweb/Thirdweb.Wallets/InAppWallet/EcosystemWallet/EcosystemWallet.cs

+38-9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public partial class EcosystemWallet : IThirdwebWallet
2525
internal readonly string PhoneNumber;
2626
internal readonly string AuthProvider;
2727
internal readonly string LegacyEncryptionKey;
28+
internal readonly string WalletSecret;
2829

2930
internal string Address;
3031

@@ -46,7 +47,8 @@ internal EcosystemWallet(
4647
string phoneNumber,
4748
string authProvider,
4849
IThirdwebWallet siweSigner,
49-
string legacyEncryptionKey
50+
string legacyEncryptionKey,
51+
string walletSecret
5052
)
5153
{
5254
this.Client = client;
@@ -59,6 +61,7 @@ string legacyEncryptionKey
5961
this.PhoneNumber = phoneNumber;
6062
this.AuthProvider = authProvider;
6163
this.SiweSigner = siweSigner;
64+
this.WalletSecret = walletSecret;
6265
}
6366

6467
#region Creation
@@ -75,6 +78,7 @@ string legacyEncryptionKey
7578
/// <param name="storageDirectoryPath">The path to the storage directory.</param>
7679
/// <param name="siweSigner">The SIWE signer wallet for SIWE authentication.</param>
7780
/// <param name="legacyEncryptionKey">The encryption key that is no longer required but was used in the past. Only pass this if you had used custom auth before this was deprecated.</param>
81+
/// <param name="walletSecret">The wallet secret for Backend authentication.</param>
7882
/// <returns>A task that represents the asynchronous operation. The task result contains the created in-app wallet.</returns>
7983
/// <exception cref="ArgumentException">Thrown when required parameters are not provided.</exception>
8084
public static async Task<EcosystemWallet> Create(
@@ -86,7 +90,8 @@ public static async Task<EcosystemWallet> Create(
8690
AuthProvider authProvider = Thirdweb.AuthProvider.Default,
8791
string storageDirectoryPath = null,
8892
IThirdwebWallet siweSigner = null,
89-
string legacyEncryptionKey = null
93+
string legacyEncryptionKey = null,
94+
string walletSecret = null
9095
)
9196
{
9297
if (client == null)
@@ -117,6 +122,7 @@ public static async Task<EcosystemWallet> Create(
117122
Thirdweb.AuthProvider.Github => "Github",
118123
Thirdweb.AuthProvider.Twitch => "Twitch",
119124
Thirdweb.AuthProvider.Steam => "Steam",
125+
Thirdweb.AuthProvider.Backend => "Backend",
120126
Thirdweb.AuthProvider.Default => string.IsNullOrEmpty(email) ? "Phone" : "Email",
121127
_ => throw new ArgumentException("Invalid AuthProvider"),
122128
};
@@ -150,15 +156,15 @@ public static async Task<EcosystemWallet> Create(
150156
try
151157
{
152158
var userAddress = await ResumeEnclaveSession(enclaveHttpClient, embeddedWallet, email, phoneNumber, authproviderStr).ConfigureAwait(false);
153-
return new EcosystemWallet(ecosystemId, ecosystemPartnerId, client, embeddedWallet, enclaveHttpClient, email, phoneNumber, authproviderStr, siweSigner, legacyEncryptionKey)
159+
return new EcosystemWallet(ecosystemId, ecosystemPartnerId, client, embeddedWallet, enclaveHttpClient, email, phoneNumber, authproviderStr, siweSigner, legacyEncryptionKey, walletSecret)
154160
{
155161
Address = userAddress
156162
};
157163
}
158164
catch
159165
{
160166
enclaveHttpClient.RemoveHeader("Authorization");
161-
return new EcosystemWallet(ecosystemId, ecosystemPartnerId, client, embeddedWallet, enclaveHttpClient, email, phoneNumber, authproviderStr, siweSigner, legacyEncryptionKey)
167+
return new EcosystemWallet(ecosystemId, ecosystemPartnerId, client, embeddedWallet, enclaveHttpClient, email, phoneNumber, authproviderStr, siweSigner, legacyEncryptionKey, walletSecret)
162168
{
163169
Address = null
164170
};
@@ -468,6 +474,13 @@ public async Task<List<LinkedAccount>> LinkAccount(
468474
}
469475
serverRes = await ecosystemWallet.PreAuth_Siwe(ecosystemWallet.SiweSigner, chainId.Value).ConfigureAwait(false);
470476
break;
477+
case "Backend":
478+
if (string.IsNullOrEmpty(ecosystemWallet.WalletSecret))
479+
{
480+
throw new ArgumentException("Cannot link account with a Backend wallet without a wallet secret.");
481+
}
482+
serverRes = await ecosystemWallet.PreAuth_Backend(ecosystemWallet.WalletSecret).ConfigureAwait(false);
483+
break;
471484
case "JWT":
472485
if (string.IsNullOrEmpty(jwt))
473486
{
@@ -692,12 +705,12 @@ public async Task<string> LoginWithOauth(
692705

693706
private async Task<Server.VerifyResult> PreAuth_Siwe(IThirdwebWallet siweSigner, BigInteger chainId)
694707
{
695-
if (this.SiweSigner == null)
708+
if (siweSigner == null)
696709
{
697710
throw new ArgumentNullException(nameof(siweSigner), "SIWE Signer wallet cannot be null.");
698711
}
699712

700-
if (!await this.SiweSigner.IsConnected().ConfigureAwait(false))
713+
if (!await siweSigner.IsConnected().ConfigureAwait(false))
701714
{
702715
throw new InvalidOperationException("SIWE Signer wallet must be connected as this operation requires it to sign a message.");
703716
}
@@ -716,6 +729,23 @@ public async Task<string> LoginWithSiwe(BigInteger chainId)
716729

717730
#endregion
718731

732+
#region Backend
733+
734+
private async Task<Server.VerifyResult> PreAuth_Backend(string walletSecret)
735+
{
736+
return string.IsNullOrEmpty(walletSecret)
737+
? throw new ArgumentException("Wallet secret cannot be null or empty.", nameof(walletSecret))
738+
: await this.EmbeddedWallet.SignInWithBackendAsync(walletSecret).ConfigureAwait(false);
739+
}
740+
741+
public async Task<string> LoginWithBackend()
742+
{
743+
var serverRes = await this.PreAuth_Backend(this.WalletSecret).ConfigureAwait(false);
744+
return await this.PostAuth(serverRes).ConfigureAwait(false);
745+
}
746+
747+
#endregion
748+
719749
#region Guest
720750

721751
private async Task<Server.VerifyResult> PreAuth_Guest()
@@ -746,13 +776,12 @@ public async Task<string> LoginWithGuest()
746776

747777
private async Task<Server.VerifyResult> PreAuth_JWT(string jwt)
748778
{
749-
return string.IsNullOrEmpty(jwt) ? throw new ArgumentException(nameof(jwt), "JWT cannot be null or empty.") : await this.EmbeddedWallet.SignInWithJwtAsync(jwt).ConfigureAwait(false);
779+
return string.IsNullOrEmpty(jwt) ? throw new ArgumentException("JWT cannot be null or empty.", nameof(jwt)) : await this.EmbeddedWallet.SignInWithJwtAsync(jwt).ConfigureAwait(false);
750780
}
751781

752782
public async Task<string> LoginWithJWT(string jwt)
753783
{
754-
var serverRes = string.IsNullOrEmpty(jwt) ? throw new ArgumentException("JWT cannot be null or empty.", nameof(jwt)) : await this.EmbeddedWallet.SignInWithJwtAsync(jwt).ConfigureAwait(false);
755-
784+
var serverRes = await this.PreAuth_JWT(jwt).ConfigureAwait(false);
756785
return await this.PostAuth(serverRes).ConfigureAwait(false);
757786
}
758787

Thirdweb/Thirdweb.Wallets/InAppWallet/EmbeddedWallet.Authentication/Server.cs

+14-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ internal abstract class ServerBase
1616
internal abstract Task<LoginPayloadData> FetchSiwePayloadAsync(string address, string chainId);
1717
internal abstract Task<Server.VerifyResult> VerifySiweAsync(LoginPayloadData payload, string signature);
1818

19+
internal abstract Task<Server.VerifyResult> VerifyBackendAsync(string walletSecret);
20+
1921
internal abstract Task<Server.VerifyResult> VerifyGuestAsync(string sessionId);
2022

2123
internal abstract Task<string> SendEmailOtpAsync(string emailAddress);
@@ -155,8 +157,19 @@ internal override async Task<VerifyResult> VerifySiweAsync(LoginPayloadData payl
155157
return await this.InvokeAuthResultLambdaAsync(authResult).ConfigureAwait(false);
156158
}
157159

158-
// login/guest
160+
// login/backend
161+
internal override async Task<VerifyResult> VerifyBackendAsync(string walletSecret)
162+
{
163+
var uri = MakeUri2024("/login/backend");
164+
var content = MakeHttpContent(new { walletSecret });
165+
var response = await this._httpClient.PostAsync(uri.ToString(), content).ConfigureAwait(false);
166+
await CheckStatusCodeAsync(response).ConfigureAwait(false);
159167

168+
var authResult = await DeserializeAsync<AuthResultType>(response).ConfigureAwait(false);
169+
return await this.InvokeAuthResultLambdaAsync(authResult).ConfigureAwait(false);
170+
}
171+
172+
// login/guest
160173
internal override async Task<VerifyResult> VerifyGuestAsync(string sessionId)
161174
{
162175
var uri = MakeUri2024("/login/guest/callback");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Thirdweb.EWS;
2+
3+
internal partial class EmbeddedWallet
4+
{
5+
public async Task<Server.VerifyResult> SignInWithBackendAsync(string walletSecret)
6+
{
7+
return await this._server.VerifyBackendAsync(walletSecret).ConfigureAwait(false);
8+
}
9+
}

Thirdweb/Thirdweb.Wallets/InAppWallet/InAppWallet.Types.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public enum AuthProvider
2323
Coinbase,
2424
Github,
2525
Twitch,
26-
Steam
26+
Steam,
27+
Backend
2728
}
2829

2930
/// <summary>

Thirdweb/Thirdweb.Wallets/InAppWallet/InAppWallet.cs

+9-5
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ internal InAppWallet(
1616
string authProvider,
1717
IThirdwebWallet siweSigner,
1818
string address,
19-
string legacyEncryptionKey
19+
string legacyEncryptionKey,
20+
string walletSecret
2021
)
21-
: base(null, null, client, embeddedWallet, httpClient, email, phoneNumber, authProvider, siweSigner, legacyEncryptionKey)
22+
: base(null, null, client, embeddedWallet, httpClient, email, phoneNumber, authProvider, siweSigner, legacyEncryptionKey, walletSecret)
2223
{
2324
this.Address = address;
2425
}
@@ -33,6 +34,7 @@ string legacyEncryptionKey
3334
/// <param name="storageDirectoryPath">The path to the storage directory.</param>
3435
/// <param name="siweSigner">The SIWE signer wallet for SIWE authentication.</param>
3536
/// <param name="legacyEncryptionKey">The encryption key that is no longer required but was used in the past. Only pass this if you had used custom auth before this was deprecated.</param>
37+
/// <param name="walletSecret">The wallet secret for backend authentication.</param>
3638
/// <returns>A task that represents the asynchronous operation. The task result contains the created in-app wallet.</returns>
3739
/// <exception cref="ArgumentException">Thrown when required parameters are not provided.</exception>
3840
public static async Task<InAppWallet> Create(
@@ -42,11 +44,12 @@ public static async Task<InAppWallet> Create(
4244
AuthProvider authProvider = Thirdweb.AuthProvider.Default,
4345
string storageDirectoryPath = null,
4446
IThirdwebWallet siweSigner = null,
45-
string legacyEncryptionKey = null
47+
string legacyEncryptionKey = null,
48+
string walletSecret = null
4649
)
4750
{
4851
storageDirectoryPath ??= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Thirdweb", "InAppWallet");
49-
var ecoWallet = await Create(client, null, null, email, phoneNumber, authProvider, storageDirectoryPath, siweSigner, legacyEncryptionKey);
52+
var ecoWallet = await Create(client, null, null, email, phoneNumber, authProvider, storageDirectoryPath, siweSigner, legacyEncryptionKey, walletSecret);
5053
return new InAppWallet(
5154
ecoWallet.Client,
5255
ecoWallet.EmbeddedWallet,
@@ -56,7 +59,8 @@ public static async Task<InAppWallet> Create(
5659
ecoWallet.AuthProvider,
5760
ecoWallet.SiweSigner,
5861
ecoWallet.Address,
59-
ecoWallet.LegacyEncryptionKey
62+
ecoWallet.LegacyEncryptionKey,
63+
ecoWallet.WalletSecret
6064
);
6165
}
6266
}

0 commit comments

Comments
 (0)