Skip to content

Conversation

@iceljc
Copy link
Collaborator

@iceljc iceljc commented Nov 13, 2025

PR Type

Enhancement


Description

  • Add max token renewal limit to prevent infinite retry loops

  • Track token renewal count in user store and increment on each renewal

  • Clear retry queue and redirect to login when max renewals exceeded

  • Skip loader for token renewal endpoint requests

  • Improve token validation logic in request/response interceptors


Diagram Walkthrough

flowchart LR
  A["Token Expired"] --> B["Increment renew_token_count"]
  B --> C{"Count >= maxRenewTokenCount?"}
  C -->|Yes| D["Clear Queue & Redirect"]
  C -->|No| E["Refresh Token"]
  E --> F["Retry Requests"]
Loading

File Walkthrough

Relevant files
Enhancement
http.js
Add token renewal limit and queue management                         

src/lib/helpers/http.js

  • Added maxRenewTokenCount property set to 30 to limit token renewal
    attempts
  • Increment renew_token_count when token refresh is initiated
  • Check renewal count limit in response interceptor to prevent infinite
    retries
  • Clear retry queue and redirect to login when limit is exceeded
  • Added token validation in request interceptor to clear queue if no
    token exists
  • Added /renew-token endpoint to skip loader regex patterns
+15/-7   
userTypes.js
Add renew_token_count property to User type                           

src/lib/helpers/types/userTypes.js

  • Added renew_token_count optional property to User type definition
  • Tracks the number of token renewal attempts for the user
+1/-0     
auth-service.js
Reset token renewal count on successful auth                         

src/lib/services/auth-service.js

  • Initialize renew_token_count to 0 when user successfully obtains a new
    token
  • Ensures counter resets on successful authentication
+1/-0     
Formatting
store.js
Improve code formatting in getUserStore                                   

src/lib/helpers/store.js

  • Improved code formatting with consistent brace placement in
    getUserStore() function
  • Enhanced readability of conditional logic for session storage
    retrieval
+3/-2     

@iceljc iceljc merged commit 5f1e85c into SciSharp:main Nov 13, 2025
1 of 2 checks passed
@qodo-merge-pro
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Console sensitive log: The code logs token renewal count to console which may expose internal auth state to
end-users or client logs.

