-
Notifications
You must be signed in to change notification settings - Fork 4
[ENG-2416] feat: add jwt provider session storage part 1 #1219
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
Conversation
ba9da51 to
03d13cb
Compare
- adds jose library to handle jwt token expiration / decoding - adds jwt token provider to ampersand context - refactor api service to use jwt token provider
add installation provider to connect provider add feature flag for jwt auth
03d13cb to
9e57468
Compare
- sessionStorage is now used to cache the JWT token - default token expiration time is 10 minutes - jwt token is now cached in sessionStorage - jwt token is now cached in the in-memory cache - jwt token is now cached in the sessionStorage - jwt token is now cached in the in-memory cache
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.
Pull Request Overview
This PR adds JWT token authentication as an alternative to API key authentication for the Ampersand provider. It implements JWT token caching with session storage, expiration handling, and integrates JWT authentication into the API service layer.
- Adds JWT token provider with caching and session storage
- Refactors API service to support both API key and JWT authentication
- Updates AmpersandProvider to accept either apiKey or getToken callback
Reviewed Changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/services/api.ts | Refactors API service to support both API key and JWT authentication with helper functions |
| src/context/JwtTokenContextProvider.tsx | Implements JWT token provider with caching, session storage, and expiration handling |
| src/context/ApiKeyContextProvider.tsx | Removes strict error requirement for API key context |
| src/context/AmpersandContextProvider/AmpersandContextProvider.tsx | Updates provider to accept getToken callback and enforce mutual exclusivity with apiKey |
| src/components/Connect/ConnectProvider.tsx | Wraps ConnectionsProvider with InstallationProvider for JWT auth support |
| package.json | Adds jose library dependency for JWT handling |
| const decoded = await jwtVerify(token, new Uint8Array(0), { | ||
| algorithms: [], // Skip signature verification |
Copilot
AI
Jul 31, 2025
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.
Using an empty Uint8Array and empty algorithms array completely bypasses JWT signature verification, which is a serious security vulnerability. This allows any malformed or malicious JWT to be accepted as valid.
| const decoded = await jwtVerify(token, new Uint8Array(0), { | |
| algorithms: [], // Skip signature verification | |
| const decoded = await jwtVerify(token, "your-verification-key", { | |
| algorithms: ["HS256", "RS256"], // Specify allowed algorithms |
| const decoded = await jwtVerify(token, new Uint8Array(0), { | ||
| algorithms: [], // Skip signature verification | ||
| }); | ||
| const payload = decoded.payload; |
Copilot
AI
Jul 31, 2025
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.
Skipping signature verification defeats the purpose of JWT security. Consider using jose's decodeJwt() function instead if you only need to read the payload without verification, or implement proper signature verification.
| const decoded = await jwtVerify(token, new Uint8Array(0), { | |
| algorithms: [], // Skip signature verification | |
| }); | |
| const payload = decoded.payload; | |
| const payload = decodeJwt(token); |
| }); | ||
|
|
||
| // TODO: remove this flag when we have a proper JWT auth flow | ||
| const ENABLE_JWT_AUTH_FF = false; |
Copilot
AI
Jul 31, 2025
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.
Hard-coded feature flag should be configurable through environment variables or build-time configuration rather than being embedded in the source code.
| const ENABLE_JWT_AUTH_FF = false; | |
| const ENABLE_JWT_AUTH_FF = process.env.ENABLE_JWT_AUTH_FF === "true"; |
| if (cached && cached.expiresAt > now) { | ||
| return cached.token; | ||
| } else { | ||
| tokenCache.delete(cacheKey); |
Copilot
AI
Jul 31, 2025
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.
The tokenCache.delete() operation inside the else block modifies the state directly rather than using setTokenCache, which could lead to inconsistent state and React rendering issues.
| tokenCache.delete(cacheKey); | |
| setTokenCache((prev) => { | |
| const newCache = new Map(prev); | |
| newCache.delete(cacheKey); | |
| return newCache; | |
| }); |
| }); | ||
|
|
||
| // TODO: remove this flag when we have a proper JWT auth flow | ||
| const ENABLE_JWT_AUTH_FF = false; |
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.
turn this to true to test; we can also inject a env flag here later.
Summary
This PR adds the ability for the builder to give a callback
getTokento get a JWT. The API service will detect either an API key or agetTokenoption and use if only one is provided.joselibrary to handle jwt token expiration / decodingENABLE_JWT_AUTH_FFhard coded feature flag blocks usage of JWT for time being though the param is available in AmpersandProviderSupported
InstallationProvider(supported)ConnectProvider(supported)InstallIntegration(not supported yet)Tested
test API key workflow for ConnectProvider
test jwt flow
ENABLE_JWT_AUTH_FF=truerun yarn buildsource vars.sh&./run_mailmonkey.sh)go run generateJWT.goinfeat/jwt-integrationlocalhost:3000/connect(ConnectProvider)JWT Logic
getTokengets token from builder's backendamp-labs/reactapi service will look in local cache (react) andsession storage(browser) for a cached jwt token or callgetTokento use and set in cache/session storage.Session Storage vs Local Storage
Session Storage: same session / same tab - auto clear when tab closes
Local Storage: works across tabs, need manual deletion
Session storage is marginally safer as the need to clear cache is a little less important considering that user will likely close tabs. Session storage will still allow the app to work when user refreshes the page.
Not included
To be most secure, we'll want to implement a http cookie, but 10 min jwt tokens will stil minimize access.
README pr
#1220