Skip to content
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

Fix/refresh token #247

Merged
merged 7 commits into from
Nov 26, 2024
Merged

Fix/refresh token #247

merged 7 commits into from
Nov 26, 2024

Conversation

DanielRivers
Copy link
Contributor

@DanielRivers DanielRivers commented Nov 21, 2024

Explain your changes

Automatically refresh tokens on retrieval

Resolves: #237

Checklist

🛟 If you need help, consider asking for advice over in the Kinde community.

Copy link
Contributor

coderabbitai bot commented Nov 21, 2024

Walkthrough

This pull request introduces enhancements to token management within the application. Key changes include the addition of a validation step for access tokens in the setup function, which now attempts to refresh tokens if validation fails. A new utility function refreshTokens is also introduced to handle the token refresh logic. The getAccessToken function is updated to incorporate this refresh mechanism, ensuring that valid tokens are retrieved or refreshed as necessary. Additionally, type assertions are added to ensure tokens are treated as strings in relevant functions.

Changes

File Change Summary
src/handlers/setup.ts Enhanced token validation; integrated refreshTokens logic; updated error handling for token issues.
src/utils/getAccessToken.ts Modified to implement token refresh mechanism using kindeClient; retains existing error handling and logging.
src/utils/refreshTokens.ts New file defining refreshTokens function to refresh tokens and validate them; includes error logging.
src/session/getOrganization.ts Added type assertion for accessToken to ensure it is treated as a string.
src/session/getUser.ts Added type assertions for rawToken and accessToken to ensure they are treated as strings.
src/utils/getIdToken.ts Enhanced token validation and refresh logic; added tokenKey variable for clarity in session handling.
src/authMiddleware/authMiddleware.ts Minor formatting adjustments; no significant changes to logic or error handling.
src/routerClients/AppRouterClient.js Updated constructor for structured configuration of Kinde client; minor formatting changes.
src/session/getAccessToken.js Minor formatting adjustments; no changes to logic or error handling.
src/session/getIdToken.js Reformatted import statement; no changes to logic or error handling.
src/session/isAuthenticated.js Minor formatting adjustments; no changes to functionality.
src/session/sessionManager.js Enhanced session management logic; improved error logging and cookie handling.
src/utils/generateOrganizationObject.ts Minor formatting adjustments; no changes to logic or error handling.
src/utils/validateToken.ts Improved formatting and readability; no changes to core logic.
src/utils/version.js Added semicolon to export statement; no changes to version number or logic.

Assessment against linked issues

Objective Addressed Explanation
Implement a middleware function to monitor tokens approaching expiry (#[237])

Possibly related PRs

  • feat: adding refreshData #180: The changes in this PR involve adding a refreshData function that may relate to the overall token management and refreshing logic, which is relevant to the main PR's updates on token validation and refresh handling.
  • fix: validate token on isAuthenticated #223: This PR focuses on validating tokens in the authentication middleware, which directly connects to the main PR's enhancements in token validation and error handling.
  • Fix: Token validation strength #243: This PR enhances the token validation process, which aligns with the main PR's updates to improve token validation and error handling in the setup function.

Suggested reviewers

  • DaveOrDead
  • peterphanouvong

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/utils/validateToken.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-jest".

(The package "eslint-plugin-jest" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-jest@latest --save-dev

The plugin "eslint-plugin-jest" was referenced from the config file in ".eslintrc.json".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 69fa795 and bb17e9a.

📒 Files selected for processing (1)
  • src/utils/validateToken.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utils/validateToken.ts

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@DanielRivers DanielRivers changed the base branch from main to fix/token-validation November 21, 2024 18:34
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (21)
src/server/index.js (1)

Line range hint 1-9: Documentation update may be needed

Since this change removes a previously exported middleware, please ensure that:

  1. The documentation is updated to reflect this change
  2. A migration guide is provided for users who need to switch from authMiddleware to withAuth
  3. The changelog includes this breaking change

Would you like me to help draft the documentation updates or migration guide?

clientConfig/rollup.config.js (1)

Line range hint 3-5: Consider configuring TypeScript plugin options

The TypeScript plugin is included but lacks specific configuration. Consider adding TypeScript compiler options to the plugin configuration for better control over the compilation process.

 import babel from '@rollup/plugin-babel';
 import {terser} from 'rollup-plugin-terser';
 import tsPlugin from '@rollup/plugin-typescript';
 
 export default {
-  plugins: [babel({babelHelpers: 'bundled'}), terser(), tsPlugin()],
+  plugins: [
+    babel({babelHelpers: 'bundled'}),
+    terser(),
+    tsPlugin({
+      tsconfig: './tsconfig.json',
+      declaration: true,
+      declarationDir: './dist/types',
+      rootDir: './src'
+    })
+  ],
src/session/getAccessToken.js (2)

19-20: Consider separating error handling

The current implementation catches errors from both getAccessToken and jwtDecoder in the same try-catch block. Consider handling them separately to provide more specific error handling and logging.

export const getAccessTokenFactory = (req, res) => async () => {
  try {
    const accessToken = await getAccessToken(req, res);
-    return jwtDecoder(accessToken) 
+    try {
+      return jwtDecoder(accessToken);
+    } catch (jwtError) {
+      if (config.isDebugMode) {
+        console.error('JWT decoding failed:', jwtError);
+      }
+      return null;
+    }
  } catch (err) {
    if (config.isDebugMode) {
-      console.error(err);
+      console.error('Access token retrieval failed:', err);
    }
    return null;
  }
};

Based on the evidence gathered, I can now provide the final response:

Token refresh mechanism is missing and needs to be implemented

The current implementation in getAccessToken.ts has a placeholder comment "look for refresh token" but lacks actual refresh token handling:

  • No refresh token implementation exists despite token validation
  • The function simply returns null when tokens are invalid
  • No integration with the OAuth token endpoint for refresh flows

This could lead to unnecessary logouts when tokens expire. Consider:

  • Implementing token refresh logic when validation fails
  • Using the OAuth token endpoint at ${config.issuerURL}/oauth2/token
  • Storing and managing refresh tokens in the session
🔗 Analysis chain

Line range hint 1-24: Verify integration with refresh token mechanism

Since this PR focuses on fixing the refresh token mechanism, we should verify how this implementation integrates with the token refresh flow.


Let me gather more information about the token handling implementation.


Let me check one more aspect to see if there's any token refresh implementation in other files or if there are any token refresh endpoints being used.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check integration with refresh token mechanism
# Expected: Should see proper token refresh handling

# Look for refresh token handling
rg -A 10 "refresh.*token" "src/utils/getAccessToken.ts"

# Check for token refresh related tests
fd -e test.ts -e test.js -e spec.ts -e spec.js | xargs rg "refresh.*token"

# Look for other components using getAccessToken
ast-grep --pattern 'import { getAccessToken } from "$_"'

Length of output: 405


Script:

#!/bin/bash
# Check the complete implementation of getAccessToken utility
cat src/utils/getAccessToken.ts

# Look for token-related error handling and refresh logic
rg -A 5 "token.*expired|invalid.*token" 

# Check for any token refresh implementations
ast-grep --pattern 'async function refreshToken($$$) { $$$ }'
ast-grep --pattern 'const refreshToken = async ($$$) => { $$$ }'

Length of output: 2649


Script:

#!/bin/bash
# Look for token refresh related endpoints or implementations
rg -A 5 "refresh.*token.*endpoint|token.*refresh.*url"

# Check for any OAuth token refresh implementations
rg -A 10 "oauth.*token|token.*refresh" src/

# Look for refresh token storage or handling in session manager
cat src/session/sessionManager.ts

Length of output: 1931

src/session/getIdToken.js (1)

4-4: Consider migrating this file to TypeScript

Since this file imports from TypeScript modules and handles sensitive authentication logic, consider migrating it to TypeScript to maintain consistency and leverage type safety across the authentication flow.

src/session/getOrganization.ts (2)

29-29: Consider adding explicit token validation

While the code correctly decodes the token, consider adding explicit validation of the decoded token's contents before using it.

 const accessToken = await getAccessToken(req, res);
 const decodedToken = jwtDecoder<KindeAccessToken>(accessToken)
+if (!decodedToken || !decodedToken.org_code) {
+  throw new Error('Invalid access token structure');
+}
 return generateOrganizationObject(idToken, decodedToken);

Also applies to: 31-31


Line range hint 32-37: Consider more specific error handling

The current catch-all error handling could be more specific to help with debugging and user feedback.

   } catch (error) {
     if (config.isDebugMode) {
-      console.error(error);
+      console.error('Failed to get organization:', error instanceof Error ? error.message : 'Unknown error');
     }
     return null;
   }
src/utils/getIdToken.ts (2)

6-10: Add JSDoc documentation for better code maintainability.

The implementation looks good, but adding JSDoc documentation would improve code maintainability and IDE support.

+/**
+ * Retrieves and validates the ID token from the session.
+ * @param req - Next.js API request
+ * @param res - Next.js API response
+ * @returns Promise<string | null> - The validated ID token or null if invalid/missing
+ */
 export const getIdToken = async(req: NextApiRequest, res: NextApiResponse) => {

30-37: Consider handling specific error types differently.

The current implementation catches all errors and returns null. Consider handling specific error types (e.g., validation errors vs network errors) differently for better error reporting.

-    } catch (error) {
+    } catch (error: unknown) {
+        if (error instanceof Error) {
+            if (config.isDebugMode) {
+                console.error('getIdToken:', error.message);
+            }
+            // Handle specific error types
+            if (error.name === 'ValidationError') {
+                return null;
+            }
+            if (error.name === 'NetworkError') {
+                throw error; // Let the caller handle network errors
+            }
+        }
         if (config.isDebugMode) {
-            console.error('getIdToken', error);
+            console.error('getIdToken: Unknown error occurred');
         }
         return null;
     }
src/utils/getAccessToken.ts (1)

35-40: Consider adding more specific error handling.

While the current error handling is functional, it could be more informative by:

  1. Distinguishing between different types of errors (validation errors vs network errors)
  2. Providing more context in the error logs
 } catch (error) {
     if (config.isDebugMode) {
-        console.error('getAccessToken', error);
+        console.error('getAccessToken error:', {
+            type: error instanceof Error ? error.name : 'Unknown',
+            message: error instanceof Error ? error.message : String(error),
+            stack: error instanceof Error ? error.stack : undefined
+        });
     }
     return null;
 }
src/handlers/callback.ts (3)

Line range hint 44-53: Strengthen URL validation to prevent open redirect vulnerabilities

The current URL validation only checks if the URL starts with 'http', which could allow malicious redirects. Consider implementing stronger URL validation:

   if (postLoginRedirectURL) {
-    if (postLoginRedirectURL.startsWith('http')) {
-      return routerClient.redirect(postLoginRedirectURL);
+    // Validate against allowed domains
+    const allowedDomains = [new URL(routerClient.clientConfig.siteUrl).hostname];
+    try {
+      const redirectUrl = new URL(postLoginRedirectURL);
+      if (allowedDomains.includes(redirectUrl.hostname)) {
+        return routerClient.redirect(postLoginRedirectURL);
+      }
+      throw new Error('Invalid redirect domain');
+    } catch {
+      // If URL parsing fails or domain not allowed, redirect to relative path
+      return routerClient.redirect(
+        `${routerClient.clientConfig.siteUrl}${postLoginRedirectURL}`
+      );
     }
-    return routerClient.redirect(
-      `${routerClient.clientConfig.siteUrl}${postLoginRedirectURL}`
-    );
   }

Line range hint 21-40: Consider enhancing error handling

The error handling could be more robust by:

  1. Using specific error types instead of string matching
  2. Logging structured error information in debug mode
   } catch (error) {
     if (config.isDebugMode) {
-      console.error('callback', error);
+      console.error('Callback handler error', {
+        error: error.message,
+        stack: error.stack,
+        url: routerClient.getUrl()
+      });
     }

-    if (error.message.includes('Expected: State not found')) {
+    if (error instanceof StateNotFoundError) {
       return routerClient.json(
         {
           error:
             `Error: State not found.\nTo resolve this error please visit our docs https://docs.kinde.com/developer-tools/sdks/backend/nextjs-sdk/#state-not-found-error` +
             error.message
         },
         {status: 500}
       );
     }

-    return routerClient.json({error: error.message}, {status: 500});
+    return routerClient.json({
+      error: 'Authentication failed. Please try again.',
+      details: config.isDebugMode ? error.message : undefined
+    }, {status: 500});

Incomplete refresh token implementation found

The code in getAccessToken.ts contains a comment "look for refresh token" but no actual implementation of token refresh logic. The related files (RouterClient.ts, sessionManager.ts, KindeClient.ts) appear to be missing or not accessible, suggesting the refresh token mechanism mentioned in PR objectives is not fully implemented.

  • src/utils/getAccessToken.ts: Contains a placeholder comment for refresh token logic but no implementation
  • Missing critical files:
    • src/routerClients/RouterClient.ts
    • src/session/sessionManager.ts
    • KindeClient.ts
🔗 Analysis chain

Line range hint 1-53: Verify refresh token implementation

While this file handles the callback flow, it doesn't directly address the refresh token mechanism mentioned in the PR objectives.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for refresh token related implementations
echo "Searching for refresh token related files..."
rg -l "refresh.*token" --type ts

echo "\nSearching for token validation implementations..."
ast-grep --pattern 'function $_(token: $_) {
  $$$
}'

Length of output: 330


Script:

#!/bin/bash
# Let's examine the refresh token implementation in getAccessToken.ts
echo "Content of getAccessToken.ts:"
cat src/utils/getAccessToken.ts

# Search for token refresh related methods in RouterClient
echo -e "\nSearching for token refresh methods in RouterClient:"
rg -A 10 "refresh.*token" src/routerClients/RouterClient.ts

# Look for session management implementations
echo -e "\nSearching for session token management:"
ast-grep --pattern 'class SessionManager {
  $$$
}'

Length of output: 1678


Script:

#!/bin/bash
# Let's check the session manager implementation
echo "Searching for session manager file:"
fd "sessionManager.ts"

echo -e "\nChecking session manager content:"
cat src/session/sessionManager.ts

# Look for KindeClient implementation which might handle token refresh
echo -e "\nSearching for KindeClient implementation:"
fd "KindeClient.ts"

Length of output: 403

src/api-client.js (2)

32-32: Consider caching the API token

The current implementation always removes and regenerates the API token, which could be inefficient. Consider implementing token caching with expiration checks to reduce unnecessary token requests.

Here's a suggested implementation:

 const store = await sessionManager(req, res);
-store.removeSessionItem('kinde_api_access_token');
+const cachedToken = store.getSessionItem('kinde_api_access_token');
+if (cachedToken) {
+  try {
+    const decoded = JSON.parse(atob(cachedToken.split('.')[1]));
+    if (decoded.exp * 1000 > Date.now()) {
+      return cachedToken;
+    }
+  } catch (e) {
+    // Invalid token format, proceed to fetch new token
+  }
+}
+store.removeSessionItem('kinde_api_access_token');

Line range hint 34-45: Add error handling for token fetch

The token fetch operation lacks error handling and timeout management, which could lead to unhandled exceptions or hanging requests.

Consider implementing proper error handling:

-  const response = await fetch(`${config.issuerURL}/oauth2/token`, {
-    method: 'POST',
-    headers: {
-      'content-type': 'application/x-www-form-urlencoded'
-    },
-    body: new URLSearchParams({
-      grant_type: 'client_credentials',
-      client_id: config.clientID || '',
-      client_secret: config.clientSecret || '',
-      audience: config.issuerURL + '/api'
-    })
-  });
-  apiToken = (await response.json()).access_token;
+  try {
+    const controller = new AbortController();
+    const timeoutId = setTimeout(() => controller.abort(), 5000);
+    
+    const response = await fetch(`${config.issuerURL}/oauth2/token`, {
+      method: 'POST',
+      headers: {
+        'content-type': 'application/x-www-form-urlencoded'
+      },
+      body: new URLSearchParams({
+        grant_type: 'client_credentials',
+        client_id: config.clientID || '',
+        client_secret: config.clientSecret || '',
+        audience: config.issuerURL + '/api'
+      }),
+      signal: controller.signal
+    });
+    
+    clearTimeout(timeoutId);
+    
+    if (!response.ok) {
+      throw new Error(`HTTP error! status: ${response.status}`);
+    }
+    
+    const data = await response.json();
+    if (!data.access_token) {
+      throw new Error('No access token received');
+    }
+    
+    apiToken = data.access_token;
+    store.setSessionItem('kinde_api_access_token', apiToken);
+  } catch (error) {
+    if (error.name === 'AbortError') {
+      throw new Error('Request timeout while fetching access token');
+    }
+    throw new Error(`Failed to fetch access token: ${error.message}`);
+  }
src/handlers/setup.ts (1)

17-24: Enhance error handling and type safety.

While the validation logic is correct, consider these improvements:

  1. Add more descriptive error messages including validation details
  2. Add type checking for the token parameter
-    const accessTokenValidation = await validateToken({
+    if (!accessTokenEncoded || typeof accessTokenEncoded !== 'string') {
+      throw new Error('Access token is missing or invalid format');
+    }
+    const accessTokenValidation = await validateToken({
       token: accessTokenEncoded,
       domain: config.issuerURL
     })

     if (!accessTokenValidation.valid) {
-      throw new Error('Invalid access token');
+      throw new Error(`Invalid access token: ${accessTokenValidation.error?.message || 'unknown error'}`);
     }
src/session/sessionManager.js (3)

103-110: Consider optimizing cookie cleanup performance

The cookie cleanup logic could be more efficient by using filter instead of map+forEach.

-    cookieStore
-      .getAll()
-      .map((c) => c.name)
-      .forEach((key) => {
-        if (key.startsWith(`${String(itemKey)}`)) {
-          cookieStore.delete(key);
-        }
-      });
+    const cookies = cookieStore.getAll();
+    cookies
+      .filter(c => c.name.startsWith(`${String(itemKey)}`))
+      .forEach(c => cookieStore.delete(c.name));

Line range hint 8-13: Enhance security configuration for token cookies

Current security configuration has potential vulnerabilities:

  1. Secure flag is only set in production
  2. No validation of cookie domain configuration
  3. No explicit HTTPS enforcement

Consider:

  1. Always enabling secure flag for token cookies
  2. Validating cookie domain configuration
  3. Adding HTTPS enforcement middleware
 export const GLOBAL_COOKIE_OPTIONS = {
   sameSite: 'lax',
   httpOnly: true,
-  secure: process.env.NODE_ENV === 'production',
+  secure: true,  // Always require HTTPS for token cookies
   path: '/'
 };

Incomplete refresh token implementation detected

The codebase shows an incomplete implementation of refresh token handling:

  • getAccessToken.ts has a commented placeholder for refresh token logic ("// look for refresh token")
  • sessionManager.js only handles storage/retrieval of refresh tokens but lacks actual refresh mechanism
  • No implementation found for token refresh flow when access token becomes invalid
🔗 Analysis chain

Line range hint 1-1: Verify complete refresh token fix implementation

While this file improves cookie cleanup, it's unclear how it addresses the refresh token issues mentioned in the PR objectives.

Let's check for related changes:


Let me check the content of these files to understand the refresh token implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Look for other files handling refresh tokens
rg -l "refresh.*token" --type ts --type js

# Check for recent changes to refresh token handling
git log -p --grep="refresh.*token"

Length of output: 102


Script:

#!/bin/bash
# Check the content of files handling refresh tokens
echo "=== sessionManager.js ==="
cat src/session/sessionManager.js

echo -e "\n=== getAccessToken.ts ==="
cat src/utils/getAccessToken.ts

Length of output: 9670

src/authMiddleware/authMiddleware.ts (1)

Line range hint 55-68: Simplify conditional logic to reduce redundancy

The conditions validateTokenResponse.valid && customValidationValid are checked multiple times. Consider refactoring to streamline the control flow and improve readability.

Here's a suggested refactor to consolidate the condition checks:

  if (!validateTokenResponse.valid || !customValidationValid) {
    return NextResponse.redirect(
      new URL(loginRedirectUrl, options?.redirectURLBase || config.redirectURL)
    );
  }

- if (validateTokenResponse.valid && customValidationValid && onSuccess) {
+ if (onSuccess) {
    return await onSuccess({
      token: accessTokenValue,
      user: {
        family_name: idTokenValue.family_name,
        given_name: idTokenValue.given_name,
        email: idTokenValue.email,
        id: idTokenValue.sub,
        picture: idTokenValue.picture
      }
    });
  }

- if (validateTokenResponse.valid && customValidationValid) {
-   return;
- }

+ return;

This refactoring handles the redirect early if validation fails and proceeds with onSuccess or returns accordingly if validation passes.

src/config/index.ts (1)

68-68: Ensure consistent naming conventions for property names

Consider standardizing the casing of property names to improve code consistency and readability. For example, use clientId instead of clientID to maintain consistent camelCase formatting across the codebase.

Also applies to: 88-88

🛑 Comments failed to post (7)
src/session/isAuthenticated.js (1)

11-14: 🛠️ Refactor suggestion

Add error handling for token and user retrieval

The current implementation lacks explicit error handling for failed token retrieval or user fetch operations. This could lead to silent failures and make debugging more difficult.

Consider adding error handling:

export const isAuthenticatedFactory = (req, res) => async () => {
-  const token = getAccessToken(req, res);
+  try {
+    const token = getAccessToken(req, res);
+    const user = await getUserFactory(req, res)();
+    return token && Boolean(user);
+  } catch (error) {
+    console.error('Authentication check failed:', error);
+    return false;
+  }
-  const user = await getUserFactory(req, res)();
-  return token && Boolean(user);
};

Additionally, consider adding logging to track authentication failures for better observability.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

export const isAuthenticatedFactory = (req, res) => async () => {
  try {
    const token = getAccessToken(req, res);
    const user = await getUserFactory(req, res)();
    return token && Boolean(user);
  } catch (error) {
    console.error('Authentication check failed:', error);
    return false;
  }
};
src/session/getUser.ts (1)

14-19: 💡 Codebase verification

Error handling is properly implemented but token refresh is incomplete

The error propagation chain is properly implemented with all functions returning null on errors and logging in debug mode. However, there's an incomplete token refresh implementation in getAccessToken:

  • getIdToken properly validates and returns null for invalid/missing tokens
  • getAccessToken has a commented "look for refresh token" section that's not implemented
  • getUser properly handles errors from both token utilities
🔗 Analysis chain

Verify error propagation from token utilities.

The code correctly retrieves and decodes both ID and access tokens. However, we should verify that token refresh errors are properly propagated from the new utility functions.

Consider adding specific error types for token-related failures to improve error handling:

interface TokenError extends Error {
  code: 'TOKEN_EXPIRED' | 'TOKEN_INVALID' | 'TOKEN_MISSING';
}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check error handling in token utility functions

# Check error handling in getIdToken
ast-grep --pattern 'export function getIdToken($_) {
  try {
    $$$
  } catch($_) {
    $$$
  }
}'

# Check error handling in getAccessToken
ast-grep --pattern 'export function getAccessToken($_) {
  try {
    $$$
  } catch($_) {
    $$$
  }
}'

Length of output: 207


Script:

#!/bin/bash
# Let's try a different approach to find the token utility functions and their implementations

# Search for getIdToken function definition
rg "function getIdToken" -A 10

# Search for getAccessToken function definition
rg "function getAccessToken" -A 10

# Also search for any error handling related to these functions
rg "throw|catch" --type ts

Length of output: 892


Script:

#!/bin/bash
# Let's examine the implementation of token utility functions

# Check getIdToken implementation
cat src/utils/getIdToken.ts

# Check getAccessToken implementation
cat src/utils/getAccessToken.ts

# Check how errors are handled in getUser.ts
cat src/session/getUser.ts

Length of output: 3402

src/utils/getAccessToken.ts (1)

23-32: ⚠️ Potential issue

Implement refresh token logic in the invalid token case.

There's a comment indicating refresh token logic should be implemented here, but the implementation is missing. Given this PR's focus on fixing refresh token functionality, this section should handle token refresh when the current token is invalid.

Would you like me to help implement the refresh token logic? A typical implementation would:

  1. Check for a refresh token in the session
  2. If present, use it to obtain a new access token
  3. Update the session with the new token
  4. Return the new token or null if refresh fails
src/handlers/callback.ts (1)

6-8: 🛠️ Refactor suggestion

Add type validation before type assertion

The type assertion as string could mask potential type-related issues if the session item is undefined or null. Consider adding validation:

-    (await routerClient.sessionManager.getSessionItem(
-      'post_login_redirect_url'
-    )) as string;
+    const redirectUrl = await routerClient.sessionManager.getSessionItem(
+      'post_login_redirect_url'
+    );
+    if (redirectUrl !== undefined && typeof redirectUrl !== 'string') {
+      throw new Error('post_login_redirect_url must be a string');
+    }
+    redirectUrl as string;

Committable suggestion skipped: line range outside the PR's diff.

src/handlers/setup.ts (1)

30-37: 🛠️ Refactor suggestion

Refactor duplicate token validation logic.

The ID token validation duplicates the access token validation logic. Consider extracting this into a reusable function.

+    const validateTokenWithType = async (token: string | null, tokenType: string) => {
+      if (!token || typeof token !== 'string') {
+        throw new Error(`${tokenType} is missing or invalid format`);
+      }
+      const validation = await validateToken({
+        token,
+        domain: config.issuerURL
+      });
+      if (!validation.valid) {
+        throw new Error(`Invalid ${tokenType}: ${validation.error?.message || 'unknown error'}`);
+      }
+    };
+
-    const idTokenValidation = await validateToken({
-      token: idTokenEncoded,
-      domain: config.issuerURL
-    })
-
-    if (!idTokenValidation.valid) {
-      throw new Error('Invalid id token');
-    }
+    await validateTokenWithType(accessTokenEncoded, 'access token');
+    await validateTokenWithType(idTokenEncoded, 'ID token');

Committable suggestion skipped: line range outside the PR's diff.

src/config/index.ts (2)

63-63: 🛠️ Refactor suggestion

Define a specific type for initialState instead of any

Using any defeats the purpose of TypeScript's type safety. Defining a specific type for initialState will improve code maintainability and prevent potential runtime errors.

Would you like assistance in defining the appropriate type for initialState?


71-71: 🛠️ Refactor suggestion

Type audience as string[] and default to an empty array

To maintain type consistency and avoid potential runtime errors, consider typing audience as string[] and defaulting to an empty array when KINDE_AUDIENCE is not provided.

Apply this diff to adjust the type and default value:

- audience: string[] | '';
+ audience: string[];

And update the default assignment in the config object:

- audience: KINDE_AUDIENCE ? KINDE_AUDIENCE.split(' ') : '',
+ audience: KINDE_AUDIENCE ? KINDE_AUDIENCE.split(' ') : [],

Also applies to: 86-86

@DanielRivers
Copy link
Contributor Author

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Nov 21, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 and nitpick comments (5)
src/utils/refreshTokens.ts (1)

12-27: Enhance error handling and logging

The current error handling approach might mask different types of failures and make debugging more difficult.

Consider these improvements:

         if (token && typeof token === 'string') {
-            const validationResult = await validateToken({
-                token,
-                domain: config.issuerURL
-            });
+            try {
+                const validationResult = await validateToken({
+                    token,
+                    domain: config.issuerURL
+                });
 
-            return validationResult.valid
+                return validationResult.valid;
+            } catch (validationError) {
+                if (config.isDebugMode) {
+                    console.error('Token validation failed:', validationError);
+                }
+                return false;
+            }
         } 
         return false;
         
     } catch (error) {
         if (config.isDebugMode) {
-            console.error('refreshTokens', error);
+            console.error('Token refresh failed:', {
+                error: error instanceof Error ? error.message : 'Unknown error',
+                stack: error instanceof Error ? error.stack : undefined
+            });
         }
         return false;
     }
src/handlers/setup.ts (4)

24-26: Fix typo in error message and enhance error handling

The error message contains a typo ("refrehs" should be "refresh").

-        throw new Error('Invalid access token and refrehs failed');
+        throw new Error('Invalid access token and refresh failed');

24-26: Consider enhancing the refresh token implementation

The current implementation has several potential improvements to consider:

  1. Add a mechanism to prevent infinite refresh loops
  2. Include more detailed error information (e.g., original validation error)
  3. Consider adding specific error types for better error handling

Consider implementing something like this:

if (!accessTokenValidation.valid) {
  try {
    const refreshResult = await refreshTokens(routerClient.sessionManager);
    if (!refreshResult) {
      throw new Error(`Token refresh failed: ${accessTokenValidation.error}`);
    }
  } catch (refreshError) {
    throw new Error(`Failed to refresh invalid access token: ${refreshError.message}. Original validation error: ${accessTokenValidation.error}`);
  }
}

Line range hint 93-109: Consider enhancing error handling for different JWT error types

The current error handling only specifically handles ERR_JWT_EXPIRED. Consider handling other JWT-specific error cases and providing more detailed error information in debug mode.

} catch (error) {
  if (config.isDebugMode) {
    console.debug('Token setup error:', {
      error,
      code: error.code,
      message: error.message,
      stack: error.stack
    });
  }

  switch (error.code) {
    case 'ERR_JWT_EXPIRED':
      return routerClient.json(
        { needsRefresh: true },
        { status: 200 }
      );
    case 'ERR_JWT_INVALID':
    case 'ERR_JWT_MALFORMED':
      return routerClient.json(
        { error: 'Invalid token format' },
        { status: 401 }
      );
    default:
      return routerClient.json(
        { error: 'Internal server error' },
        { status: 500 }
      );
  }
}

Line range hint 13-109: Consider adding atomic token refresh and retry mechanism

The current implementation could benefit from additional architectural improvements:

  1. Consider implementing an atomic token refresh mechanism to prevent race conditions when multiple requests attempt to refresh tokens simultaneously.
  2. Add retry logic with exponential backoff for token refresh attempts.
  3. Consider implementing a token cache to reduce the number of validation and refresh operations.

Would you like assistance in implementing these architectural improvements?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e19c505 and 42407fa.

📒 Files selected for processing (3)
  • src/handlers/setup.ts (2 hunks)
  • src/utils/getAccessToken.ts (2 hunks)
  • src/utils/refreshTokens.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utils/getAccessToken.ts
🔇 Additional comments (2)
src/utils/refreshTokens.ts (1)

1-4: LGTM! Imports are well-organized

The imports are properly structured with a clear separation between external packages and internal modules.

src/handlers/setup.ts (1)

6-6: Verify the refreshTokens utility implementation

The import suggests a new utility file. Let's ensure it exists and follows best practices.

✅ Verification successful

Implementation of refreshTokens utility looks correct and follows best practices

The utility implementation:

  • Properly handles token refresh using Kinde SDK's client
  • Validates the refreshed token using @kinde/jwt-validator
  • Includes appropriate error handling and debug logging
  • Returns boolean indicating success/failure of refresh operation
  • Uses correct type annotations with SessionManager
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the refreshTokens utility implementation
# Check if the file exists and examine its implementation
fd "refreshTokens.ts" --type f --exec cat {}

