-
Notifications
You must be signed in to change notification settings - Fork 536
Add useAuthToken hook for in-app wallet authentication #7120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add useAuthToken hook for in-app wallet authentication #7120
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
WalkthroughA new React hook, Changes
Sequence Diagram(s)sequenceDiagram
participant ReactComponent
participant useAuthToken
participant useActiveWallet
participant useActiveAccount
participant Wallet
ReactComponent->>useAuthToken: Call hook
useAuthToken->>useActiveWallet: Get active wallet
useAuthToken->>useActiveAccount: Get active account
alt Wallet has getAuthToken and account matches
useAuthToken->>Wallet: getAuthToken()
Wallet-->>useAuthToken: Return JWT token
useAuthToken-->>ReactComponent: Return token
else Not available
useAuthToken-->>ReactComponent: Return null
end
sequenceDiagram
participant User
participant Wallet
participant ConnectorStorage
User->>Wallet: connect() or autoConnect()
Wallet->>ConnectorStorage: Retrieve auth cookie
alt Success
ConnectorStorage-->>Wallet: Return auth token
Wallet->>Wallet: Set authToken
else Failure
ConnectorStorage-->>Wallet: Error
Wallet->>Wallet: Set authToken to null
end
User->>Wallet: disconnect()
Wallet->>Wallet: Reset authToken to null
Suggested reviewers
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (8)
🚧 Files skipped from review as they are similar to previous changes (8)
⏰ Context from checks skipped due to timeout of 90000ms (8)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts (1)
58-201
: 💡 Verification agent🧩 Analysis chain
Consider implementing token expiration handling.
JWT tokens typically have an expiration time. There's currently no mechanism to refresh the token when it expires or to check if it's still valid before returning it.
Consider adding a token validation and refresh mechanism, especially if the tokens have short lifespans. This could involve:
- Parsing the JWT to check its expiration time
- Implementing a refresh mechanism when tokens are near expiration
- Adding a validation check in the
getAuthToken
methodExample implementation for the
getAuthToken
method:getAuthToken: () => { if (authToken && isTokenExpired(authToken)) { // Either return null for expired tokens or trigger a refresh // Could also set up a background refresh mechanism return null; } return authToken; },
🌐 Web query:
How to check if a JWT token is expired in JavaScript?
💡 Result:
How to Check if a JWT Token Is Expired in JavaScript
To determine if a JWT (JSON Web Token) is expired in JavaScript, the most common approach is to decode the token's payload, read the
exp
(expiration) claim, and compare it with the current time. Here’s a step-by-step guide:1. Understanding JWT Structure and Expiration
- A JWT consists of three parts separated by dots: header, payload, and signature.
- The payload contains claims, including the
exp
claim, which is the expiration time as a Unix timestamp (in seconds)[6][7].- If the current time (in seconds) is greater than or equal to
exp
, the token is expired[4][6][7].2. Decoding the Token and Checking Expiry
You can use pure JavaScript to decode the payload and check if the token has expired. The following function does this:
const isTokenExpired = (token) => { if (!token) return true; try { const payload = JSON.parse(atob(token.split('.')[1])); // `exp` is in seconds, Date.now() in milliseconds return Date.now() >= payload.exp * 1000; } catch (e) { // If token can't be decoded, treat as expired return true; } };
atob
decodes the base64-encoded payload.payload.exp
gives the expiration timestamp (seconds since epoch).Date.now()
returns the current time in milliseconds, so multiplyexp
by 1000 for comparison.3. Using Libraries
Several libraries can automate this check:
- jwt-check-expiration: A lightweight package to check JWT expiration in the browser[2].
jwt-decode
: Popular for decoding JWTs, but you still need to compare theexp
claim manually.4. Notes and Best Practices
- This client-side check is useful for preventing unnecessary API calls or for UI state management.
- Security-critical validation (like actual access control) should always be performed on the server, with signature verification.
- Handle tokens that cannot be decoded gracefully by treating them as expired[4].
5. Summary Table
Step Action Reference Decode JWT payload Use atob(token.split('.')[1])
[4][7][6] Extract exp
claimGet expiration timestamp from payload [6][7] Compare with now Date.now() >= exp * 1000
(returns true if expired)[4][8] This approach is widely used in React and other JavaScript frameworks for session management and proactive token refresh[1][8].
Citations:
- 1: https://dev.to/egnoel/how-to-verify-jwt-token-expiry-in-reactnext-22dn
- 2: https://www.npmjs.com/package/jwt-check-expiration
- 3: https://jwt.io
- 4: https://gist.github.com/alex-alekseichuk/64f5f28058d95a4ac5e6bfdcfaf3eaa7
- 5: https://www.baeldung.com/java-jwt-check-expiry-no-exception
- 6: https://mojoauth.com/blog/understanding-jwt-expiration-time-claim-exp/
- 7: https://community.auth0.com/t/how-to-check-access-token-is-expired/78890
- 8: https://www.bezkoder.com/handle-jwt-token-expiration-react/
- 9: https://community.auth0.com/t/checking-token-validity-expiry/9348
- 10: https://devforum.zoom.us/t/how-can-i-know-when-my-jwt-token-will-expire/83881
Implement Token Expiration and Refresh in getAuthToken
The current
getAuthToken
simply returns the stored JWT without any expiry check or refresh logic. To prevent returning expired tokens (and avoid silent failures), add a validation step and, when possible, a refresh mechanism:• File to update:
- packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts
- Method:
getAuthToken
• Steps:
- Create or import a utility, e.g.
isTokenExpired(token: string): boolean
, that decodes the JWT’sexp
claim and compares it toDate.now()
.- Change
getAuthToken
to:
- Check
authToken
; returnnull
if missing or expired.- Optionally attempt to refresh via your connector (e.g.
connector.storage.getAuthCookie()
or a newrefreshAuthToken()
helper) before returning.- If you surface token refresh errors, ensure callers handle them (or fall back to a fresh
connect()
).Example diff:
- getAuthToken: () => authToken, + getAuthToken: async () => { + if (!authToken || isTokenExpired(authToken)) { + // Try refreshing the token + try { + const connector = await getOrCreateInAppWalletConnector(client, connectorFactory, ecosystem); + authToken = await connector.storage.getAuthCookie(); + } catch { + return null; + } + } + return authToken; + },• Add a helper in e.g.
src/utils/jwt.ts
:export function isTokenExpired(token: string): boolean { try { const { exp } = JSON.parse(atob(token.split('.')[1])); return Date.now() >= exp * 1000; } catch { return true; } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
packages/thirdweb/src/react/core/hooks/wallets/useAuthToken.ts
(1 hunks)packages/thirdweb/src/wallets/in-app/core/interfaces/connector.ts
(2 hunks)packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts
(4 hunks)packages/thirdweb/src/wallets/in-app/native/native-connector.ts
(1 hunks)packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts
(1 hunks)packages/thirdweb/src/wallets/interfaces/wallet.ts
(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Lint Packages
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Analyze (javascript)
🔇 Additional comments (9)
packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts (1)
53-53
: Changed property visibility from private to publicThe
storage
property has been changed from private to public to support the new authentication token functionality. This enables the in-app wallet to access the storage for retrieving auth tokens.packages/thirdweb/src/wallets/in-app/native/native-connector.ts (1)
32-32
: Changed property visibility from private to publicThe
storage
property has been changed from private to public to maintain consistent interface implementation with theInAppConnector
interface. This change enables the new authentication token functionality.packages/thirdweb/src/wallets/in-app/core/interfaces/connector.ts (2)
3-3
: Added import for ClientScopedStorage typeAdded the import for
ClientScopedStorage
type to support the new storage property in the interface.
42-42
: Added storage property to the InAppConnector interfaceAdded a required
storage
property of typeClientScopedStorage
to the interface. This change formalizes the public storage requirement for all in-app wallet connector implementations, enabling the auth token functionality.packages/thirdweb/src/wallets/interfaces/wallet.ts (1)
154-165
: Added getAuthToken method to the Wallet interfaceAdded a new conditional method
getAuthToken
that's only available for in-app wallets. This method returns the authentication token for the wallet, which can be used for making authorized API calls. The documentation and typings are well-structured with a clear example of usage.packages/thirdweb/src/react/core/hooks/wallets/useAuthToken.ts (1)
4-42
: Well-implemented auth token hook with clear documentation.The
useAuthToken
hook is well-designed and follows React best practices. It correctly checks for all necessary conditions before returning the auth token, and includes comprehensive JSDoc documentation with a practical usage example.packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts (3)
58-58
: LGTM: Auth token state initialization.The auth token state is properly initialized as null.
62-62
: LGTM: Auth token accessor implementation.The
getAuthToken
method correctly exposes the current auth token state.
201-201
: LGTM: Auth token cleanup on disconnect.Properly resets the auth token to null when disconnecting the wallet.
packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts
Outdated
Show resolved
Hide resolved
packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts
Outdated
Show resolved
Hide resolved
4e5b8b4
to
db54597
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7120 +/- ##
=======================================
Coverage 55.61% 55.61%
=======================================
Files 902 902
Lines 58162 58177 +15
Branches 4087 4085 -2
=======================================
+ Hits 32344 32356 +12
- Misses 25713 25716 +3
Partials 105 105
🚀 New features to boost your workflow:
|
size-limit report 📦
|
db54597
to
3f6f8cb
Compare
Merge activity
|
# 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 -->
3f6f8cb
to
526b6b5
Compare
Add
useAuthToken
hook for in-app wallet authenticationThis 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:
useAuthToken()
hook that returns the auth token when an in-app wallet is activeInAppConnector
interface to expose the storage propertygetAuthToken()
method for in-app walletsThe hook ensures the token is only returned when the active wallet is an in-app wallet and matches the active account.
Example usage:
Summary by CodeRabbit
PR-Codex overview
This PR focuses on enhancing wallet functionality by introducing an
authToken
feature for in-app wallets, makingstorage
public, and adding a new hook to retrieve the authentication token.Detailed summary
storage
from private to public innative-connector.ts
andweb-connector.ts
.getAuthToken
method to the wallet interface inwallet.ts
.storage
in theInAppConnector
interface.authToken
retrieval increateInAppWallet
.useAuthToken
hook to fetch the authentication token for the active wallet.