@grasp-labs/ds-auth-web
v0.4.0
Published
Modern authentication library for React applications with OAuth2 and credentials support. Simplified API, automatic token refresh, and full TypeScript support.
Readme
@grasp-labs/ds-auth-web
Modern authentication library for React applications with OAuth2 and credentials support. Simplified API, automatic token refresh, and full TypeScript support.
Installation
npm install @grasp-labs/ds-auth-webFor beta releases:
npm install @grasp-labs/ds-auth-web@betaQuick Start
import { AuthProvider, useAuth } from "@grasp-labs/ds-auth-web";
function App() {
return (
<AuthProvider
storage="session"
credentials={{
loginUrl: "/api/auth/login",
mfaUrl: "/api/auth/mfa",
userInfoUrl: "/api/auth/user",
cors: true, // Enable CORS for credentials-based auth
}}
oauth2={{
google: {
clientId: "your-google-client-id",
redirectUri: window.location.origin,
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
tokenUrl: "https://oauth2.googleapis.com/token",
scope: ["openid", "profile", "email"],
},
}}
>
<YourApp />
</AuthProvider>
);
}
function YourApp() {
const { isAuthenticated, user, loginOAuth2, loginCredentials, logout } =
useAuth();
if (isAuthenticated) {
return (
<div>
Welcome, {user?.name}!<button onClick={logout}>Sign Out</button>
</div>
);
}
return (
<div>
{/* Credentials login */}
<form
onSubmit={(e) => {
e.preventDefault();
const form = e.target as HTMLFormElement;
loginCredentials(form.email.value, form.password.value);
}}
>
<input name="email" type="email" required />
<input name="password" type="password" required />
<button type="submit">Sign In</button>
</form>
{/* OAuth2 login with provider key */}
<button onClick={() => loginOAuth2("google")}>Sign in with Google</button>
</div>
);
}Features
- 🔐 OAuth2 with PKCE - Secure authorization code flow
- 📝 Credentials login - Email/password with MFA support
- 🔄 Auto token refresh - Keeps sessions alive automatically
- 💾 Flexible storage - Session, local, or memory storage
- 🎣 React 19 ready - No unnecessary hooks or memoization
- 🌐 CORS support - Built-in CORS handling for credentials auth
- 🔌 Axios integration - Auto-inject auth headers with one flag
- �️ Error handling - Typed errors with user-friendly messages
- �📦 Small bundle - ~25KB gzipped
- 🚀 TypeScript - Full type safety
API Reference
useAuth() Hook
The main hook for accessing authentication state and methods:
const {
// State
isAuthenticated: boolean,
user: User | null,
tokens: Tokens | null,
method: 'oauth2' | 'credentials' | null,
error: Error | null,
mfa: MFAState | undefined,
// Loading states
isLoggingIn: boolean,
isVerifyingMFA: boolean,
isRefreshing: boolean,
isFetchingUserInfo: boolean,
// Methods
loginOAuth2: (providerKey: string) => Promise<void>,
loginCredentials: (email, password, rememberMe?) => Promise<Tokens | { mfaRequired: true }>,
verifyMFA: (code: string) => Promise<Tokens>,
logout: () => Promise<void>,
refresh: () => Promise<boolean>,
// Utilities
getAuthHeader: () => string | null,
} = useAuth();Configuration
AuthProvider accepts individual props instead of a config object:
interface IAuthProviderProps {
children: ReactNode;
// Storage
storage?: "local" | "session" | "memory"; // Default: 'session'
// Auto refresh
autoRefresh?: boolean; // Default: true
refreshBuffer?: number; // Buffer before expiry in seconds
refreshInterval?: number; // Check interval in ms
// OAuth2 providers
oauth2?: Record<string, OAuth2Config>;
// Credentials configuration
credentials?: CredentialsConfig;
// Callbacks
onAuthChange?: (isAuthenticated: boolean) => void;
onError?: (error: Error) => void;
}
interface OAuth2Config {
clientId: string;
redirectUri: string;
authorizationUrl: string;
tokenUrl: string;
userInfoUrl?: string;
scope?: string[];
clientSecret?: string;
usePKCE?: boolean; // Default: true
revokeUrl?: string;
}
interface CredentialsConfig {
loginUrl: string;
mfaUrl?: string;
userInfoUrl?: string;
refreshUrl?: string;
logoutUrl?: string;
cors?: boolean;
}Development
Getting Started
Want to contribute or run the project locally? Here's what you need:
Requirements:
- Node.js 22 or higher
- npm or your favorite package manager
Setup:
# Install dependencies
npm install
# (Optional) configure example server secrets
cp examples/.env.example examples/.env.local
# Run the example dev server (loads `examples/.env` automatically)
npm run dev:examples
# Run tests
npm test
# Run tests in watch mode (great for development)
npm run test:watch
# Build the library
npm run buildExternal IDP toggle
The credential form in examples/ includes a "Use External IDP" checkbox powered by the IDP_LOGIN_URL, IDP_MFA_URL, and IDP_USERINFO_URL variables. Point those URLs at any identity provider that exposes compatible JSON endpoints—Grasp DP, Keycloak, Auth0, etc.—and the example app will proxy email/password + MFA requests through your backend instead of the mock database. When the toggle is off, everything runs against the mocked routes so you can develop without touching real infrastructure.
The build output goes into the dist/ folder, which is what gets published to npm.
Running Tests
We use Vitest for testing because it's fast and works great with TypeScript:
npm test # Run all tests once
npm run test:watch # Watch mode - tests run as you make changes
npm run test:coverage # Generate a coverage reportCoverage reports are generated as HTML in the coverage/ directory.
Code Quality
Before submitting a PR, make sure your code passes linting and formatting:
npm run lint # Check for issues
npm run lint:fix # Auto-fix what we can
npm run format # Format all files with PrettierLocal Beta Release
To generate and publish a beta release locally:
npm run build
npm version prerelease --preid=beta
npm publish --tag beta