Skip to content

Commit 526b6b5

Browse files
committed
Add useAuthToken hook for in-app wallet authentication (#7120)
# Add `useAuthToken` hook for in-app wallet authentication This PR adds a new React hook `useAuthToken()` that returns a JWT authentication token for the currently active in-app wallet. This token can be used to authorize API calls to backend servers. Key changes: - Added `useAuthToken()` hook that returns the auth token when an in-app wallet is active - Modified the `InAppConnector` interface to expose the storage property - Updated the wallet interface to include a `getAuthToken()` method for in-app wallets - Implemented token retrieval in the in-app wallet core implementation The hook ensures the token is only returned when the active wallet is an in-app wallet and matches the active account. Example usage: ```tsx function MyComponent() { const authToken = useAuthToken(); const fetchData = async () => { const response = await fetch('https://api.example.com/data', { headers: { 'Authorization': `Bearer ${authToken}` } }); // ... handle response }; } ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a new hook to retrieve authentication tokens for in-app wallets, enabling secure authorization for API calls. - **Documentation** - Added usage examples and clarifications regarding authentication token availability for wallets. <!-- end of auto-generated comment: release notes by coderabbit.ai --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on enhancing the wallet functionality by introducing an authentication token feature and updating the visibility of certain properties. It adds a method for retrieving an authentication token and modifies the storage property to be public. ### Detailed summary - Changed `storage` property from `private` to `public` in `native-connector.ts` and `web-connector.ts`. - Added `getAuthToken` method to the wallet interface in `wallet.ts` with documentation. - Included `storage` in the `InAppConnector` interface. - Implemented `authToken` handling in `createInAppWallet` function. - Created `useAuthToken` hook for retrieving the JWT of the active wallet. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent f31116e commit 526b6b5

File tree

8 files changed

+75
-5
lines changed

8 files changed

+75
-5
lines changed

packages/thirdweb/src/exports/react.native.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ export type {
99

1010
// wallet hooks
1111
export { useActiveWallet } from "../react/core/hooks/wallets/useActiveWallet.js";
12-
export { useAdminWallet } from "../react/core/hooks/wallets/useAdminWallet.js";
1312
export { useActiveWalletChain } from "../react/core/hooks/wallets/useActiveWalletChain.js";
1413
export { useActiveWalletConnectionStatus } from "../react/core/hooks/wallets/useActiveWalletConnectionStatus.js";
1514
export { useActiveAccount } from "../react/core/hooks/wallets/useActiveAccount.js";
15+
export { useAdminWallet } from "../react/core/hooks/wallets/useAdminWallet.js";
16+
export { useAuthToken } from "../react/core/hooks/wallets/useAuthToken.js";
1617
export { useAutoConnect } from "../react/native/hooks/wallets/useAutoConnect.js";
1718
export { useConnect } from "../react/core/hooks/wallets/useConnect.js";
1819
export { useConnectedWallets } from "../react/core/hooks/wallets/useConnectedWallets.js";

packages/thirdweb/src/exports/react.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ export type { MediaRendererProps } from "../react/web/ui/MediaRenderer/types.js"
4040

4141
// wallet hooks
4242
export { useActiveWallet } from "../react/core/hooks/wallets/useActiveWallet.js";
43-
export { useAdminWallet } from "../react/core/hooks/wallets/useAdminWallet.js";
4443
export { useActiveWalletChain } from "../react/core/hooks/wallets/useActiveWalletChain.js";
4544
export { useActiveWalletConnectionStatus } from "../react/core/hooks/wallets/useActiveWalletConnectionStatus.js";
4645
export { useActiveAccount } from "../react/core/hooks/wallets/useActiveAccount.js";
46+
export { useAdminWallet } from "../react/core/hooks/wallets/useAdminWallet.js";
47+
export { useAuthToken } from "../react/core/hooks/wallets/useAuthToken.js";
4748
export { useAutoConnect } from "../react/web/hooks/wallets/useAutoConnect.js";
4849
export { useConnect } from "../react/core/hooks/wallets/useConnect.js";
4950
export { useConnectedWallets } from "../react/core/hooks/wallets/useConnectedWallets.js";
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useActiveAccount } from "./useActiveAccount.js";
2+
import { useActiveWallet } from "./useActiveWallet.js";
3+
4+
/**
5+
* A hook that returns the authentication token (JWT) for the currently active wallet.
6+
* This token can be used to authorize API calls to your backend server.
7+
*
8+
* @returns The JWT string if the active wallet is an in-app wallet and matches the active account, null otherwise
9+
*
10+
* @example
11+
* ```tsx
12+
* function MyComponent() {
13+
* const authToken = useAuthToken();
14+
*
15+
* const fetchData = async () => {
16+
* const response = await fetch('https://api.example.com/data', {
17+
* headers: {
18+
* 'Authorization': `Bearer ${authToken}`
19+
* }
20+
* });
21+
* // ... handle response
22+
* };
23+
* }
24+
* ```
25+
*
26+
* @wallet
27+
*/
28+
export function useAuthToken() {
29+
const activeWallet = useActiveWallet();
30+
const activeAccount = useActiveAccount();
31+
// if the active wallet is an in-app wallet and the active account is the same as the active wallet's account, return the auth token for the in-app wallet
32+
if (
33+
activeWallet?.getAuthToken &&
34+
activeAccount &&
35+
activeAccount.address === activeWallet.getAccount()?.address
36+
) {
37+
return activeWallet.getAuthToken();
38+
}
39+
// all other wallets don't expose an auth token for now
40+
return null;
41+
}

packages/thirdweb/src/wallets/in-app/core/interfaces/connector.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { SocialAuthOption } from "../../../../wallets/types.js";
22
import type { Account } from "../../../interfaces/wallet.js";
3+
import type { ClientScopedStorage } from "../authentication/client-scoped-storage.js";
34
import type {
45
AuthArgsType,
56
AuthLoginReturnType,
@@ -38,4 +39,5 @@ export interface InAppConnector {
3839
linkProfile(args: AuthArgsType): Promise<Profile[]>;
3940
unlinkProfile(args: Profile): Promise<Profile[]>;
4041
getProfiles(): Promise<Profile[]>;
42+
storage: ClientScopedStorage;
4143
}

packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ export function createInAppWallet(args: {
5555
let adminAccount: Account | undefined = undefined; // Admin account if smartAccountOptions were provided with connection
5656
let chain: Chain | undefined = undefined;
5757
let client: ThirdwebClient | undefined;
58+
let authToken: string | null = null;
5859

5960
return {
6061
id: walletId,
62+
getAuthToken: () => authToken,
6163
subscribe: emitter.subscribe,
6264
getChain() {
6365
if (!chain) {
@@ -114,6 +116,12 @@ export function createInAppWallet(args: {
114116
account = connectedAccount;
115117
adminAccount = _adminAccount;
116118
chain = connectedChain;
119+
try {
120+
authToken = await connector.storage.getAuthCookie();
121+
} catch (error) {
122+
console.error("Failed to retrieve auth token:", error);
123+
authToken = null;
124+
}
117125
trackConnect({
118126
client: options.client,
119127
ecosystem,
@@ -168,6 +176,12 @@ export function createInAppWallet(args: {
168176
account = connectedAccount;
169177
adminAccount = _adminAccount;
170178
chain = connectedChain;
179+
try {
180+
authToken = await connector.storage.getAuthCookie();
181+
} catch (error) {
182+
console.error("Failed to retrieve auth token:", error);
183+
authToken = null;
184+
}
171185
trackConnect({
172186
client: options.client,
173187
ecosystem,
@@ -194,6 +208,7 @@ export function createInAppWallet(args: {
194208
account = undefined;
195209
adminAccount = undefined;
196210
chain = undefined;
211+
authToken = null;
197212
emitter.emit("disconnect", undefined);
198213
},
199214
switchChain: async (newChain) => {

packages/thirdweb/src/wallets/in-app/native/native-connector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type NativeConnectorOptions = {
2929
export class InAppNativeConnector implements InAppConnector {
3030
private client: ThirdwebClient;
3131
private ecosystem?: Ecosystem;
32-
private storage: ClientScopedStorage;
32+
public storage: ClientScopedStorage;
3333
private passkeyDomain?: string;
3434
private wallet?: IWebWallet;
3535

packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export class InAppWebConnector implements InAppConnector {
5050
private client: ThirdwebClient;
5151
private ecosystem?: Ecosystem;
5252
private querier: InAppWalletIframeCommunicator<AuthQuerierTypes>;
53-
private storage: ClientScopedStorage;
53+
public storage: ClientScopedStorage;
5454

5555
private wallet?: IWebWallet;
5656
/**

packages/thirdweb/src/wallets/interfaces/wallet.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,18 @@ export type Wallet<TWalletId extends WalletId = WalletId> = {
151151
* This is useful for smart wallets to get the underlying personal account
152152
*/
153153
getAdminAccount?: () => Account | undefined;
154-
};
155154

155+
/**
156+
* Get the authentication token for the wallet.
157+
*
158+
* This method is not available for on all wallets. This method will be `undefined` if the wallet does not support it.
159+
* @example
160+
* ```ts
161+
* const authToken = await wallet.getAuthToken();
162+
* ```
163+
*/
164+
getAuthToken?: () => string | null;
165+
};
156166
/**
157167
* Account interface
158168
*

0 commit comments

Comments
 (0)