From a064c455a605c9f7fca956a084e876a7230c6bbf Mon Sep 17 00:00:00 2001 From: Gabriele Picco Date: Fri, 21 Jun 2024 09:21:33 +0200 Subject: [PATCH] :sparkles: Update Web3Auth SDK to 3.0.0 (#226) * :sparkles: Update Web3Auth SDK to 3.0.0 * :bookmark: Bump SDK version 1.2.5 --- .../Plugins/Web3AuthSDK/Api/Web3AuthApi.cs | 2 +- .../Plugins/Web3AuthSDK/Types/ChainConfig.cs | 13 ++ .../Web3AuthSDK/Types/ChainConfig.cs.meta | 11 ++ .../Plugins/Web3AuthSDK/Types/LoginParams.cs | 12 +- .../Plugins/Web3AuthSDK/Types/MfaSettings.cs | 10 +- Runtime/Plugins/Web3AuthSDK/Types/Provider.cs | 6 +- .../Web3AuthSDK/Types/SessionResponse.cs | 4 + .../Web3AuthSDK/Types/SessionResponse.cs.meta | 11 ++ Runtime/Plugins/Web3AuthSDK/Types/UserInfo.cs | 2 +- .../Web3AuthSDK/Types/Web3AuthOptions.cs | 20 +- Runtime/Plugins/Web3AuthSDK/Web3Auth.cs | 180 ++++++++++++++++-- package.json | 2 +- 12 files changed, 232 insertions(+), 41 deletions(-) create mode 100644 Runtime/Plugins/Web3AuthSDK/Types/ChainConfig.cs create mode 100644 Runtime/Plugins/Web3AuthSDK/Types/ChainConfig.cs.meta create mode 100644 Runtime/Plugins/Web3AuthSDK/Types/SessionResponse.cs create mode 100644 Runtime/Plugins/Web3AuthSDK/Types/SessionResponse.cs.meta diff --git a/Runtime/Plugins/Web3AuthSDK/Api/Web3AuthApi.cs b/Runtime/Plugins/Web3AuthSDK/Api/Web3AuthApi.cs index aaf4afea..5872b891 100644 --- a/Runtime/Plugins/Web3AuthSDK/Api/Web3AuthApi.cs +++ b/Runtime/Plugins/Web3AuthSDK/Api/Web3AuthApi.cs @@ -8,7 +8,7 @@ public class Web3AuthApi { static Web3AuthApi instance; - static string baseAddress = "https://broadcast-server.tor.us"; + static string baseAddress = "https://session.web3auth.io"; public static Web3AuthApi getInstance() { diff --git a/Runtime/Plugins/Web3AuthSDK/Types/ChainConfig.cs b/Runtime/Plugins/Web3AuthSDK/Types/ChainConfig.cs new file mode 100644 index 00000000..27df1de3 --- /dev/null +++ b/Runtime/Plugins/Web3AuthSDK/Types/ChainConfig.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +#nullable enable +public class ChainConfig { + public Web3Auth.ChainNamespace? chainNamespace { get; set; } = Web3Auth.ChainNamespace.EIP155; + public int decimals { get; set; } = 18; + public string blockExplorerUrl { get; set; } = null; + public string chainId { get; set; } + public string displayName { get; set; } = null; + public string logo { get; set; } = null; + public string rpcTarget { get; set; } + public string ticker { get; set; } = null; + public string tickerName { get; set; } = null; +} \ No newline at end of file diff --git a/Runtime/Plugins/Web3AuthSDK/Types/ChainConfig.cs.meta b/Runtime/Plugins/Web3AuthSDK/Types/ChainConfig.cs.meta new file mode 100644 index 00000000..e6abf844 --- /dev/null +++ b/Runtime/Plugins/Web3AuthSDK/Types/ChainConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 14f23cb8321c8456cab023bf500e0d6e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Plugins/Web3AuthSDK/Types/LoginParams.cs b/Runtime/Plugins/Web3AuthSDK/Types/LoginParams.cs index 8c6aa621..ff3f7f48 100644 --- a/Runtime/Plugins/Web3AuthSDK/Types/LoginParams.cs +++ b/Runtime/Plugins/Web3AuthSDK/Types/LoginParams.cs @@ -1,22 +1,14 @@ using System; -using UnityEngine.Scripting; -[Preserve] -[Serializable] public class LoginParams { - [Preserve] public Provider loginProvider { get; set; } - [Preserve] public string dappShare { get; set; } - [Preserve] public ExtraLoginOptions extraLoginOptions { get; set; } - [Preserve] public Uri redirectUrl { get; set; } - [Preserve] public string appState { get; set; } - [Preserve] public MFALevel mfaLevel { get; set; } - [Preserve] + public Curve curve { get; set; } = Curve.SECP256K1; + public string dappUrl { get; set; } } \ No newline at end of file diff --git a/Runtime/Plugins/Web3AuthSDK/Types/MfaSettings.cs b/Runtime/Plugins/Web3AuthSDK/Types/MfaSettings.cs index 975ffa9d..aafdde1a 100644 --- a/Runtime/Plugins/Web3AuthSDK/Types/MfaSettings.cs +++ b/Runtime/Plugins/Web3AuthSDK/Types/MfaSettings.cs @@ -1,22 +1,26 @@ -#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. - public class MfaSettings { public MfaSetting? deviceShareFactor { get; set; } public MfaSetting? backUpShareFactor { get; set; } public MfaSetting? socialBackupFactor { get; set; } public MfaSetting? passwordFactor { get; set; } + public MfaSetting? passkeysFactor { get; set; } + public MfaSetting? authenticatorFactor { get; set; } // Constructors public MfaSettings( MfaSetting? deviceShareFactor, MfaSetting? backUpShareFactor, MfaSetting? socialBackupFactor, - MfaSetting? passwordFactor) + MfaSetting? passwordFactor, + MfaSetting? passkeysFactor, + MfaSetting? authenticatorFactor) { this.deviceShareFactor = deviceShareFactor; this.backUpShareFactor = backUpShareFactor; this.socialBackupFactor = socialBackupFactor; this.passwordFactor = passwordFactor; + this.passkeysFactor = passkeysFactor; + this.authenticatorFactor = authenticatorFactor; } } \ No newline at end of file diff --git a/Runtime/Plugins/Web3AuthSDK/Types/Provider.cs b/Runtime/Plugins/Web3AuthSDK/Types/Provider.cs index a2269a8d..3b926c84 100644 --- a/Runtime/Plugins/Web3AuthSDK/Types/Provider.cs +++ b/Runtime/Plugins/Web3AuthSDK/Types/Provider.cs @@ -38,5 +38,9 @@ public enum Provider [EnumMember(Value = "jwt")] JWT, [EnumMember(Value = "CUSTOM_VERIFIER")] - CUSTOM_VERIFIER + CUSTOM_VERIFIER, + [EnumMember(Value = "sms_passwordless")] + SMS_PASSWORDLESS, + [EnumMember(Value = "farcaster")] + FARCASTER } \ No newline at end of file diff --git a/Runtime/Plugins/Web3AuthSDK/Types/SessionResponse.cs b/Runtime/Plugins/Web3AuthSDK/Types/SessionResponse.cs new file mode 100644 index 00000000..ae516fee --- /dev/null +++ b/Runtime/Plugins/Web3AuthSDK/Types/SessionResponse.cs @@ -0,0 +1,4 @@ +public class SessionResponse +{ + public string sessionId; +} \ No newline at end of file diff --git a/Runtime/Plugins/Web3AuthSDK/Types/SessionResponse.cs.meta b/Runtime/Plugins/Web3AuthSDK/Types/SessionResponse.cs.meta new file mode 100644 index 00000000..4505d66e --- /dev/null +++ b/Runtime/Plugins/Web3AuthSDK/Types/SessionResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: daf6cdeb659614fd6a31d7300f309c76 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Plugins/Web3AuthSDK/Types/UserInfo.cs b/Runtime/Plugins/Web3AuthSDK/Types/UserInfo.cs index db2b5aaa..c76255de 100644 --- a/Runtime/Plugins/Web3AuthSDK/Types/UserInfo.cs +++ b/Runtime/Plugins/Web3AuthSDK/Types/UserInfo.cs @@ -1,4 +1,4 @@ -using System; +using System; using UnityEngine.Scripting; [Serializable] diff --git a/Runtime/Plugins/Web3AuthSDK/Types/Web3AuthOptions.cs b/Runtime/Plugins/Web3AuthSDK/Types/Web3AuthOptions.cs index 897bdfae..2fb8d670 100644 --- a/Runtime/Plugins/Web3AuthSDK/Types/Web3AuthOptions.cs +++ b/Runtime/Plugins/Web3AuthSDK/Types/Web3AuthOptions.cs @@ -1,7 +1,6 @@ -using System; +using System; using System.Collections.Generic; #nullable enable -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public class Web3AuthOptions { public string clientId { get; set; } @@ -12,20 +11,31 @@ public class Web3AuthOptions { public string sdkUrl { get { if (buildEnv == Web3Auth.BuildEnv.STAGING) - return "https://staging-auth.web3auth.io/{openLoginVersion}"; + return "https://staging-auth.web3auth.io/v8"; else if (buildEnv == Web3Auth.BuildEnv.TESTING) return "https://develop-auth.web3auth.io"; else - return "https://auth.web3auth.io/{openLoginVersion}"; + return "https://auth.web3auth.io/v8"; } set { } } - public const string openLoginVersion = "v6"; + public string walletSdkUrl { + get { + if (buildEnv == Web3Auth.BuildEnv.STAGING) + return "https://staging-wallet.web3auth.io/v2"; + else if (buildEnv == Web3Auth.BuildEnv.TESTING) + return "https://develop-wallet.web3auth.io"; + else + return "https://wallet.web3auth.io/v2"; + } + set { } + } public WhiteLabelData? whiteLabel { get; set; } public Dictionary? loginConfig { get; set; } public bool? useCoreKitKey { get; set; } = false; public Web3Auth.ChainNamespace? chainNamespace { get; set; } = Web3Auth.ChainNamespace.EIP155; public MfaSettings? mfaSettings { get; set; } = null; public int sessionTime { get; set; } = 86400; + public ChainConfig? chainConfig { get; set; } } \ No newline at end of file diff --git a/Runtime/Plugins/Web3AuthSDK/Web3Auth.cs b/Runtime/Plugins/Web3AuthSDK/Web3Auth.cs index a75bc3b4..0d813324 100644 --- a/Runtime/Plugins/Web3AuthSDK/Web3Auth.cs +++ b/Runtime/Plugins/Web3AuthSDK/Web3Auth.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System; using System.Collections.Generic; @@ -35,7 +35,7 @@ public enum ThemeModes public enum Language { - en, de, ja, ko, zh, es, fr, pt, nl + en, de, ja, ko, zh, es, fr, pt, nl, tr } private Web3AuthOptions web3AuthOptions; @@ -45,6 +45,7 @@ public enum Language public event Action onLogin; public event Action onLogout; + public event Action onMFASetup; [SerializeField] private string clientId; @@ -232,7 +233,6 @@ private void IncomingHttpRequest(IAsyncResult result) System.IO.Stream output = httpResponse.OutputStream; output.Write(buffer, 0, buffer.Length); output.Close(); - string code = httpRequest.QueryString.Get("code"); if (!string.IsNullOrEmpty(code)) { @@ -244,7 +244,7 @@ private void IncomingHttpRequest(IAsyncResult result) } #endif - private async void request(string path, LoginParams loginParams = null, Dictionary extraParams = null) + private async void request(string path, LoginParams loginParams = null) { #if UNITY_STANDALONE || UNITY_EDITOR this.initParams["redirectUrl"] = StartLocalWebserver(); @@ -256,13 +256,14 @@ private async void request(string path, LoginParams loginParams = null, Dictiona Dictionary paramMap = new Dictionary(); paramMap["options"] = this.initParams; paramMap["params"] = loginParams == null ? (object)new Dictionary() : (object)loginParams; - paramMap["actionType"] = "login"; + paramMap["actionType"] = path; + + if (path == "enable_mfa") + { + string sessionId = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.SESSION_ID); + paramMap["sessionId"] = sessionId; + } - if (extraParams != null && extraParams.Count > 0) - foreach (KeyValuePair item in extraParams) - { - (paramMap["params"] as Dictionary)[item.Key] = item.Value; - } //Debug.Log("paramMap: =>" + JsonConvert.SerializeObject(paramMap)); string loginId = await createSession(JsonConvert.SerializeObject(paramMap, Formatting.None, new JsonSerializerSettings @@ -283,8 +284,16 @@ private async void request(string path, LoginParams loginParams = null, Dictiona }))); UriBuilder uriBuilder = new UriBuilder(this.web3AuthOptions.sdkUrl); - uriBuilder.Path = path; + if(this.web3AuthOptions.sdkUrl.Contains("develop")) + { + uriBuilder.Path = "/" + "start"; + } + else + { + uriBuilder.Path += "/" + "start"; + } uriBuilder.Fragment = "b64Params=" + hash; + //Debug.Log("finalUriBuilderToOpen: =>" + uriBuilder.ToString()); Utils.LaunchUrl(uriBuilder.ToString(), this.initParams["redirectUrl"].ToString(), gameObject.name); } @@ -294,6 +303,66 @@ private async void request(string path, LoginParams loginParams = null, Dictiona } } + public async void launchWalletServices(ChainConfig chainConfig, string path = "wallet") + { + string sessionId = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.SESSION_ID); + if (!string.IsNullOrEmpty(sessionId)) + { + #if UNITY_STANDALONE || UNITY_EDITOR + this.initParams["redirectUrl"] = StartLocalWebserver(); + #elif UNITY_WEBGL + this.initParams["redirectUrl"] = Utils.GetCurrentURL(); + #endif + + this.initParams["chainConfig"] = chainConfig; + Dictionary paramMap = new Dictionary(); + paramMap["options"] = this.initParams; + + //Debug.Log("paramMap: =>" + JsonConvert.SerializeObject(paramMap)); + string loginId = await createSession(JsonConvert.SerializeObject(paramMap, Formatting.None, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore + }), 600); + + if (!string.IsNullOrEmpty(loginId)) + { + var loginIdObject = new Dictionary + { + { "loginId", loginId }, + { "sessionId", sessionId }, + { "platform", "unity" } + }; + string hash = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(loginIdObject, Formatting.None, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore + }))); + + UriBuilder uriBuilder = new UriBuilder(this.web3AuthOptions.walletSdkUrl); + if(this.web3AuthOptions.sdkUrl.Contains("develop")) + { + uriBuilder.Path = "/" + path; + } + else + { + uriBuilder.Path += "/" + path; + } + uriBuilder.Fragment = "b64Params=" + hash; + //Debug.Log("finalUriBuilderToOpen: =>" + uriBuilder.ToString()); + + Utils.LaunchUrl(uriBuilder.ToString(), this.initParams["redirectUrl"].ToString(), gameObject.name); + } + else + { + throw new Exception("Some went wrong. Please try again later."); + } + } else + { + throw new Exception("SessionId not found. Please login first."); + } + } + public void setResultUrl(Uri uri) { string hash = uri.Fragment; @@ -304,20 +373,29 @@ public void setResultUrl(Uri uri) if (hash == null) throw new UserCancelledException(); #endif - if(hash.Length == 0) return; hash = hash.Remove(0, 1); - Dictionary queryParameters = Utils.ParseQuery(uri.Query); + Dictionary queryParameters = Utils.ParseQuery(uri.Query); if (queryParameters.Keys.Contains("error")) throw new UnKnownException(queryParameters["error"]); - string sessionId = hash.Split('&')[0].Split('=')[1]; - - //save new sessionId + string newUriString = "http://" + uri.Host + "?" + hash; + Uri newUri = new Uri(newUriString); + string b64Params = getQueryParamValue(newUri, "b64Params"); + string decodedString = decodeBase64Params(b64Params); + SessionResponse sessionResponse = null; + try + { + sessionResponse = JsonUtility.FromJson(decodedString); + } + catch (Exception e) + { + Debug.Log("Failed to decode JSON: " + e.Message); + } + string sessionId = sessionResponse.sessionId; this.Enqueue(() => KeyStoreManagerUtils.savePreferenceData(KeyStoreManagerUtils.SESSION_ID, sessionId)); //call authorize session API - // Debug.Log("publickey after successful redirection from web. =>" + sessionId); this.Enqueue(() => authorizeSession(sessionId)); #if !UNITY_EDITOR && UNITY_WEBGL @@ -328,6 +406,42 @@ public void setResultUrl(Uri uri) #endif } + private string getQueryParamValue(Uri uri, string key) + { + string value = ""; + if (uri.Query != null && uri.Query.Length > 0) + { + string[] queryParameters = uri.Query.Substring(1).Split('&'); + foreach (string queryParameter in queryParameters) + { + string[] keyValue = queryParameter.Split('='); + if (keyValue[0] == key) + { + value = keyValue[1]; + break; + } + } + } + return value; + } + + private string decodeBase64Params(string base64Params) + { + if(string.IsNullOrEmpty(base64Params)) + return string.Empty; + // Replace URL-safe characters + base64Params = base64Params.Replace('-', '+').Replace('_', '/'); + var d = base64Params.Length % 4; + if (d != 0) + { + base64Params = base64Params.TrimEnd('='); + base64Params += d % 2 > 0 ? "=" : "=="; + } + byte[] bytes = Convert.FromBase64String(base64Params); + var decodedString = System.Text.Encoding.UTF8.GetString(bytes); + return decodedString; + } + public void login(LoginParams loginParams) { if (web3AuthOptions.loginConfig != null) @@ -341,7 +455,7 @@ public void login(LoginParams loginParams) } } - request("start", loginParams); + request("login", loginParams); } public void logout(Dictionary extraParams) @@ -361,6 +475,32 @@ public void logout(Uri redirectUrl = null, string appState = null) logout(extraParams); } + public void enableMFA(LoginParams loginParams) + { + if(web3AuthResponse.userInfo.isMfaEnabled == true) + { + throw new Exception("MFA is already enabled for this user."); + } + string sessionId = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.SESSION_ID); + if (!string.IsNullOrEmpty(sessionId)) + { + if (web3AuthOptions.loginConfig != null) + { + var loginConfigItem = web3AuthOptions.loginConfig?.Values.First(); + var share = KeyStoreManagerUtils.getPreferencesData(loginConfigItem?.verifier); + if (!string.IsNullOrEmpty(share)) + { + loginParams.dappShare = share; + } + } + request("enable_mfa", loginParams); + } + else + { + throw new Exception("SessionId not found. Please login first."); + } + } + private void authorizeSession(string newSessionId) { string sessionId = ""; @@ -372,7 +512,6 @@ private void authorizeSession(string newSessionId) else { sessionId = newSessionId; - // Debug.Log("sessionId during authorizeSession in else part =>" + sessionId); } if (!string.IsNullOrEmpty(sessionId)) @@ -418,6 +557,7 @@ private void authorizeSession(string newSessionId) this.Enqueue(() => this.onLogout?.Invoke()); else this.Enqueue(() => this.onLogin?.Invoke(this.web3AuthResponse)); + this.Enqueue(() => this.onMFASetup?.Invoke(true)); } } @@ -491,6 +631,7 @@ private async Task createSession(string data, long sessionTime) { TaskCompletionSource createSessionResponse = new TaskCompletionSource(); var newSessionKey = KeyStoreManagerUtils.generateRandomSessionKey(); + // Debug.Log("newSessionKey =>" + newSessionKey); var ephemKey = KeyStoreManagerUtils.getPubKey(newSessionKey); var ivKey = KeyStoreManagerUtils.generateRandomBytes(); @@ -525,6 +666,7 @@ private async Task createSession(string data, long sessionTime) { try { + // Debug.Log("newSessionKey before saving into keystore =>" + newSessionKey); this.Enqueue(() => KeyStoreManagerUtils.savePreferenceData(KeyStoreManagerUtils.SESSION_ID, newSessionKey)); createSessionResponse.SetResult(newSessionKey); } diff --git a/package.json b/package.json index 4ab82828..e2b4afca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.solana.unity_sdk", - "version": "1.2.4", + "version": "1.2.5", "unity": "2019.4", "displayName": "Solana SDK", "description": "Open-Source Unity-Solana SDK with Full RPC coverage, NFT support and more",