Skip to content

Docs: The JWT refresh token rotation example is not working correctly #13281

@Lukas2019

Description

@Lukas2019

What is the improvement or update you wish to see?

The code example for refresh token rotation in the jwt callback documentation is incorrect and causes errors.

The current example attempts to access access_token, expires_at, and refresh_token from the account object on the initial sign-in. However, these properties are not available on the account object in this context. Instead, they are passed within the user object.

This leads to the JWT never being populated with the necessary tokens on the first login, which breaks the entire refresh logic for all subsequent requests.

The code should be updated to use the user object to correctly initialize the token, like this:

// ...
  callbacks: {
    async jwt({ token, account, user }) {
      // First-time sign-in
      if (account && user) {
        return {
          ...token,
          access_token: user.access_token, // Use user.access_token
          expires_at: user.expires_at,       // Use user.expires_at
          refresh_token: user.refresh_token, // Use user.refresh_token
        }
      }

      // Return previous token if the access token has not expired yet
      if (Date.now() < token.expires_at * 1000) {
        return token
      }

      // Access token has expired, try to update it
      // ... rest of the refresh logic
    },
  },
// ...

Is there any context that might help us understand?

When implementing the refresh token rotation logic exactly as described in the documentation, the initial sign-in fails to persist the access_token and refresh_token in the JWT. This is because the account object does not contain these values on the first callback invocation. The correct object to source these from is the user object.

By changing account.access_token to user.access_token (and similarly for the other token properties), the logic works as expected. The tokens are saved on the first sign-in, and the refresh mechanism can then function correctly when the access token expires.

This seems to be a common point of confusion for developers trying to implement this feature, and updating the documentation would provide a working example out-of-the-box.

Does the docs page already exist? Please link to it.

https://authjs.dev/guides/refresh-token-rotation

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageUnseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions