dauth-react
v7.3.0
Published
React provider and hook for passwordless authentication via the Dauth service (BFF pattern with httpOnly cookies)
Readme
dauth-context-react
React context provider and hook for passwordless authentication with the dauth service. Uses the BFF (Backend-for-Frontend) pattern with httpOnly cookies -- no tokens are exposed to the browser. Provides DauthProvider and useDauth() for seamless integration of dauth tenant authentication into React applications.
Installation
npm install dauth-context-react
# or
pnpm add dauth-context-reactPeer dependency: react >= 16.
Tech Stack
| Technology | Version | Purpose | |---|---|---| | React | >= 16 | Peer dependency | | TypeScript | 5.9 | Type safety | | tsup | 8 | Build tool (CJS + ESM bundles) | | vitest | 4 | Testing framework | | size-limit | 12 | Bundle size budget (10KB per entry) |
Usage
1. Wrap your app with DauthProvider
import { DauthProvider } from 'dauth-context-react';
import { RouterProvider } from 'react-router-dom';
import router from './router/router';
function App() {
return (
<DauthProvider domainName="your-domain-name">
<RouterProvider router={router} fallbackElement={<></>} />
</DauthProvider>
);
}2. Use the useDauth() hook
import { useDauth } from 'dauth-context-react';
function MyComponent() {
const { isAuthenticated, isLoading, user, loginWithRedirect, logout } = useDauth();
if (isLoading) return <div>Loading...</div>;
if (isAuthenticated) {
return (
<div>
<p>Hello, {user.name}!</p>
<button onClick={logout}>Logout</button>
</div>
);
}
return <button onClick={loginWithRedirect}>Login</button>;
}3. Implement the backend proxy
Your backend must implement 6 endpoints at authProxyPath (default /api/auth) that proxy requests to the dauth backend and manage httpOnly session cookies. The dauth-md-node package provides a ready-made Express router for this.
Authentication flow
- On mount: checks for
?code=in the URL. If present, exchanges the code for a session viaPOST {authProxyPath}/exchange-code. If absent, checks for an existing session viaGET {authProxyPath}/session. - Login:
loginWithRedirect()navigates to{dauthUrl}/{domainName}/signin. After authentication, dauth redirects back with?code=. - Logout: calls
POST {authProxyPath}/logoutand resets context state. - CSRF: mutating requests read the CSRF token from cookie and send it as
X-CSRF-Tokenheader. - Localhost detection: auto-routes to
localhost:5185in development,https://dauth.ovhin production. Override withdauthUrlprop.
API Reference
<DauthProvider> props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| domainName | string | yes | - | Tenant identifier used in the signin redirect URL |
| children | React.ReactNode | yes | - | Child components |
| authProxyPath | string | no | '/api/auth' | Base path of the auth proxy on the consumer's backend |
| onError | (error: Error) => void | no | console.error | Error callback for failed auth operations |
| env | string | no | - | Environment name appended as ?env= to the signin redirect URL |
| dauthUrl | string | no | auto-detected | Override the dauth frontend URL (e.g. 'https://dev.dauth.ovh' for staging) |
useDauth() return value
| Property | Type | Description |
|---|---|---|
| user | IDauthUser | Authenticated user object |
| domain | IDauthDomainState | Domain configuration (name, loginRedirect, allowedOrigins, authMethods) |
| isLoading | boolean | true while the initial auth check is in progress |
| isAuthenticated | boolean | true if the user has a valid session |
| loginWithRedirect | () => void | Redirects to the dauth tenant sign-in page |
| logout | () => void | Clears the session (server-side + context reset) |
| updateUser | (fields: Partial<IDauthUser>) => Promise<boolean> | Updates user profile fields via the proxy |
| updateUserWithRedirect | () => void | Redirects to the dauth profile editing page |
| deleteAccount | () => Promise<boolean> | Deletes the user account |
Backend proxy endpoints
Your backend must implement these at authProxyPath:
| Method | Path | Purpose |
|---|---|---|
| POST | /exchange-code | Exchange authorization code for tokens, set httpOnly cookies |
| GET | /session | Verify session cookie, return user + domain data |
| POST | /logout | Clear session cookies |
| PATCH | /user | Forward user profile updates to dauth |
| DELETE | /user | Forward account deletion to dauth |
| GET | /profile-redirect | Return redirect URL to the dauth profile page |
Exported types
IDauthUser-- user object (name, email, avatar, role, language, etc.)IDauthDomainState-- domain config (name, environments, loginRedirect, allowedOrigins, authMethods)IDauthState-- full context valueIDauthProviderProps-- provider propsIDauthAuthMethods-- auth methods config (magicLink,passkey)IActionStatus-- status object (type, message)
Scripts
| Script | Description |
|---|---|
| pnpm start | Watch mode (tsup --watch) |
| pnpm build | Production build (CJS + ESM + types) |
| pnpm test | Run vitest tests (80 tests) |
| pnpm test:coverage | Coverage report (v8, 70% threshold) |
| pnpm typecheck | TypeScript type checking |
| pnpm size | Check bundle size (10KB budget per entry) |
| pnpm format | Prettier formatting |
Testing
80 tests across 6 files using vitest 4 with @testing-library/react (jsdom environment).
pnpm test
pnpm test:coveragePublishing
Automated via GitHub Actions. Push a v* tag to trigger build, test, and npm publish.
# 1. Bump version in package.json
# 2. Commit and tag
git tag v5.0.1
git push origin main --tags
# 3. GitHub Actions publishes to npm automaticallyRequires NPM_TOKEN secret configured in the GitHub repo.
Code Style
Prettier: 80 char width, single quotes, semicolons, trailing commas (es5), 2-space indent.
License
MIT