Length of output: 896

src/utils/refreshTokens.ts Outdated Show resolved Hide resolved
src/utils/refreshTokens.ts Outdated Show resolved Hide resolved
@DanielRivers DanielRivers changed the base branch from fix/token-validation to main November 26, 2024 15:00
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 and nitpick comments (2)
src/session/getUser.ts (1)

Line range hint 14-24: Consider implementing comprehensive token validation

While the type assertions handle the immediate type safety concerns, consider implementing a more robust token validation strategy:

  1. Add token expiration checks before attempting refresh
  2. Consider implementing retry logic for failed refresh attempts
  3. Add logging for token refresh events in debug mode

Would you like assistance in implementing these improvements?

src/session/getOrganization.ts (1)

Line range hint 29-33: Consider adding refresh token error handling

The catch block currently returns null for all errors, which might mask specific token refresh failures. Consider adding specific error handling for refresh token scenarios.

Apply this diff to improve error handling:

  } catch (error) {
    if (config.isDebugMode) {
-     console.error(error);
+     if (error instanceof Error) {
+       console.error('Organization retrieval failed:', error.message);
+       // Log specific error types for token refresh failures
+       if (error.message.includes('refresh')) {
+         console.error('Token refresh failed - user may need to re-authenticate');
+       }
+     }
    }
    return null;
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 42407fa and 086d2de.

📒 Files selected for processing (6)
  • src/handlers/setup.ts (3 hunks)
  • src/session/getOrganization.ts (1 hunks)
  • src/session/getUser.ts (1 hunks)
  • src/utils/getAccessToken.ts (2 hunks)
  • src/utils/getIdToken.ts (2 hunks)
  • src/utils/refreshTokens.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/handlers/setup.ts
  • src/utils/getAccessToken.ts
  • src/utils/refreshTokens.ts
🔇 Additional comments (7)
src/session/getUser.ts (2)

20-20: 🛠️ Refactor suggestion

Enhance error handling for token refresh scenarios

With the new refresh token mechanism in getAccessToken, the type assertion might mask potential errors during the refresh process. Consider:

  1. Adding specific error handling for refresh failures
  2. Documenting the possible return types and error scenarios

Here's a suggested improvement:

-      const accessToken = await getAccessToken(req, res) as string;
+      const accessToken = await getAccessToken(req, res);
+      if (typeof accessToken !== 'string') {
+        if (config.isDebugMode) {
+          console.debug('Access token refresh failed:', accessToken);
+        }
+        return null;
+      }

Let's verify the token refresh implementation:


14-14: Verify type assertion necessity and token refresh handling

The type assertion as string might be redundant since there's an explicit null check immediately after. Consider letting TypeScript infer the type or using type guards instead.

Let's verify the return type of getIdToken and its usage:

✅ Verification successful

Let me gather more information about the getIdToken implementation since we only see its usage but not its definition.


Let's check the content of these files to understand the implementation and return types.


Type assertion is necessary and correctly implemented

The type assertion as string is actually necessary and correct here because:

  1. The getIdToken function in src/utils/getIdToken.ts returns either a string token or null
  2. The subsequent code specifically handles the null case with an explicit check
  3. When the token exists, it's guaranteed to be a string due to the runtime check typeof token !== 'string' in the implementation
  4. The type assertion helps TypeScript understand that non-null values are definitely strings
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check getIdToken implementation and usage
# Expected: Find the return type definition and other usages to ensure type consistency

# Check getIdToken implementation
ast-grep --pattern 'export $_ getIdToken = $_'

# Check other usages of getIdToken
rg -A 3 'getIdToken\(' --type ts

Length of output: 288


Script:

#!/bin/bash
# Search for getIdToken function definition
ast-grep --pattern 'function getIdToken($_) {
  $$$
}'

