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
5 changes: 5 additions & 0 deletions .changeset/three-dancers-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

Consolidate custom jwt and custom auth endpoint through common endpoint
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
import type { ThirdwebClient } from "../../../../client/client.js";
import { getSessionHeaders } from "../../native/helpers/api/fetchers.js";
import { getClientFetch } from "../../../../utils/fetch.js";
import { ROUTE_AUTH_ENDPOINT_CALLBACK } from "../../native/helpers/constants.js";
import { createErrorMessage } from "../../native/helpers/errors.js";
import type { ClientScopedStorage } from "./client-scoped-storage.js";
import type { Ecosystem } from "../wallet/types.js";
import type { AuthStoredTokenWithCookieReturnType } from "./types.js";

export async function authEndpoint(args: {
payload: string;
client: ThirdwebClient;
storage: ClientScopedStorage;
ecosystem?: Ecosystem;
}): Promise<AuthStoredTokenWithCookieReturnType> {
const resp = await fetch(ROUTE_AUTH_ENDPOINT_CALLBACK, {
const clientFetch = getClientFetch(args.client, args.ecosystem);

const res = await clientFetch(ROUTE_AUTH_ENDPOINT_CALLBACK, {
method: "POST",
headers: {
...getSessionHeaders(),
"Content-Type": "application/json",
},
body: JSON.stringify({
payload: args.payload,
developerClientId: args.client.clientId,
}),
});
if (!resp.ok) {
const error = await resp.json();

if (!res.ok) {
const error = await res.json();
throw new Error(
`Custom auth endpoint authentication error: ${error.message}`,
);
}

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

return { storedToken: verifiedToken };
} catch (e) {
Expand Down
35 changes: 16 additions & 19 deletions packages/thirdweb/src/wallets/in-app/core/authentication/guest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,22 @@ export async function guestAuthenticate(args: {
}

const clientFetch = getClientFetch(args.client, args.ecosystem);
const authResult = await (async () => {
const path = getLoginCallbackUrl({
authOption: "guest",
client: args.client,
ecosystem: args.ecosystem,
});
const res = await clientFetch(`${path}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
sessionId,
}),
});
const path = getLoginCallbackUrl({
authOption: "guest",
client: args.client,
ecosystem: args.ecosystem,
});
const res = await clientFetch(`${path}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
sessionId,
}),
});

if (!res.ok) throw new Error("Failed to generate guest account");
if (!res.ok) throw new Error("Failed to generate guest account");

return (await res.json()) satisfies AuthStoredTokenWithCookieReturnType;
})();
return authResult;
return (await res.json()) satisfies AuthStoredTokenWithCookieReturnType;
}
19 changes: 11 additions & 8 deletions packages/thirdweb/src/wallets/in-app/core/authentication/jwt.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
import type { ThirdwebClient } from "../../../../client/client.js";
import { getSessionHeaders } from "../../native/helpers/api/fetchers.js";
import { getClientFetch } from "../../../../utils/fetch.js";
import { ROUTE_AUTH_JWT_CALLBACK } from "../../native/helpers/constants.js";
import { createErrorMessage } from "../../native/helpers/errors.js";
import type { ClientScopedStorage } from "./client-scoped-storage.js";
import type { Ecosystem } from "../wallet/types.js";
import type { AuthStoredTokenWithCookieReturnType } from "./types.js";

export async function customJwt(args: {
jwt: string;
client: ThirdwebClient;
storage: ClientScopedStorage;
ecosystem?: Ecosystem;
}): Promise<AuthStoredTokenWithCookieReturnType> {
const resp = await fetch(ROUTE_AUTH_JWT_CALLBACK, {
const clientFetch = getClientFetch(args.client, args.ecosystem);

const res = await clientFetch(ROUTE_AUTH_JWT_CALLBACK, {
method: "POST",
headers: {
...getSessionHeaders(),
"Content-Type": "application/json",
},
body: JSON.stringify({
jwt: args.jwt,
developerClientId: args.client.clientId,
}),
});

if (!resp.ok) {
const error = await resp.json();
if (!res.ok) {
const error = await res.json();
throw new Error(`JWT authentication error: ${error.message}`);
}

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

return { storedToken: verifiedToken };
} catch (e) {
throw new Error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const ECOSYSTEM_PARTNER_ID_HEADER = "x-ecosystem-partner-id";

let sessionNonce: Hex | undefined = undefined;

export function getSessionHeaders() {
function getSessionHeaders() {
if (!sessionNonce) {
sessionNonce = randomBytesHex(16);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,13 @@ export class InAppNativeConnector implements InAppConnector {
return customJwt({
jwt: params.jwt,
client: this.client,
storage: this.storage,
ecosystem: this.ecosystem,
});
case "auth_endpoint":
return authEndpoint({
payload: params.payload,
client: this.client,
storage: this.storage,
ecosystem: this.ecosystem,
});
default:
throw new Error(`Unsupported authentication type: ${strategy}`);
Expand Down
40 changes: 20 additions & 20 deletions packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { webLocalStorage } from "../../../../utils/storage/webStorage.js";
import type { SocialAuthOption } from "../../../../wallets/types.js";
import type { Account } from "../../../interfaces/wallet.js";
import { getUserStatus } from "../../core/actions/get-enclave-user-status.js";
import { authEndpoint } from "../../core/authentication/authEndpoint.js";
import { ClientScopedStorage } from "../../core/authentication/client-scoped-storage.js";
import { guestAuthenticate } from "../../core/authentication/guest.js";
import { customJwt } from "../../core/authentication/jwt.js";
import {
getLinkedProfilesInternal,
linkAccount,
Expand Down Expand Up @@ -268,8 +270,11 @@ export class InAppWebConnector implements InAppConnector {
});
}

async loginWithAuthToken(authResult: AuthStoredTokenWithCookieReturnType) {
return this.auth.loginWithAuthToken(authResult);
async loginWithAuthToken(
authResult: AuthStoredTokenWithCookieReturnType,
recoveryCode?: string,
) {
return this.auth.loginWithAuthToken(authResult, recoveryCode);
}

/**
Expand All @@ -292,20 +297,22 @@ export class InAppWebConnector implements InAppConnector {
client: this.client,
ecosystem: this.ecosystem,
});
case "auth_endpoint": {
return authEndpoint({
payload: args.payload,
client: this.client,
ecosystem: this.ecosystem,
});
}
case "jwt":
return this.auth.authenticateWithCustomJwt({
return customJwt({
jwt: args.jwt,
encryptionKey: args.encryptionKey,
client: this.client,
ecosystem: this.ecosystem,
});
case "passkey": {
return this.passkeyAuth(args);
}
case "auth_endpoint": {
return this.auth.authenticateWithCustomAuthEndpoint({
payload: args.payload,
encryptionKey: args.encryptionKey,
});
}
case "iframe_email_verification": {
return this.auth.authenticateWithIframe({
email: args.email,
Expand Down Expand Up @@ -359,17 +366,10 @@ export class InAppWebConnector implements InAppConnector {
): Promise<AuthLoginReturnType> {
const strategy = args.strategy;
switch (strategy) {
case "auth_endpoint":
case "jwt": {
return this.auth.loginWithCustomJwt({
jwt: args.jwt,
encryptionKey: args.encryptionKey,
});
}
case "auth_endpoint": {
return this.auth.loginWithCustomAuthEndpoint({
payload: args.payload,
encryptionKey: args.encryptionKey,
});
const authToken = await this.authenticate(args);
return await this.loginWithAuthToken(authToken, args.encryptionKey);
}
case "iframe_email_verification": {
return this.auth.loginWithIframe({
Expand Down
Loading