Skip to content
Merged
Next Next commit
custom jwt flow
  • Loading branch information
ikethirdweb committed Oct 17, 2023
commit 45ba5a3ae19764eaa65864ed6a9c9fb6c8d15ddf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AuthOptions,
EmbeddedWalletConnectionArgs,
EmbeddedWalletConnectorOptions,
OauthOption,
Expand All @@ -7,7 +8,12 @@ import type { Chain } from "@thirdweb-dev/chains";
import { Connector, normalizeChainId } from "@thirdweb-dev/wallets";
import { providers, Signer } from "ethers";
import { utils } from "ethers";
import { sendEmailOTP, socialLogin, validateEmailOTP } from "./embedded/auth";
import {
customJwt,
sendEmailOTP,
socialLogin,
validateEmailOTP,
} from "./embedded/auth";
import { getEthersSigner } from "./embedded/signer";
import { logoutUser } from "./embedded/helpers/auth/logout";
import {
Expand All @@ -30,11 +36,16 @@ export class EmbeddedWalletConnector extends Connector<EmbeddedWalletConnectionA
this.email = getConnectedEmail();
}

async connect(options?: { email?: string; chainId?: number }) {
async connect(
options?: { chainId?: number } & Omit<
EmbeddedWalletConnectionArgs,
"email"
>,
) {
const connected = await this.isConnected();

if (!connected) {
throw new Error("Not connected");
// const;
}

if (options?.chainId) {
Expand Down Expand Up @@ -114,6 +125,30 @@ export class EmbeddedWalletConnector extends Connector<EmbeddedWalletConnectionA
return { success: true };
}

async verifyAuth(authOptions: AuthOptions) {
try {
const resp = await customJwt(authOptions, this.options.clientId);
this.email = resp.email;
} catch (error) {
console.error(`Error while verifying auth: ${error}`);
this.disconnect();
throw error;
}

try {
await this.getSigner();
this.emit("connected");
} catch (error) {
if (error instanceof Error) {
return { error: error.message };
} else {
return { error: "Error getting the signer" };
}
}

return { success: true };
}

async disconnect(): Promise<void> {
clearConnectedEmail();
await logoutUser(this.options.clientId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ import { isDeviceSharePresentForUser } from "./helpers/storage/local";
import { getCognitoUser, setCognitoUser } from "./helpers/storage/state";
import { SendEmailOtpReturnType } from "@thirdweb-dev/wallets";
import { InAppBrowser } from "react-native-inappbrowser-reborn";
import { OauthOption } from "../types";
import { ROUTE_HEADLESS_GOOGLE_LOGIN } from "./helpers/constants";
import { AuthOptions, OauthOption } from "../types";
import {
ROUTE_AUTH_JWT_CALLBACK,
ROUTE_HEADLESS_GOOGLE_LOGIN,
} from "./helpers/constants";

export async function sendEmailOTP(
email: string,
Expand Down Expand Up @@ -196,3 +199,46 @@ export async function socialLogin(oauthOptions: OauthOption, clientId: string) {
);
}
}

export async function customJwt(authOptions: AuthOptions, clientId: string) {
const { jwt, authProvider } = authOptions;

const resp = await fetch(ROUTE_AUTH_JWT_CALLBACK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jwt,
authProvider,
developerClientId: clientId,
}),
});
if (!resp.ok) {
const { error } = await resp.json();
throw new Error(`JWT authentication error: ${error} `);
}

try {
const { verifiedToken, verifiedTokenJwtString } = await resp.json();

const toStoreToken: AuthStoredTokenWithCookieReturnType["storedToken"] = {
jwtToken: verifiedToken.rawToken,
authProvider: verifiedToken.authProvider,
authDetails: {
...verifiedToken.authDetails,
email: verifiedToken.authDetails.email,
},
developerClientId: verifiedToken.developerClientId,
cookieString: verifiedTokenJwtString,
shouldStoreCookieString: false,
isNewUser: verifiedToken.isNewUser,
};

await postPaperAuth(toStoreToken, clientId);

return { verifiedToken, email: verifiedToken.authDetails.email };
} catch (e) {
throw new Error(
`Malformed response from post authentication: ${JSON.stringify(e)}`,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const ROUTE_INIT_RECOVERY_CODE_FREE_WALLET = `${ROUTE_2022_08_12_API_BASE
export const ROUTE_STORE_USER_SHARES = `${ROUTE_2022_08_12_API_BASE_PATH}/embedded-wallet/store-shares`;
export const ROUTE_GET_USER_SHARES = `${ROUTE_2022_08_12_API_BASE_PATH}/embedded-wallet/get-shares`;
export const ROUTE_VERIFY_THIRDWEB_CLIENT_ID = `${ROUTE_2022_08_12_API_BASE_PATH}/embedded-wallet/verify-thirdweb-client-id`;
export const ROUTE_AUTH_JWT_CALLBACK = `${ROUTE_2022_08_12_API_BASE_PATH}/embedded-wallet/jwt-callback`;

export const ROUTE_HEADLESS_GOOGLE_LOGIN = `${BASE_URL}/api/2022-08-12/embedded-wallet/headless-login-link`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ export interface EmbeddedWalletConnectorOptions {
styles?: PaperConstructorType<RecoveryShareManagement>["styles"];
}

export interface AuthOptions {
jwt: string;
authProvider: string;
recoveryCode: string;
}

export interface EmbeddedWalletConnectionArgs {
email?: string;
authOptions?: AuthOptions;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export type EmbeddedWalletConfig = {
// @default true - set false to disable
email?: boolean;

// @default { providers: ['google'] } - set false to disable
oauthOptions?:
| {
providers: OAuthProvider[];
Expand Down