Referred Code
console.log("renew token count.", user.renew_token_count);
if (!user?.token || user.renew_token_count >= retryQueue.maxRenewTokenCount) {

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Unstructured logging: Use of console.log with authentication state ("renew token count") is
unstructured and may leak sensitive operational data.

Referred Code
console.log("renew token count.", user.renew_token_count);
if (!user?.token || user.renew_token_count >= retryQueue.maxRenewTokenCount) {

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Missing audit logs: New critical auth-related actions (token renewal attempts and login redirects) are added
without structured audit logging of user ID, timestamp, action, and outcome.

Referred Code
this.queue.push(item);

if (!this.isRefreshingToken) {
    const user = getUserStore();
    if (!isTokenExired(user.expires)) {
        this.dequeue(user.token);
    } else {
        this.isRefreshingToken = true;
        user.renew_token_count = (user.renew_token_count || 0) + 1;
        // @ts-ignore
        userStore.set(user);
        this.refreshAccessToken(user?.token || '')
            .then((newToken) => {
                this.isRefreshingToken = false;
                const promise = this.dequeue(newToken);

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Limited error context: Interceptors redirect on missing/expired tokens without logging actionable error context
or handling edge cases around failed token refresh outcomes.

Referred Code
(error) => {
    loaderStore.set(false);
    const originalRequest = error?.config || {};
    const user = getUserStore();
    console.log("renew token count.", user.renew_token_count);
    if (!user?.token || user.renew_token_count >= retryQueue.maxRenewTokenCount) {
        retryQueue.queue = [];
        redirectToLogin();
        return Promise.reject(error);

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Token handling: Client-side handling of tokens (storing and updating renew_token_count, attaching
Authorization headers) lacks visible validation/sanitization and safeguards beyond max
retry count.

Referred Code
axios.interceptors.request.use(
    (config) => {
        // Add your authentication logic here
        const user = getUserStore();
        if (!skipLoader(config)) {
            loaderStore.set(true);
        }
        // Attach an authentication token to the request headers
        if (user.token) {
            config.headers.Authorization = `Bearer ${user.token}`;
        } else {
            retryQueue.queue = [];
            redirectToLogin();
        }
        return config;

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-merge-pro
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Sensitive information exposure

Description: Logging user.renew_token_count on every error response may leak sensitive session-related
information to client-side logs, which could aid an attacker in understanding auth state
or brute-force token refresh behavior.
http.js [133-136]

Referred Code
console.log("renew token count.", user.renew_token_count);
if (!user?.token || user.renew_token_count >= retryQueue.maxRenewTokenCount) {
    retryQueue.queue = [];
    redirectToLogin();
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Console disclosure: The added console.log("renew token count.", user.renew_token_count); outputs
internal state which may leak sensitive session info in user-facing consoles.

Referred Code
console.log("renew token count.", user.renew_token_count);
if (!user?.token || user.renew_token_count >= retryQueue.maxRenewTokenCount) {

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Sensitive console log: Logging renew_token_count via console.log introduces unstructured logs and risks exposing
session-related details in client logs.

Referred Code
console.log("renew token count.", user.renew_token_count);
if (!user?.token || user.renew_token_count >= retryQueue.maxRenewTokenCount) {

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Missing audit logs: The new logic for token renewal limits, login redirection, and request queuing lacks
explicit audit logging of critical auth events (e.g., token refresh attempts, reaching max
renew limit, redirects).

Referred Code
axios.interceptors.request.use(
    (config) => {
        // Add your authentication logic here
        const user = getUserStore();
        if (!skipLoader(config)) {
            loaderStore.set(true);
        }
        // Attach an authentication token to the request headers
        if (user.token) {
            config.headers.Authorization = `Bearer ${user.token}`;
        } else {
            retryQueue.queue = [];
            redirectToLogin();
        }
        return config;
    },
    (error) => {
        loaderStore.set(false);
        return Promise.reject(error);
    }
);


 ... (clipped 15 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Edge cases unhandled: When user.renew_token_count or user are missing or corrupted, the code assumes their
presence and may not handle edge cases beyond redirecting, and errors are rejected without
contextual logging for debugging.

Referred Code
this.queue.push(item);

if (!this.isRefreshingToken) {
    const user = getUserStore();
    if (!isTokenExired(user.expires)) {
        this.dequeue(user.token);
    } else {
        this.isRefreshingToken = true;
        user.renew_token_count = (user.renew_token_count || 0) + 1;
        // @ts-ignore
        userStore.set(user);
        this.refreshAccessToken(user?.token || '')
            .then((newToken) => {
                this.isRefreshingToken = false;
                const promise = this.dequeue(newToken);

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Token handling checks: While a max renew limit is added, there is no explicit validation/sanitization of values
read from storage (e.g., user object fields) before use in auth headers and control flow.

Referred Code
axios.interceptors.request.use(
    (config) => {
        // Add your authentication logic here
        const user = getUserStore();
        if (!skipLoader(config)) {
            loaderStore.set(true);
        }
        // Attach an authentication token to the request headers
        if (user.token) {
            config.headers.Authorization = `Bearer ${user.token}`;
        } else {
            retryQueue.queue = [];
            redirectToLogin();
        }
        return config;

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-merge-pro
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Decouple renewal counter from user model

The renew_token_count should be managed separately from the UserModel because it
is a transient state for the HTTP client's retry logic, not a core user
property. Consider managing it within the retryQueue object or its own
sessionStorage item to avoid coupling the data model with implementation
details.

Examples:

src/lib/helpers/types/userTypes.js [21]
 * @property {number?} [renew_token_count]
src/lib/helpers/http.js [41-43]
                user.renew_token_count = (user.renew_token_count || 0) + 1;
                // @ts-ignore
                userStore.set(user);

Solution Walkthrough:

Before:

// src/lib/helpers/types/userTypes.js
/**
 * @typedef {Object} UserModel
 * ...
 * @property {string} [token]
 * @property {boolean} [open_detail]
 * @property {number?} [renew_token_count]
 */

// src/lib/helpers/http.js
retryQueue.enqueue(item) {
    // ...
    if (isTokenExired(user.expires)) {
        this.isRefreshingToken = true;
        user.renew_token_count = (user.renew_token_count || 0) + 1;
        userStore.set(user);
        this.refreshAccessToken(...)
    }
}

After:

// src/lib/helpers/types/userTypes.js
/**
 * @typedef {Object} UserModel
 * ...
 * @property {string} [token]
 * @property {boolean} [open_detail]
 * // renew_token_count is removed
 */

// src/lib/helpers/http.js
let renewTokenCount = parseInt(sessionStorage.getItem('renewTokenCount') || '0');

retryQueue.enqueue(item) {
    // ...
    if (isTokenExired(user.expires)) {
        this.isRefreshingToken = true;
        renewTokenCount++;
        sessionStorage.setItem('renewTokenCount', renewTokenCount);
        this.refreshAccessToken(...)
    }
}
Suggestion importance[1-10]: 8

__

Why: This is a strong architectural suggestion that correctly identifies the coupling of the UserModel with transient HTTP client state (renew_token_count), proposing a cleaner design that improves separation of concerns and maintainability.

Medium
Possible issue
Cancel request if user is unauthenticated

In the request interceptor, cancel the outgoing request by returning a rejected
promise if the user has no token to prevent an unnecessary network call.

src/lib/helpers/http.js [109-114]

 if (user.token) {
     config.headers.Authorization = `Bearer ${user.token}`;
 } else {
     retryQueue.queue = [];
     redirectToLogin();
+    return Promise.reject(new Error('User not authenticated.'));
 }
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a bug where an unnecessary network request is sent for an unauthenticated user, and proposes a valid fix to reject the promise, preventing the request.

Medium
General
Remove debugging console log statement

Remove the debugging console.log statement from the response interceptor to
avoid cluttering the console in production.

src/lib/helpers/http.js [132-138]

 const user = getUserStore();
-console.log("renew token count.", user.renew_token_count);
 if (!user?.token || user.renew_token_count >= retryQueue.maxRenewTokenCount) {
     retryQueue.queue = [];
     redirectToLogin();
     return Promise.reject(error);
 }
  • Apply / Chat
Suggestion importance[1-10]: 3

__

Why: The suggestion correctly identifies a debugging console.log statement that should be removed for code cleanliness, which is a minor but valid improvement.

Low
  • More

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant