npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cognito-session-manager

v0.1.1

Published

Lightweight, framework-agnostic session lifecycle management for Amazon Cognito User Pools

Readme

Amazon Cognito Session Manager

Lightweight, framework-agnostic session lifecycle management for Amazon Cognito User Pools. Provides automatic token refresh, multi-tab synchronization, and pluggable storage without requiring AWS Amplify.

Overview

When you use Amazon Cognito User Pools with the AWS SDK directly, you receive tokens but must manage their lifecycle yourself. This includes tracking expiration, refreshing tokens before they expire, handling concurrent refresh requests, and coordinating sessions across browser tabs.

cognito-session-manager solves these problems in a single, focused library:

  • 2.8 KB gzipped core + 0.5 KB fetch interceptor
  • Zero runtime dependencies (peer dependency on @aws-sdk/client-cognito-identity-provider)
  • Works everywhere - Node.js 18+, modern browsers, React Native, Deno, Cloudflare Workers
  • No framework lock-in - use with React, Vue, Angular, Svelte, or vanilla JavaScript

Installation

npm install cognito-session-manager @aws-sdk/client-cognito-identity-provider

Getting Started

Basic Usage

import { SessionManager } from 'cognito-session-manager';

const session = new SessionManager({
  region: 'us-east-1',
  clientId: 'your-app-client-id',
});

// After authenticating your user through any method (hosted UI, SRP, custom flow),
// store the resulting tokens:
await session.setTokens({
  accessToken: authResult.AccessToken,
  idToken: authResult.IdToken,
  refreshToken: authResult.RefreshToken,
  expiresAt: Math.floor(Date.now() / 1000) + authResult.ExpiresIn,
  clockDrift: 0,
});

// Retrieve a valid access token. The library refreshes automatically
// if the token is about to expire.
const token = await session.getAccessToken();

Restoring Sessions on App Startup

import { SessionManager, LocalStorageAdapter } from 'cognito-session-manager';

const session = new SessionManager({
  region: 'us-east-1',
  clientId: 'your-app-client-id',
  storage: new LocalStorageAdapter(),
});

// Loads tokens from storage. If expired, attempts a refresh automatically.
const tokens = await session.initialize();
if (!tokens) {
  // No valid session found, redirect to login
  redirectToLogin();
}

Listening to Session Events

const unsubscribe = session.on((event) => {
  switch (event.type) {
    case 'signedIn':
      console.log('User signed in');
      break;
    case 'tokenRefreshed':
      console.log('Tokens refreshed automatically');
      break;
    case 'signedOut':
      console.log('User signed out');
      break;
    case 'sessionExpired':
      console.log('Session expired:', event.reason);
      redirectToLogin();
      break;
  }
});

// Later, to stop listening:
unsubscribe();

Fetch Interceptor

The library includes a separate entry point for automatically attaching access tokens to HTTP requests:

import { SessionManager } from 'cognito-session-manager';
import { createAuthFetch } from 'cognito-session-manager/fetch';

const session = new SessionManager({ region: 'us-east-1', clientId: '...' });
const authFetch = createAuthFetch(session);

// The token is attached as "Authorization: Bearer <token>" automatically.
// On a 401 response, the library refreshes the token and retries once.
const response = await authFetch('/api/protected-resource');

Fetch Interceptor Options

const authFetch = createAuthFetch(session, {
  // Only attach the token to requests matching this filter
  shouldAttachToken: (url) => url.startsWith('/api'),

  // Use a custom header name (default: 'Authorization')
  headerName: 'X-Auth-Token',

  // Use a custom header value format (default: 'Bearer {token}')
  headerValue: (token) => token,

  // Disable automatic retry on 401 (default: true)
  retryOnUnauthorized: false,
});

Storage Adapters

By default, tokens are stored in memory and lost on page reload. The library ships with three storage adapters:

MemoryStorage (default)

import { SessionManager, MemoryStorage } from 'cognito-session-manager';

const session = new SessionManager({
  region: 'us-east-1',
  clientId: '...',
  storage: new MemoryStorage(),
});

LocalStorageAdapter

Persists tokens in the browser's localStorage:

import { SessionManager, LocalStorageAdapter } from 'cognito-session-manager';

const session = new SessionManager({
  region: 'us-east-1',
  clientId: '...',
  storage: new LocalStorageAdapter(),          // default prefix: 'cognito-session:'
  // storage: new LocalStorageAdapter('myapp:') // custom prefix
});

CookieStorageAdapter

Persists tokens in cookies. Useful for SSR or cross-subdomain scenarios:

import { SessionManager, CookieStorageAdapter } from 'cognito-session-manager';

const session = new SessionManager({
  region: 'us-east-1',
  clientId: '...',
  storage: new CookieStorageAdapter({
    domain: '.example.com',
    secure: true,
    sameSite: 'Lax',
    maxAge: 30 * 24 * 60 * 60, // 30 days
  }),
});

Custom Storage Adapter

Implement the StorageAdapter interface to use any persistence layer:

import type { StorageAdapter } from 'cognito-session-manager';

const redisAdapter: StorageAdapter = {
  async getItem(key: string): Promise<string | null> {
    return redis.get(key);
  },
  async setItem(key: string, value: string): Promise<void> {
    await redis.set(key, value);
  },
  async removeItem(key: string): Promise<void> {
    await redis.del(key);
  },
};

Multi-Tab Synchronization

In browser environments, the library automatically synchronizes session state across tabs using the BroadcastChannel API:

  • When one tab refreshes tokens, all other tabs receive the updated tokens.
  • When one tab signs out, all other tabs are notified immediately.
  • Only one tab performs the actual refresh network call. Other tabs wait for the broadcast.

This behavior is enabled by default in environments where BroadcastChannel is available. You can disable it:

const session = new SessionManager({
  region: 'us-east-1',
  clientId: '...',
  enableTabSync: false,
});

API Reference

SessionManager

Constructor

new SessionManager(config: SessionManagerConfig)

Configuration

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | region | string | Yes | - | AWS Region of your Cognito User Pool | | clientId | string | Yes | - | The App Client ID from your User Pool | | userPoolId | string | No | - | The User Pool ID (reserved for future use) | | storage | StorageAdapter | No | MemoryStorage | Storage adapter for token persistence | | refreshBufferSeconds | number | No | 60 | How many seconds before expiry to trigger a proactive refresh | | enableTabSync | boolean | No | auto | Whether to synchronize sessions across browser tabs | | cognitoClient | CognitoIdentityProviderClient | No | auto | Provide your own configured SDK client |

Methods

| Method | Returns | Description | |--------|---------|-------------| | initialize() | Promise<AuthTokens \| null> | Restores a session from storage. Call once on app startup. Attempts refresh if tokens are expired. | | setTokens(tokens) | Promise<void> | Stores tokens after a successful authentication. Starts the refresh scheduler. | | getAccessToken() | Promise<string> | Returns the current access token. Triggers a refresh if the token is about to expire. | | getIdToken() | Promise<string> | Returns the current ID token. | | getTokens() | Promise<AuthTokens \| null> | Returns all current tokens, or null if no session exists. | | forceRefresh() | Promise<AuthTokens> | Forces an immediate token refresh regardless of expiry status. | | signOut() | Promise<void> | Clears tokens, cancels the refresh scheduler, and notifies other tabs. | | on(handler) | () => void | Subscribes to session events. Returns an unsubscribe function. | | destroy() | void | Cleans up timers, BroadcastChannel listeners, and event subscriptions. |

Types

interface AuthTokens {
  accessToken: string;
  idToken: string;
  refreshToken: string;
  expiresAt: number;   // Unix timestamp in seconds
  clockDrift: number;  // Detected clock drift in seconds
}

type SessionEvent =
  | { type: 'signedIn'; tokens: AuthTokens }
  | { type: 'tokenRefreshed'; tokens: AuthTokens }
  | { type: 'signedOut' }
  | { type: 'sessionExpired'; reason: 'refreshFailed' | 'refreshTokenExpired' }
  | { type: 'error'; error: Error };

How It Works

Proactive Token Refresh

The library schedules a refresh refreshBufferSeconds before the access token expires (default: 60 seconds). This means requests never encounter a 401 due to token expiry under normal network conditions.

Concurrency Deduplication

If multiple parts of your application call getAccessToken() or forceRefresh() simultaneously, only one network request is made to Cognito. All concurrent callers receive the same result from the single request.

Clock Drift Detection

On each token refresh, the library reads the iat (issued at) claim from the JWT and compares it to the local system clock. The detected drift is stored and applied to all future expiry calculations, preventing premature or delayed refreshes on devices with inaccurate clocks.

Error Recovery

| Scenario | Behavior | |----------|----------| | Network error during refresh | Retries once after 5 seconds, then emits sessionExpired with reason refreshFailed | | Refresh token revoked or expired | Emits sessionExpired with reason refreshTokenExpired | | Storage adapter throws on write | Tokens remain in memory; no data loss occurs | | BroadcastChannel unavailable | Gracefully degrades; no multi-tab sync |

Scope and Limitations

This library manages sessions after authentication. It does not:

  • Provide sign-in or sign-up UI components
  • Handle the initial authentication flow (hosted UI, SRP, custom auth challenges)
  • Manage Amazon Cognito Identity Pool (federated identity) credentials
  • Replace the full AWS Amplify Auth module

Use it alongside your existing authentication flow. Authenticate with whatever method you prefer, then pass the resulting tokens to setTokens().

Interactive Demo

An interactive dashboard that demonstrates all library features against a real Cognito User Pool is available at:

cognito-session-manager-demo

The demo lets you:

  • Sign in and observe live token state (expiry countdown, clock drift, refresh count)
  • Fire concurrent refresh calls and verify deduplication (5 calls, 1 API request)
  • Test the fetch interceptor against a live endpoint
  • Open multiple tabs to observe BroadcastChannel synchronization
  • Compare the library's behavior side-by-side with the raw SDK approach

Development

git clone https://github.com/paramanandmallik/cognito-session-manager.git
cd cognito-session-manager
npm install
npm run build        # Builds ESM, CJS, and type declarations with tsup
npm run test         # Runs the full test suite (79 tests)
npm run typecheck    # Runs tsc with no output

Security

If you discover a potential security issue in this project, please do not create a public GitHub issue. Instead, contact the maintainer directly.

License

This project is licensed under the MIT License.