@auth31/auth-service
v1.0.17
Published
Reusable authentication package with login, forgot password, and reset password flows using React, TypeScript, and MUI
Downloads
804
Readme
@auth31/auth-service
A comprehensive and reusable authentication service for React and Next.js applications, featuring Login, MFA (OTP Verification), Forgot Password, Reset Password, Change Password, and token refresh flows with Material UI (MUI) and dynamic branding support.
🚀 Features
- Pre-built Auth Pages: Highly optimized Login, MFA (Verify OTP), Forgot Password, Reset Password, and Change Password pages.
- Token Refresh: Built-in
POST /auth/refreshsupport with token rotation, cookie storage, and automatic retry on401. - Backend-Driven Error Messaging: Displays precise backend API error responses (
detail,message,error) seamlessly across all authentication flows without static fallback error strings. - Enhanced OTP Verification & Device Trust (MFA):
- Remember Device Trust Window: "Remember this device" option to establish an MFA trust window for the organization's configured duration (
mfa_trust_days). - MFA Bypass (
v3/auth/login): Automatically skips OTP verification on trusted devices whenmfa_skipped: trueand passes authcodedirectly for token exchange. - Privacy & Security: Built-in email masking with interactive show/hide toggle.
- Persistent Cooldown: Session-backed OTP resend timer that maintains countdown across browser refreshes.
- Seamless Inputs: Mobile-friendly 6-digit input boxes (
OtpInputGroup) with auto-focus and clipboard paste support.
- Remember Device Trust Window: "Remember this device" option to establish an MFA trust window for the organization's configured duration (
- Dynamic Branding: Inject logos, titles, colors, background, and MFA trust period dynamically via
BrandingProvideror remote config. - Flexible UI: Seamlessly integrates with Material UI (v5/v6) and custom themes.
- Multiple Frameworks: Complete integration support for React (Vite/CRA) and Next.js (App Router).
- Callback Driven: Handle authentication events (success/failure) and navigation overrides with custom callbacks.
🆕 What's New in Recent Updates
🛡️ MFA Device Trust & OTP Bypass (v3/auth/login)
- Remember this Device: A styled checkbox on the OTP screen sends
remember_mfa: trueto/api/v2/auth/verify-otp. - Dynamic Policy Note: An informative note renders with smooth animation indicating the active trust duration (e.g. "You won't be asked for a verification code on this device for the next 10 days." based on
mfa_trust_days). - Instant Login (MFA Skipped): The login flow calls
POST /api/v3/auth/login. If the device has an active MFA trust window, the API returnsmfa_skipped: truewith an authcode, immediately redirecting for token exchange without requiring OTP.
🔄 Token Refresh (/api/v1/auth/refresh)
- Exchange a valid refresh token for a new access + refresh token pair.
- Token rotation: the submitted refresh token is revoked; the client must replace both stored tokens.
- Public-Key header is sent automatically from cached branding (must match the app that issued the token).
- Single session: if another device already consumed the refresh token, the API returns
401and the package clears tokens and redirects to login. - Authenticated package API calls that receive
401automatically attempt one refresh, then retry.
⚡ Backend-Driven Error Toast Notifications
- Replaced hardcoded static error strings with direct backend error response parsing (
detail,message,error). - Clean, single-source toast notifications for failed API calls (e.g.
{"detail": "Invalid OTP code"}).
🔐 MFA & OTP Improvements
- Email Privacy Control: Automatically masks recipient email (
a*****@domain.com) with a toggle button to reveal the full email address. - Resend OTP Cooldown: Persisted timer storage (
otpResendStorage) ensuring cooldown timers remain accurate even if the page is refreshed. - Dynamic Text Templates: Support for template interpolation in
verifyOtpbranding configuration ({{email}},{{expiryTime}},{{days}}). - Modular Subcomponents: Exported standalone
OtpInputGroup,VerifyOtpLeftSection, andOtpResendSectioncomponents.
📦 Installation
To get started, install the package and its peer dependencies:
npm install @auth31/auth-service @mui/material @emotion/react @emotion/styled @mui/icons-material react-router-dom axios notistack js-cookie[!NOTE] Ensure you have
reactandreact-dom(>= 18) installed in your project.
🛠️ Usage: React (Vite/CRA)
Follow these steps to integrate the auth service into your React application.
1. Configure the Auth Provider
In your entry point (usually main.tsx or App.tsx), wrap your application with the hierarchical providers.
[!IMPORTANT]
appIdandbackend_urlare essential configuration properties. Other properties likeendpoints,callbacks, andnavigationare optional. SetonNavigateToLoginso expired sessions redirect correctly after a failed refresh.
import {
AuthConfigProvider,
BrandingProvider,
ThemeProvider,
NotistackProvider,
LoginPage,
ForgotPasswordPage,
ResetPasswordPage,
VerifyOtpPage
} from "@auth31/auth-service";
import { BrowserRouter, Routes, Route } from "react-router-dom";
const authConfig = {
appId: "12345", // Required
apiBaseUrl: "http://localhost:3000", // Frontend URL (Testing)
backend_url: "https://your-api-url.com/api/v1", // Backend API URL
navigation: {
onNavigateToLogin: () => {
window.location.assign("/");
}
},
callbacks: {
onTokenRefreshSuccess: (data) => {
console.log("Tokens refreshed", data);
},
onTokenRefreshError: (error) => {
console.error("Token refresh failed", error);
},
onSessionExpired: () => {
console.log("Session expired — user redirected to login");
}
}
};
function App() {
return (
<AuthConfigProvider config={authConfig}>
<BrandingProvider>
{/* ThemeProvider is optional. Use yours or ours! */}
<ThemeProvider>
<NotistackProvider>
<BrowserRouter>
<Routes>
<Route path="/" element={<LoginPage />} />
<Route path="/verify-otp" element={<VerifyOtpPage />} />
<Route
path="/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route path="/reset-password" element={<ResetPasswordPage />} />
</Routes>
</BrowserRouter>
</NotistackProvider>
</ThemeProvider>
</BrandingProvider>
</AuthConfigProvider>
);
}
export default App;🛠️ Usage: Next.js (App Router)
Since this package uses react-router-dom for internal navigation, it requires a client-side wrapper to function within Next.js.
Step 1: Create a Client-Side Auth Wrapper
Create components/AuthServiceWrapper.tsx:
"use client";
import {
AuthConfigProvider,
BrandingProvider,
ThemeProvider,
NotistackProvider,
LoginPage,
ForgotPasswordPage,
ResetPasswordPage,
VerifyOtpPage
} from "@auth31/auth-service";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { useRouter } from "next/navigation";
export default function AuthServiceWrapper() {
const router = useRouter();
const authConfig = {
appId: process.env.NEXT_PUBLIC_APP_ID!,
backend_url: process.env.NEXT_PUBLIC_API_URL!,
apiBaseUrl: "http://localhost:3000", // Frontend URL for testing
navigation: {
onNavigateToLogin: () => router.push("/auth/login"),
onNavigateToVerifyOtp: (data) =>
router.push(
`/auth/verify-otp?request_id=${data.request_id}&email=${data.email}`
)
},
callbacks: {
onLoginSuccess: (data) => {
console.log("Login success, proceed to MFA", data);
},
onVerifyOtpSuccess: () => router.push("/dashboard"),
onTokenRefreshSuccess: (data) => {
console.log("Tokens refreshed", data);
},
onSessionExpired: () => router.push("/auth/login")
}
};
return (
<AuthConfigProvider config={authConfig}>
<BrandingProvider>
<ThemeProvider>
<NotistackProvider>
<BrowserRouter basename="/auth">
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/verify-otp" element={<VerifyOtpPage />} />
<Route
path="/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route path="/reset-password" element={<ResetPasswordPage />} />
</Routes>
</BrowserRouter>
</NotistackProvider>
</ThemeProvider>
</BrandingProvider>
</AuthConfigProvider>
);
}Step 2: Create a Catch-all Route
Create app/auth/[...slug]/page.tsx to handle all authentication routes:
import dynamic from "next/dynamic";
// Disable SSR for the auth flow because it depends on browser routing
const AuthServiceWrapper = dynamic(
() => import("@/components/AuthServiceWrapper"),
{ ssr: false }
);
export default function AuthPage() {
return <AuthServiceWrapper />;
}🔑 Token Storage & Refresh (Host App Requirements)
Installing the package and wrapping providers is not enough for refresh. The MFA flow returns an authorization code, not tokens. Your host application must store tokens after it receives them (for example after exchanging the code with your backend).
1. Store tokens (required)
import { tokenStorage } from "@auth31/auth-service";
// After your app obtains access_token + refresh_token:
tokenStorage.set(access_token, refresh_token);Tokens are stored in cookies (access_token, refresh_token).
2. Refresh tokens
import { refreshSession, refreshTokenApi, tokenStorage } from "@auth31/auth-service";
// Recommended: rotates cookies, handles 401 → login
const data = await refreshSession();
// data.access_token, data.refresh_token, data.user, ...
// Or call the API directly (you must store the new pair yourself):
const response = await refreshTokenApi({
refresh_token: tokenStorage.getRefreshToken()!
});
tokenStorage.set(response.access_token, response.refresh_token);3. What the package does automatically
| Behavior | Details |
| -------- | ------- |
| Public-Key header | Injected from branding cache on every API call (including refresh) |
| Token rotation | refreshSession() replaces both cookies with the new pair |
| Auto-refresh on 401 | Package API calls that send Authorization retry once after refresh |
| Failed refresh / 401 | Clears cookies and redirects via navigation.onNavigateToLogin (fallback: /) |
[!IMPORTANT] Auto-refresh only applies to the package API client. If your host app uses its own Axios/fetch client, call
refreshSession()yourself on401, or usecreateApiClientfrom this package.
4. Clear tokens on logout
import { tokenStorage } from "@auth31/auth-service";
tokenStorage.clear();⚙️ Configuration Reference
AuthConfig
| Property | Type | Requirement | Description |
| ------------- | -------- | ------------ | ----------- |
| backend_url | string | Required | The base URL for your authentication backend API (e.g. https://…/api/v1). |
| apiBaseUrl | string | Optional | Frontend Testing URL. If provided, it takes precedence over the branding redirect_url and is used to construct forgot password links. Ideal for localhost testing. |
| appId | string | Required | ID used to fetch branding and for Public-Key scoped API calls (including refresh). |
| endpoints | object | Optional | Override default paths for login, forgotPassword, resetPassword, changePassword, and refresh. |
| callbacks | object | Optional | Success/Error hooks for auth actions, MFA, token refresh (onTokenRefreshSuccess, onTokenRefreshError), and onSessionExpired. |
| navigation | object | Optional | Override internal routing (crucial for Next.js). Includes onNavigateToLogin (used after failed refresh) and onNavigateToVerifyOtp. |
BrandingConfig
| Property | Description |
| ---------------- | -------------------------------------------------------------- |
| appName | The name of your application. |
| logoUrl | URL to your brand logo. |
| primaryColor | Hex code for primary buttons and accents. |
| secondaryColor | Hex code for success indicators. |
| background | Configuration for "gradient", "color", or "image" backgrounds. |
📦 Exported Components & Hooks
- Pages:
LoginPage,VerifyOtpPage,ForgotPasswordPage,ResetPasswordPage,ChangePasswordPage. - Auth Components:
AuthLayout,LoginLeftSection,LoginRightSection,VerifyOtpCard,VerifyOtpLeftSection,OtpInputGroup,OtpResendSection,ForgotPasswordCard,ResetPasswordCard,ChangePasswordCard,SuccessModal. - Providers:
AuthConfigProvider,BrandingProvider,ThemeProvider,NotistackProvider. - Hooks:
useAuthConfig(): Access current configuration.useBranding(): Access active branding and theme settings.useResendOtp(): Manage OTP resend countdown timers and requests.
- Token / session:
tokenStorage:set,getAccessToken,getRefreshToken,clear.refreshSession(): Exchange refresh token, rotate cookies, redirect on failure.refreshTokenApi(): Low-levelPOST /auth/refreshcall.
- API & Utils:
loginApi,verifyOtpApi,forgotPasswordApi,changePasswordApi,createApiClient.performAuthRedirect: Unified redirect helper with priority URL resolution.notify: Global toast notification utility.
📄 License
MIT © auth31
