Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions examples/react-app/src/components/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Divider from "./Divider";

function Account() {
const [addressToShow, setAddressToShow] = useState<string>("");
const { address, userInfo, getUserInfo } = usePlayground();
const { address, userInfo, getUserInfo, getExternalIdToken } = usePlayground();

useEffect(() => {
setAddressToShow(address || "");
Expand All @@ -27,9 +27,12 @@ function Account() {
<div>
<h3 className="font-bold text-app-gray-800 mb-2">{userInfo?.name || ""}</h3>
<p className="text-xs text-app-gray-400 mb-1">{userInfo?.email ? userInfo?.email : userInfo?.name}</p>
<button type="button" className="leading-none text-xs text-app-primary-600 hover:underline" onClick={getUserInfo}>
<p><button type="button" className="leading-none text-xs text-app-primary-600 hover:underline" onClick={getUserInfo}>
View User Info
</button>
</button></p>
<p><button type="button" className="leading-none text-xs text-app-primary-600 hover:underline" onClick={getExternalIdToken}>
Get External Id Token
</button></p>
</div>
<Divider />
<Button
Expand Down
17 changes: 16 additions & 1 deletion examples/react-app/src/services/playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CHAIN_NAMESPACES, IProvider, log, WEB3AUTH_NETWORK, IPlugin } from "@we
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { PasskeysPlugin } from "@web3auth/passkeys-sfa-plugin";
// Import Single Factor Auth SDK for no redirect flow
import { ADAPTER_EVENTS, decodeToken, Web3Auth } from "@web3auth/single-factor-auth";
import { ADAPTER_EVENTS, decodeToken, UserAuthInfo, Web3Auth } from "@web3auth/single-factor-auth";
import { WalletServicesPlugin } from "@web3auth/wallet-services-plugin";
import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from "react";

Expand Down Expand Up @@ -62,6 +62,7 @@ export interface IPlaygroundContext {
unlinkPasskey: (id: number) => void;
logout: () => void;
getUserInfo: () => Promise<AuthUserInfo | null>;
getExternalIdToken: () => Promise<UserAuthInfo | null>;
showCheckout: () => void;
showWalletUI: () => void;
showWalletScanner: () => void;
Expand Down Expand Up @@ -94,6 +95,7 @@ export const PlaygroundContext = createContext<IPlaygroundContext>({
unlinkPasskey: async () => null,
logout: async () => null,
getUserInfo: async () => null,
getExternalIdToken: async () => null,
showCheckout: async () => null,
showWalletUI: async () => null,
showWalletScanner: async () => null,
Expand Down Expand Up @@ -326,6 +328,17 @@ export function Playground({ children }: IPlaygroundProps) {
return null;
}, [web3authSFAuth]);

const getExternalIdToken = useCallback(async (): Promise<UserAuthInfo | null> => {
if (web3authSFAuth && web3authSFAuth?.connected) {
const data = await web3authSFAuth?.authenticateUser();
setPlaygroundConsoleTitle("Id Token");
setPlaygroundConsoleData(JSON.stringify(data, null, 2));
uiConsole(data);
return data;
}
return null;
}, [web3authSFAuth]);

const showCheckout = useCallback(async () => {
if (!wsPlugin) {
uiConsole("wallet services plugin not initialized yet");
Expand Down Expand Up @@ -523,6 +536,7 @@ export function Playground({ children }: IPlaygroundProps) {
unlinkPasskey,
logout,
getUserInfo,
getExternalIdToken,
showCheckout,
showWalletUI,
showWalletScanner,
Expand Down Expand Up @@ -554,6 +568,7 @@ export function Playground({ children }: IPlaygroundProps) {
unlinkPasskey,
logout,
getUserInfo,
getExternalIdToken,
showCheckout,
showWalletUI,
showWalletScanner,
Expand Down
77 changes: 62 additions & 15 deletions src/Web3Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class Web3Auth extends SafeEventEmitter<Web3AuthSfaEvents> implements IWe
}

get connected(): boolean {
return Boolean(this.sessionManager?.sessionId);
return this.status === ADAPTER_STATUS.CONNECTED;
}

get provider(): IProvider | null {
Expand Down Expand Up @@ -182,9 +182,16 @@ export class Web3Auth extends SafeEventEmitter<Web3AuthSfaEvents> implements IWe

const { chainNamespace, chainId } = this.coreOptions.chainConfig || {};
if (!this.authInstance || !this.privKeyProvider) throw WalletInitializationError.notReady();
const accounts = await this.privKeyProvider.provider.request<unknown, string[]>({
method: chainNamespace === CHAIN_NAMESPACES.EIP155 ? "eth_accounts" : "getAccounts",
});
const [accounts, publicKey] = await Promise.all([
this.privKeyProvider.provider.request<unknown, string[]>({
method: chainNamespace === CHAIN_NAMESPACES.EIP155 ? "eth_accounts" : "getAccounts",
}),
this.privKeyProvider.provider.request<unknown, string[]>({
method: "public_key",
}),
]);
// const thresholdPrivKey = this._getBasePrivKey();

if (accounts && accounts.length > 0) {
const existingToken = getSavedToken(accounts[0] as string, "SFA");
if (existingToken) {
Expand All @@ -204,6 +211,35 @@ export class Web3Auth extends SafeEventEmitter<Web3AuthSfaEvents> implements IWe
issuedAt: new Date().toISOString(),
};

const additionalMetadata = {
email: userInfo.email,
name: userInfo.name,
profileImage: userInfo.profileImage,
aggregateVerifier: userInfo.aggregateVerifier,
verifier: userInfo.verifier,
verifierId: userInfo.verifierId,
typeOfLogin: userInfo.typeOfLogin || "jwt",
oAuthIdToken: userInfo.oAuthIdToken,
oAuthAccessToken: userInfo.oAuthAccessToken,
wallets: [] as unknown[],
signatures: this.state.signatures,
network: this.coreOptions.web3AuthNetwork,
};

if (this.coreOptions.usePnPKey) {
additionalMetadata.wallets.push({
public_key: publicKey,
type: "web3auth_app_key",
curve: chainNamespace === CHAIN_NAMESPACES.EIP155 ? KEY_TYPE.SECP256K1 : KEY_TYPE.ED25519,
});
} else {
additionalMetadata.wallets.push({
public_key: publicKey,
type: "web3auth_threshold_key",
curve: chainNamespace === CHAIN_NAMESPACES.EIP155 ? KEY_TYPE.SECP256K1 : KEY_TYPE.ED25519,
});
}

const challenge = await signChallenge(payload, chainNamespace);
const signedMessage = await this._getSignedMessage(challenge, accounts, chainNamespace);
const idToken = await verifySignedChallenge(
Expand All @@ -213,7 +249,9 @@ export class Web3Auth extends SafeEventEmitter<Web3AuthSfaEvents> implements IWe
this.SFA_ISSUER,
this.coreOptions.sessionTime,
this.coreOptions.clientId,
this.coreOptions.web3AuthNetwork as WEB3AUTH_NETWORK_TYPE
this.coreOptions.web3AuthNetwork as WEB3AUTH_NETWORK_TYPE,
undefined,
additionalMetadata
);
saveToken(accounts[0] as string, "SFA", idToken);
return {
Expand Down Expand Up @@ -318,11 +356,12 @@ export class Web3Auth extends SafeEventEmitter<Web3AuthSfaEvents> implements IWe

async logout(): Promise<void> {
if (!this.connected) throw WalletLoginError.notConnectedError("Not logged in");
const sessionId = this.currentStorage.get<string>("sessionId");
if (!sessionId) throw WalletLoginError.fromCode(5000, "User not logged in");

await this.sessionManager.invalidateSession();
this.currentStorage.set("sessionId", "");
if (this.coreOptions.mode !== SDK_MODE.NODE) {
await this.sessionManager.invalidateSession();
this.currentStorage.set("sessionId", "");
}

this.updateState({
privKey: "",
userInfo: {
Expand Down Expand Up @@ -415,18 +454,26 @@ export class Web3Auth extends SafeEventEmitter<Web3AuthSfaEvents> implements IWe
let finalPrivKey = privKey.padStart(64, "0");
// get app scoped keys.
if (this.coreOptions.usePnPKey) {
const pnpPrivKey = subkey(finalPrivKey, Buffer.from(this.coreOptions.clientId, "base64"));
finalPrivKey = pnpPrivKey.padStart(64, "0");
finalPrivKey = this.getSubKey(finalPrivKey);
}
if (this.coreOptions.chainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA) {
if (!this.privKeyProvider.getEd25519Key) {
throw WalletLoginError.fromCode(5000, "Private key provider is not valid, Missing getEd25519Key function");
}
finalPrivKey = this.privKeyProvider.getEd25519Key(finalPrivKey);
finalPrivKey = this.getEd25519Key(finalPrivKey);
}
return finalPrivKey;
}

private getSubKey(privKey: string) {
const pnpPrivKey = subkey(privKey, Buffer.from(this.coreOptions.clientId, "base64"));
return pnpPrivKey.padStart(64, "0");
}

private getEd25519Key(privKey: string) {
if (!this.privKeyProvider.getEd25519Key) {
throw WalletLoginError.fromCode(5000, "Private key provider is not valid, Missing getEd25519Key function");
}
return this.privKeyProvider.getEd25519Key(privKey);
}

private async getTorusKey(loginParams: LoginParams): Promise<string> {
const { verifier, verifierId, idToken, subVerifierInfoArray } = loginParams;

Expand Down