# Also check for const/let/var declaration
ast-grep --pattern '$_ getIdToken = $_'

# Search for files containing getIdToken to ensure we don't miss any implementation
fd getIdToken

Length of output: 193


Script:

#!/bin/bash
# Check content of all files related to getIdToken
cat src/session/getIdToken.js src/session/getIdTokenRaw.js src/utils/getIdToken.ts

# Also search for type definitions related to these functions
rg -g '*.d.ts' 'getIdToken'

Length of output: 2597

src/session/getOrganization.ts (1)

28-29: Verify token refresh integration

Since getAccessToken has been updated to include refresh token functionality, we should verify that the token refresh mechanism works correctly with this implementation.

Let's verify the token refresh integration:

✅ Verification successful

Let me gather more information about the token refresh implementation.


Let me check the complete implementation of getAccessToken to understand the full context of the refresh token logic.


Token refresh mechanism is properly integrated and handled

The implementation in getAccessToken.ts shows a robust token refresh flow:

  • Validates the existing token first
  • Attempts to refresh the token when validation fails
  • Includes proper error handling and debugging
  • Returns null for invalid tokens, triggering re-authentication

The usage in getOrganization.ts is correct as it properly handles the token type and potential failures.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of getAccessToken and its usage
# Expected: Find the refresh token logic and verify error handling

# Check getAccessToken implementation
echo "Checking getAccessToken implementation:"
ast-grep --pattern 'export const getAccessToken = async $_' -A 20

# Check for other files using getAccessToken to ensure consistent error handling
echo "Checking getAccessToken usage:"
rg "getAccessToken\(" --type ts -A 2

Length of output: 681


Script:

#!/bin/bash
# Let's check the implementation of getAccessToken and related token refresh logic

# Find the getAccessToken implementation file
echo "Finding getAccessToken implementation file:"
fd "getAccessToken.ts"

# Search for token refresh related code
echo -e "\nSearching for token refresh implementation:"
rg "refresh.*token" --type ts -A 3

# Look for error handling in token-related files
echo -e "\nChecking error handling in token-related code:"
rg "throw.*Error.*token" --type ts -A 2

Length of output: 1752


Script:

#!/bin/bash
# Get the complete implementation of getAccessToken

echo "Content of getAccessToken.ts:"
cat src/utils/getAccessToken.ts

# Check for any session-related types and interfaces
echo -e "\nChecking for session-related types:"
rg "interface.*Session|type.*Session" --type ts -A 3

Length of output: 1555

src/utils/getIdToken.ts (4)

5-8: Good improvement with string constant extraction!

Moving the token key to a constant improves maintainability and reduces the risk of typos. The new import is properly aligned with the refresh token functionality.


Line range hint 11-23: Good addition of type checking!

The explicit type check typeof token !== 'string' improves type safety and prevents potential runtime issues. The validation flow is well-structured.


Line range hint 29-42: Error handling looks good!

The error handling is consistent and properly utilizes the debug mode configuration for logging.


5-5: Verify kindeClient integration and usage

Let's ensure the refresh token implementation is consistent across the codebase.

✅ Verification successful

Based on the results, I can now provide a final response as the verification is complete. The implementation shows a consistent pattern across the codebase:

Token refresh implementation is properly integrated

The refresh token implementation is consistent across the codebase with proper integration:

  • Centralized refreshTokens utility in src/utils/refreshTokens.ts
  • Consistent usage pattern in token validation flows:
    • getAccessToken.ts
    • getIdToken.ts
    • setup.ts
  • Proper error handling and debug logging
  • Consistent integration with kindeClient and token validation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other uses of refreshTokens and token validation patterns
echo "Checking for refreshTokens usage patterns..."
rg "refreshTokens" -A 5 -B 5

echo "Checking for token validation patterns..."
rg "validateToken" -A 5 -B 5

echo "Checking for other potential token refresh implementations..."
ast-grep --pattern 'if (!$token) { $$$ }'

Length of output: 16036

src/session/getOrganization.ts Outdated Show resolved Hide resolved
src/utils/getIdToken.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (6)
src/utils/validateToken.ts (4)

17-17: Remove debug console.log statement

This debug statement should not be present in production code.

-    console.log('attempting to validate token');

10-15: Enhance error logging specificity

The error message could be more specific about whether the token is missing or has an invalid type.

     if (config.isDebugMode) {
-      console.error('validateToken: invalid token or token is missing');
+      console.error(
+        `validateToken: ${!token ? 'token is missing' : 'token must be a string'}`
+      );
     }

18-28: Add type assertion and enhance error details

Consider adding type assertion for validation result and including more error details in debug mode.

     const validationResult = await jwtValidator({
       token,
       domain: config.issuerURL
-    });
+    }) as { valid: boolean; error?: string };

     if (!validationResult.valid) {
       if (config.isDebugMode) {
-        console.error('validateToken: invalid token');
+        console.error('validateToken: invalid token', 
+          validationResult.error || 'unknown validation error'
+        );
       }
       return false;
     }

30-36: Add type safety for decoded token

Consider adding type interface for decoded token and extracting the timestamp conversion to a constant for clarity.

+    interface DecodedToken {
+      exp?: number;
+      iss?: string;
+    }
+    const currentTimestamp = Date.now() / 1000;
-    const decodedToken = jwtDecoder(token);
+    const decodedToken = jwtDecoder(token) as DecodedToken;
     if (decodedToken.exp && decodedToken.exp < currentTimestamp) {
src/routerClients/AppRouterClient.js (1)

Line range hint 1-93: Consider enhancing token refresh capabilities

Given that this PR aims to implement automatic token refresh functionality (per issue #237), consider enhancing this class to support token refresh operations. This could include:

  1. Adding configuration options for token refresh (e.g., refreshThreshold)
  2. Implementing methods to handle token refresh logic
  3. Adding event handlers for token expiry

This would provide a more complete solution for the token refresh requirements.

Would you like me to provide a detailed implementation proposal for these enhancements?

src/session/sessionManager.js (1)

Line range hint 1-400: Consider architectural improvements for token refresh.

While the session management implementation is solid, here are some architectural suggestions to enhance the token refresh mechanism:

  1. Consider adding a method to the session manager interface specifically for token refresh operations. This would centralize the refresh logic and make it easier to maintain.

  2. The current implementation splits cookies when they exceed MAX_LENGTH. For refresh tokens, consider implementing compression to reduce the cookie size and minimize the number of cookie chunks.

Here's a suggested interface enhancement:

interface SessionManager {
  // ... existing methods ...
  
  /**
   * Refreshes the access token using the stored refresh token
   * @returns {Promise<boolean>} True if refresh was successful
   */
  refreshAccessToken(): Promise<boolean>;
  
  /**
   * Validates if the current access token needs refresh
   * @returns {Promise<boolean>} True if token needs refresh
   */
  needsTokenRefresh(): Promise<boolean>;
}

This would allow for:

  1. Centralized token refresh logic
  2. Proactive token refresh before expiration
  3. Better error handling and retry mechanisms
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 086d2de and 69fa795.

📒 Files selected for processing (15)
  • src/authMiddleware/authMiddleware.ts (2 hunks)
  • src/handlers/setup.ts (2 hunks)
  • src/routerClients/AppRouterClient.js (1 hunks)
  • src/session/getAccessToken.js (2 hunks)
  • src/session/getIdToken.js (1 hunks)
  • src/session/getOrganization.ts (2 hunks)
  • src/session/getUser.ts (2 hunks)
  • src/session/isAuthenticated.js (1 hunks)
  • src/session/sessionManager.js (1 hunks)
  • src/utils/generateOrganizationObject.ts (1 hunks)
  • src/utils/getAccessToken.ts (1 hunks)
  • src/utils/getIdToken.ts (1 hunks)
  • src/utils/refreshTokens.ts (1 hunks)
  • src/utils/validateToken.ts (1 hunks)
  • src/utils/version.js (1 hunks)
✅ Files skipped from review due to trivial changes (6)
  • src/authMiddleware/authMiddleware.ts
  • src/session/getAccessToken.js
  • src/session/getIdToken.js
  • src/session/isAuthenticated.js
  • src/utils/generateOrganizationObject.ts
  • src/utils/version.js
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/handlers/setup.ts
  • src/session/getOrganization.ts
  • src/session/getUser.ts
  • src/utils/getAccessToken.ts
  • src/utils/getIdToken.ts
  • src/utils/refreshTokens.ts
🔇 Additional comments (7)
src/utils/validateToken.ts (2)

1-9: LGTM! Well-structured imports and type definitions.

The function signature is properly typed and the necessary dependencies are correctly imported.


1-52: Verify integration with token refresh mechanism

While the token validation logic is solid, we should verify how this integrates with the token refresh mechanism mentioned in the PR objectives.

✅ Verification successful

Token validation is properly integrated with refresh mechanism

The verification shows that the token validation is correctly integrated with the refresh token flow:

  • In getAccessToken.ts and getIdToken.ts, invalid tokens trigger the refresh flow via kindeClient.refreshTokens
  • The refreshTokens.ts utility validates the newly obtained tokens using the same validation logic
  • The setup.ts handler implements proper validation and refresh sequence for both access and ID tokens
  • The middleware correctly uses token validation before allowing access
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for references to validateToken in the refresh token implementation
rg -l "validateToken" | grep -v "validateToken.ts" | xargs rg -A 10 "validateToken"

# Look for refresh token related functions
ast-grep --pattern 'function $FUNC_NAME($$$) {
  $$$
  refreshToken
  $$$
}'

Length of output: 7738

src/routerClients/AppRouterClient.js (3)

39-39: LGTM!

Cosmetic change that improves readability.


45-45: LGTM!

Minor formatting improvement.


Line range hint 15-38: Verify token-related configuration

The constructor handles various authentication configurations, but there might be missing properties needed for token refresh functionality.

✅ Verification successful

Let me gather more information about the token refresh functionality by checking the implementation details.


Let me check one final aspect to verify if all necessary token-related configurations are properly handled in the client configuration.


Token refresh functionality is properly configured

Based on the verification results, the token refresh functionality is well-implemented and properly configured:

  • Token refresh is handled through the refreshTokens utility in src/utils/refreshTokens.ts
  • The client configuration includes all necessary properties for authentication and token management
  • Token refresh is integrated with session management and error handling
  • The createKindeServerClient is properly initialized with the required configuration
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any token refresh related configurations in other files
rg -A 5 "token.*refresh|refresh.*token" --type js --type ts

Length of output: 1842


Script:

#!/bin/bash
# Check the implementation of refreshTokens method and token-related configurations
ast-grep --pattern 'refreshTokens($_) {
  $$$
}'

# Check for token-related configuration properties
rg -A 2 "tokenRefresh|refreshToken" --type js --type ts

Length of output: 2031


Script:

#!/bin/bash
# Check the client configuration structure and token-related settings
ast-grep --pattern 'const config = {
  $$$
}'

# Also check for any token-related configuration in the createKindeServerClient
ast-grep --pattern 'createKindeServerClient($$$)'

Length of output: 1030

src/session/sessionManager.js (2)

33-33: LGTM! Minor formatting change.

The formatting change in the splitString function maintains the same logic while improving code consistency.


Line range hint 8-15: Verify cookie security settings for token storage.

The current cookie security settings look good with httpOnly, secure (in production), and sameSite: 'lax'. However, since this file handles sensitive token storage, let's verify there are no security advisories for the cookie package being used.

✅ Verification successful

Let me check the package version being used to determine if we're affected by this vulnerability.


Cookie security settings are verified and safe

The cookie security settings in GLOBAL_COOKIE_OPTIONS are well-configured, and the project uses cookie v1.0.1 which is not affected by the known vulnerability (CVE affects versions < 0.7.0). The implementation includes all recommended security headers:

  • httpOnly: true prevents XSS attacks
  • secure: true in production ensures HTTPS-only
  • sameSite: 'lax' provides CSRF protection
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for security advisories in the cookie package
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NPM, package: "cookie") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 574


Script:

#!/bin/bash
# Check package.json for cookie dependency version
rg '"cookie":\s*"[^"]*"' -g 'package.json'

Length of output: 79

src/utils/validateToken.ts Outdated Show resolved Hide resolved
@DanielRivers DanielRivers merged commit 9c99f2f into main Nov 26, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature request: Refresh Active Sessions Automatically
1 participant