4

I plan to have a frontend web app written with Next.js using the AuthJS library to provide user authentication using Oauth. This frontend application depends on a backend API. I want to make sure my user signin/signup flow makes sense.

Here is a diagram of the basic flow

Basic Auth Flow

Flow Steps:

  1. User authenticates via the frontend application using AuthJS. This generates a JWT.

  2. The JWT is then sent to the server then decoded and validated.

  3. The decoded and validated JWT is used to get a primary key for the user. This primary key will be a combination of the Oauth provider and the Oauth account ID.

  4. Any request that has a JWT will be allowed access to any protected resources that the identified account should have access to.

Given the above, are there any glaring holes that need to be filled? Is there a step I am missing or misunderstanding?

Thank you

    1 Answer 1

    4

    Welcome to SE.SE ! The flow for integrating OAuth-based authentication using JWT in a Next.js frontend with a Ruby on Rails backend API looks OK to me, but what follows is a few suggestions form improvements to help ensure robustness and security of the process.

    1. Client-Side Token Storage: Storing JWTs in local or session storage exposes the application to XSS (Cross Site Scripting (XSS) attacks. Instead, store tokens in HTTP-only cookies with the SameSite=strict attribute. This should ensure that the JWT is inaccessible to JavaScript, mitigating XSS risks.

    2. Token Expiration and Refresh Flow: [This section is largely based on the accepted answer here]For web applications, the recommended approach is to set the JWT expiration to one week and refresh the token:

    • Every time the user opens the app and
    • Once every hour while the app is active.

    If the user doesn’t interact with the app for more than a week, they should log in again, which I think is generally acceptable from a user experience perspective (though I am definitely not an expert on UX). To refresh the token:

    • Create an API endpoint that receives a valid (ie, non-expired) JWT and issues a new one with an updated expiration field.
    • Always ensure the app communicates over HTTPS to prevent token interception during transmission.

    This approach balances security (by limiting token lifespan) and convenience (by automatically refreshing tokens). Using short-lived JWTs and periodic refreshes also limits the risk of compromised tokens being exploited over long periods.

    3. CSRF Protection:

    When storing JWTs in cookies, implement cross-site request forgery (CSRF) protection. You can use SameSite cookies or CSRF tokens to mitigate these attacks. Some frameworks like Next.js have built-in CSRF protection mechanisms.

    4. Authorisation Scoping and Token Invalidation: While using JWTs for access control, ensure that roles and permissions are included as claims. As role changes on the server could leave old tokens with outdated permissions, consider using short-lived tokens or a token invalidation mechanism. This can be achieved through a token revocation list or refreshing tokens more frequently.

    5. JWT Signature Validation: It is critical to validate the JWT's signature to ensure it has not been tampered with. Use HMAC or RSA for signing, and ensure that algorithm switching attacks (e.g., alg=none) are not possible. This ensures token integrity.

    6. Handling OAuth Provider Edge Cases: Integrate a system for managing OAuth provider failures or discrepancies, such as token revocation or account deactivation. Implement a mechanism to periodically verify the user's OAuth status and cache valid tokens temporarily to handle OAuth provider downtime gracefully.

    7. Session Management and Logout: JWTs are stateless, so logging users out requires a more deliberate approach. You can maintain a server-side blacklist or token invalidation mechanism for invalidating tokens. Alternatively, rotating refresh tokens allows you to manage session expiry more securely.

    8. Error Handling: Ensure proper error handling when JWT validation fails. Responses should be secure and non-informative to prevent leaking sensitive details. Typically, return a 401 Unauthorised or 403 Forbidden status, depending on the context of the request.

    9. Scalability Considerations: JWTs are stateless, which can help in scalability across distributed systems. However, try to avoid JWT size bloat by limiting the claims included. For high-load systems, consider splitting large claims into nested tokens if needed.

    Summing up, your suggested workflow is generally sound, but ensuring secure token storage, robust refresh mechanisms, and proper handling of edge cases will strengthen the architecture. Combining short-lived tokens with periodic refreshes for web applications should improve both security and user experience.

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.