Skip to content

Amplify does not call Cognito to refresh session after idToken/accessToken expiry #14406

@abhijeet4som1

Description

@abhijeet4som1

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

None

Environment information

# Put output below this line
System:
    OS: macOS 15.5
    CPU: (12) arm64 Apple M3 Pro
    Memory: 2.51 GB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.20.2 - ~/.local/share/mise/installs/node/18.20.2/bin/node
    npm: 10.5.0 - ~/.local/share/mise/installs/node/18.20.2/bin/npm
  Browsers:
    Chrome: 136.0.7103.114
    Safari: 18.5
  npmPackages:
    @amzn/awsui-collection-hooks: ^1.0.0 => 1.0.0 
    @amzn/awsui-components-react: ^3.0.0 => 3.0.0 
    @amzn/awsui-global-styles: ^1.0.0 => 1.0.0 
    @amzn/omnia-configuration: ^1.1.0 => 1.1.0 
    @amzn/omnia-configuration-manager-service-typescript-client: 1.0.0 => 1.0.0 
    @amzn/omnia-shared-frontend-libraries: ^4.0.0 => 4.0.0 
    @emotion/babel-plugin: ^11.13.5 => 11.13.5 
    @lingui/cli: ^4.13.0 => 4.14.1 
    @lingui/macro: ^4.14.1 => 4.14.1 
    @lingui/react: ^4.14.1 => 4.14.1 
    @lingui/vite-plugin: ^4.14.1 => 4.14.1 
    @tanstack/react-query: ^4.36.1 => 4.36.1 
    @tanstack/react-query-devtools: ^4.36.1 => 4.36.1 
    @testing-library/jest-dom: ^6.6.3 => 6.6.3 
    @testing-library/react: ^16.2.0 => 16.2.0 
    @testing-library/user-event: ^14.6.1 => 14.6.1 
    @types/jest: ^29.5.14 => 29.5.14 
    @types/lodash.camelcase: ^4.3.9 => 4.3.9 
    @types/lodash.chunk: ^4.2.9 => 4.2.9 
    @types/lodash.startcase: ^4.4.9 => 4.4.9 
    @types/react: ^18.3.16 => 18.3.17 
    @types/react-dom: ^18.3.5 => 18.3.5 
    @vitejs/plugin-basic-ssl: ^1.2.0 => 1.2.0 
    @vitejs/plugin-react: ^4.3.4 => 4.3.4 
    @vitest/coverage-istanbul: ^1.6.0 => 1.6.0 
    @zodios/core: ^10.9.6 => 10.9.6 
    @zodios/react: ^10.4.5 => 10.4.5 
    autoprefixer: ^10.4.20 => 10.4.20 
    aws-amplify: ^6.14.4 => 6.14.4 
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/adapter-core/internals:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/internals:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    babel-plugin-macros: ^3.1.0 => 3.1.0 
    cssnano: ^7.0.6 => 7.0.6 
    jest: ^29.7.0 => 29.7.0 
    jest-environment-jsdom: ^29.7.0 => 29.7.0 
    jotai: ^2.10.3 => 2.10.4 
    lodash.camelcase: ^4.3.0 => 4.3.0 
    lodash.chunk: ^4.2.0 => 4.2.0 
    lodash.startcase: ^4.4.0 => 4.4.0 
    moment: ^2.30.1 => 2.30.1 
    prettier: 3.5.3 => 3.5.3 
    react: ^18.3.1 => 18.3.1 
    react-dom: ^18.3.1 => 18.3.1 
    react-router-dom: ^6.28.0 => 6.28.0 
    single-spa-react: ^6.0.2 => 6.0.2 
    ts-jest: ^29.2.5 => 29.2.5 
    typescript: ^5.7.2 => 5.7.2 
    uuid: ^11.1.0 => 11.1.0 (9.0.1)
    vite: ^5.4.11 => 5.4.11 
    vite-plugin-single-spa: ^0.6.1 => 0.6.1 
    vitest: ^1.6.0 => 1.6.0 
    wait-for-expect: ^3.0.2 => 3.0.2 
    xlsx: ^0.18.5 => 0.18.5 
  npmGlobalPackages:
    corepack: 0.25.2
    npm: 10.5.0

Describe the bug

When using fetchAuthSession({ forceRefresh: true }) with cookie-based storage (e.g., via CookieStorage or a custom implementation), Amplify correctly calls the Cognito InitiateAuth endpoint (https://cognito-idp..amazonaws.com/) with the REFRESH_TOKEN_AUTH flow only when all three tokens (idToken, accessToken, and refreshToken) are still valid.

However, as soon as both the idToken and accessToken expire, even if the refreshToken is still present and valid, Amplify does not initiate any call to Cognito to refresh the session. Instead, fetchAuthSession() silently returns undefined and does not throw an error or attempt recovery via refreshToken.

This behavior breaks expected OAuth semantics, where a valid refreshToken should be sufficient to obtain new access and ID tokens even after they expire.

Expected behavior

idToken and accessToken has expired and removed from cookies, but refreshToken is still present and valid. so it should initiate call to Cognito to refresh the session and generate new tokens.

Reproduction steps

  1. Install Amplify version 6.14.4 ("aws-amplify": "^6.14.4")
  2. Configure Amplify:
    Auth: {
      Cognito: {
        userPoolId: config.userPoolId,
        userPoolClientId: config.userPoolClientId,
        loginWith: {
          oauth: {
            domain: config.domain,
            scopes: ['openid', 'email', 'profile', 'aws.cognito.signin.user.admin'],
            redirectSignIn: config.redirectSignIn,
            redirectSignOut: config.redirectSignOut,
            responseType: 'code',
            providers: [{ custom: 'AmazonFederate' }]
          }
        }
      }
    }
    
  3. Use CookieStorage or Custom Storage as mentioned in https://docs.amplify.aws/gen1/react/build-a-backend/auth/manage-user-session/#understand-token-management-options
import { CookieStorage } from 'aws-amplify/utils';
import { cognitoUserPoolsTokenProvider } from 'aws-amplify/auth/cognito';

Amplify.configure(amplifyConfig);
cognitoUserPoolsTokenProvider.setKeyValueStorage(tokenStorage);
  1. For debugging set Cognito token expiration as:
    idToken: 5 minutes
    accessToken: 5 minutes
    refreshToken: 15 minutes

  2. Call fetchAuthSession({ forceRefresh: true })

    • Called within 5 minutes that is before expiry of idToken and accessToken, it generates new tokens and are stored correctly with new extended expiration.
    • Let the idToken and accessToken expire (but refreshToken is still present and valid), now calling fetchAuthSession({ forceRefresh: true }) returns undefined, no error thrown.

Code Snippet

// Put your code below this line.
const session = await fetchAuthSession({ forceRefresh: true });
const accessToken = session.tokens?.idToken?.toString();
console.log('***** getAccessToken:', accessToken);

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

When idToken and accessToken are valid:

Image

Once idToken and accessToken expires:

Image

As per my code flow before making API call, I call await fetchAuthSession({ forceRefresh: true });, but it silently returns undefined.

Metadata

Metadata

Assignees

Labels

AuthRelated to Auth components/categorybugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions