A complete auth ecosystem for modern JavaScript & TypeScript applications.
Features β’ Quick Start β’ Packages β’ Architecture β’ Security β’ Contributing
Authentication is never "just a JWT". Every real-world app ends up writing the same boilerplate:
- Token refresh logic with race conditions
- 401 interceptors that queue and retry requests
- Multi-tab session synchronization
- Secure storage with SSR compatibility
- Protected route wrappers
- Role-based access control
smart-auth-sdk solves all of this in one modular, type-safe, framework-agnostic SDK.
| Feature | Description |
|---|---|
| π JWT Lifecycle | Automatic token management, expiration detection, proactive refresh |
| π Silent Refresh | Concurrent-safe token refresh with request queuing β only one refresh call, ever |
| π± Multi-Tab Sync | BroadcastChannel + storage event fallback β logout in one tab, logout everywhere |
| βοΈ React Integration | Provider, hooks (useAuth, useUser, usePermissions), route guards |
| π‘οΈ Express Middleware | JWT verification, RBAC authorization, token issuance, refresh rotation |
| π HTTP Interceptors | Axios and fetch wrappers with automatic token attachment and 401 retry |
| πΎ Storage Adapters | Memory (default), localStorage, sessionStorage, cookies, or custom |
| π Security-First | httpOnly cookies, token rotation, clock skew handling, sensitive data masking |
| π¦ Modular | Install only what you need β tree-shakeable, zero cross-package bloat |
| π§© TypeScript | Full type safety with generic user types and strict interfaces |
| Package | Description | Size |
|---|---|---|
@smart-auth/core |
Auth engine, token manager, storage adapters, multi-tab sync | |
@smart-auth/react |
React Provider, hooks, ProtectedRoute, GuestRoute |
|
@smart-auth/axios |
Axios interceptors with concurrent refresh queue | |
@smart-auth/fetch |
Enhanced fetch wrapper with auto-refresh | |
@smart-auth/express |
Express middleware β JWT verify, RBAC, token issuance | |
@smart-auth/types |
Shared TypeScript interfaces and error classes | Types only |
@smart-auth/shared |
Internal utilities β JWT decode, event emitter, logger | Internal |
# Core (required)
npm install @smart-auth/core
# React integration
npm install @smart-auth/react
# HTTP interceptors (pick one or both)
npm install @smart-auth/axios # for Axios
npm install @smart-auth/fetch # for fetch API
# Express backend
npm install @smart-auth/expressimport { AuthProvider, useAuth, ProtectedRoute } from '@smart-auth/react';
function App() {
return (
<AuthProvider
config={{
apiBaseUrl: '/api',
refresh: { endpoint: '/auth/refresh' },
autoRefresh: true,
}}
>
<Router>
<Route
path="/dashboard"
element={
<ProtectedRoute fallback={<Navigate to="/login" />}>
<Dashboard />
</ProtectedRoute>
}
/>
</Router>
</AuthProvider>
);
}
function Dashboard() {
const { user, logout, loading } = useAuth();
if (loading) return <Spinner />;
return (
<div>
<h1>Welcome, {user?.name}</h1>
<button onClick={() => logout()}>Sign Out</button>
</div>
);
}import express from 'express';
import {
createTokenIssuer,
verifyAccessToken,
authorize,
createRefreshHandler,
} from '@smart-auth/express';
const app = express();
// Create a token issuer
const issuer = createTokenIssuer({
accessTokenSecret: process.env.JWT_ACCESS_SECRET!,
refreshTokenSecret: process.env.JWT_REFRESH_SECRET!,
accessTokenExpiry: '15m',
refreshTokenExpiry: '7d',
});
// Login endpoint
app.post('/auth/login', async (req, res) => {
const user = await authenticate(req.body); // your logic
const tokens = issuer.issueTokenPair({
sub: user.id,
email: user.email,
roles: user.roles,
});
res.json({ user, ...tokens });
});
// Protect any route with one middleware
app.get(
'/api/profile',
verifyAccessToken({ secret: process.env.JWT_ACCESS_SECRET! }),
(req, res) => {
res.json({ userId: (req as any).auth.userId });
},
);
// Role-based access control
app.delete(
'/api/users/:id',
verifyAccessToken({ secret: process.env.JWT_ACCESS_SECRET! }),
authorize(['admin']),
(req, res) => {
// Only admins reach here
},
);
// Refresh token rotation
const refreshHandler = createRefreshHandler({ issuer });
app.post('/auth/refresh', refreshHandler.middleware);import axios from 'axios';
import { createAuth } from '@smart-auth/core';
import { createSmartAxios } from '@smart-auth/axios';
const auth = createAuth({
apiBaseUrl: '/api',
refresh: { endpoint: '/auth/refresh' },
});
const api = axios.create({ baseURL: '/api' });
// Attach interceptors β tokens are injected automatically
const cleanup = createSmartAxios({ auth, axios: api });
// Every request is now authenticated. 401s trigger silent refresh.
const { data } = await api.get('/protected-resource');import { createAuth } from '@smart-auth/core';
import { createSmartFetch } from '@smart-auth/fetch';
const auth = createAuth({ apiBaseUrl: '/api' });
const smartFetch = createSmartFetch({ auth, baseUrl: '/api' });
// Automatic token injection + 401 refresh retry
const response = await smartFetch('/protected-resource');
const data = await response.json();ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your Application β
ββββββββββββββ¬βββββββββββββ¬βββββββββββββ¬ββββββββββββββββββββ€
β React β Axios β Fetch β Express β
β Hooks & β Interceptorβ Wrapper β Middleware β
β Guards β + Queue β β + RBAC β
ββββββββββββββ΄βββββββββββββ΄βββββββββββββΌββββββββββββββββββββ€
β @smart-auth/core β β
β ββββββββββββββββββββββββββββββββββ β β
β β Auth Engine β β β
β β ββββββββββββββ¬ββββββββββββββ β β @smart-auth/ β
β β β Token β Refresh β β β express β
β β β Manager β Manager β β β β
β β ββββββββββββββΌββββββββββββββ€ β β Token Issuer β
β β β Session β Multi-Tab β β β JWT Verify β
β β β Manager β Sync β β β RBAC Authorize β
β β ββββββββββββββ΄ββββββββββββββ β β Cookie Helpers β
β ββββββββββββββββββββββββββββββββββ β β
ββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ€
β @smart-auth/shared β β
β JWT Decode Β· Events Β· Logger β β
ββββββββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββ€
β @smart-auth/types β
β Interfaces Β· Errors Β· Config Types β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Note:
@smart-auth/expressdoes not depend on@smart-auth/core. The backend package shares only types and utilities β no browser code leaks into your server bundle.
| Practice | Implementation |
|---|---|
| Default to memory storage | Access tokens are stored in-memory by default (XSS-resistant) |
| httpOnly cookies | Refresh tokens should use httpOnly cookies set by the server |
| Token rotation | Old refresh tokens are invalidated on each refresh |
| Clock skew tolerance | Configurable buffer prevents premature token rejection |
| Data masking | Sensitive data (tokens, secrets) is masked in all log output |
| CSRF protection | SameSite cookie attribute, configurable per environment |
| Concurrent refresh safety | Only one refresh request fires, all others queue and await |
# Run all unit tests (58 tests across 3 packages)
pnpm test
# Run the fullstack integration demo
cd examples/fullstack-demo && pnpm devContributions are welcome! This is a pnpm monorepo managed with Turborepo.
# Clone and install
git clone https://github.com/DurjoyGH/Smart_Auth_SDK.git
cd Smart_Auth_SDK
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Run the demo
cd examples/fullstack-demo && pnpm devsmart-auth-sdk/
βββ packages/
β βββ types/ # Shared interfaces and error classes
β βββ shared/ # Internal utilities (JWT, events, logger)
β βββ core/ # Auth engine (browser + SSR)
β βββ react/ # React Provider, hooks, route guards
β βββ axios/ # Axios interceptors
β βββ fetch/ # Fetch wrapper
β βββ express/ # Express middleware (server-only)
βββ examples/
β βββ fullstack-demo/ # Working Express + frontend demo
βββ docs/ # Guides and API documentation
βββ .github/workflows/ # CI/CD with GitHub Actions
MIT Β© Durjoy Ghosh