@aurisid/react
v0.7.1
Published
Pre-built React components for Auris authentication
Maintainers
Readme
@aurisid/react
Pre-built React components for Auris authentication - the open-source Clerk alternative.
Installation
npm install @aurisid/react
# or
pnpm add @aurisid/react
# or
yarn add @aurisid/reactOptional: Bot Protection with Turnstile
For bot protection support, install Cloudflare Turnstile:
npm install @marsidev/react-turnstileQuick Start
1. Wrap your app with AurisProvider
import { AurisProvider } from '@aurisid/react';
function App() {
return (
<AurisProvider apiUrl="https://api.aurisid.com">
<YourApp />
</AurisProvider>
);
}2. Use the components
import { UserButton, SignInButton, SignUpButton, SignedIn, SignedOut } from '@aurisid/react';
function Header() {
return (
<header>
<SignedOut>
<SignInButton />
<SignUpButton />
</SignedOut>
<SignedIn>
<UserButton showName />
</SignedIn>
</header>
);
}Core Components
<AurisProvider>
Wraps your app and provides authentication context.
Props:
apiUrl(optional): URL of your Auris API backendpublishableKey(optional): Your publishable keychildren: Your app components
<AurisProvider apiUrl="https://api.aurisid.com">
<App />
</AurisProvider><UserButton>
Displays a user avatar with a dropdown menu for account settings and sign out.
Props:
showName(boolean, default:false): Show user name next to avatarafterSignOutUrl(string, default:'/sign-in'): Redirect URL after sign out
<UserButton showName afterSignOutUrl="/goodbye" /><SignInButton>
Button that redirects to the sign-in page.
Props:
children(ReactNode): Button contentredirectUrl(string, default:'/sign-in'): Sign-in page URLforceRedirectUrl(string): Force redirect after sign-inclassName(string): Custom CSS classstyle(CSSProperties): Inline styles
<SignInButton>
Log in to your account
</SignInButton><SignUpButton>
Button that redirects to the sign-up page.
Props:
children(ReactNode): Button contentredirectUrl(string, default:'/sign-up'): Sign-up page URLforceRedirectUrl(string): Force redirect after sign-upclassName(string): Custom CSS classstyle(CSSProperties): Inline styles
<SignUpButton>
Create your free account
</SignUpButton><SignedIn>
Renders children only when user is signed in.
<SignedIn>
<Dashboard />
</SignedIn><SignedOut>
Renders children only when user is signed out.
<SignedOut>
<LandingPage />
</SignedOut>Embedded Authentication Components
<SignIn>
Complete embedded sign-in component with email/password and social login.
Features:
- Email/password authentication
- Social login (Google, GitHub)
- Forgot password link
- Automatic bot protection (if enabled)
- Breached password detection
- Customizable appearance
Props:
redirectUrl(string, default:'/dashboard'): Redirect after sign insignUpUrl(string, default:'/sign-up'): URL for sign up linkforgotPasswordUrl(string, default:'/forgot-password'): URL for forgot passwordappearance(object): Customize appearance ({ baseColor: '#6366f1' })onSuccess(function): Callback when sign in succeedsapiUrl(string): Override API URL
<SignIn
redirectUrl="/dashboard"
signUpUrl="/sign-up"
appearance={{ baseColor: '#10b981' }}
onSuccess={(user) => console.log('Signed in:', user)}
/><SignUp>
Complete embedded sign-up component with name fields and terms acceptance.
Features:
- First name and last name fields
- Email/password authentication
- Social signup (Google, GitHub)
- Terms & conditions checkbox
- Automatic bot protection (if enabled)
- Breached password detection
- Password strength validation
Props:
redirectUrl(string, default:'/dashboard'): Redirect after sign upsignInUrl(string, default:'/sign-in'): URL for sign in linkappearance(object): Customize appearance ({ baseColor: '#6366f1' })onSuccess(function): Callback when sign up succeedsapiUrl(string): Override API URL
<SignUp
redirectUrl="/onboarding"
signInUrl="/sign-in"
appearance={{ baseColor: '#10b981' }}
onSuccess={(user) => console.log('Account created:', user)}
/>Magic Links (Passwordless Login)
<MagicLink>
Passwordless authentication component that sends a magic link to user's email.
Features:
- Email-only authentication
- No password required
- Secure token-based verification
- Configurable expiration (15 minutes default)
- Success/error states
- Customizable appearance
Props:
redirectUrl(string, default:'/dashboard'): Redirect after successful verificationcallbackUrl(string): URL for the magic link callback pageappearance(object): Customize appearance ({ baseColor: '#6366f1' })onSent(function): Callback when magic link is sent successfullyapiUrl(string): Override API URL
Example:
// Page where users request magic link
import { MagicLink } from '@aurisid/react';
export default function MagicLinkPage() {
return (
<div>
<h1>Sign in with Magic Link</h1>
<MagicLink
redirectUrl="/dashboard"
callbackUrl="https://myapp.com/magic-link/verify"
onSent={(email) => console.log('Magic link sent to:', email)}
/>
</div>
);
}useMagicLink() Hook
Hook for magic link verification on callback pages.
Options:
apiUrl(string): API URL for authentication endpointsredirectUrl(string, default:'/dashboard'): Redirect after successful verificationonSuccess(function): Callback when verification succeeds (disables auto-redirect)onError(function): Callback when verification fails
Returns:
loading(boolean): Whether verification is in progresserror(string | null): Error message if verification failedsuccess(boolean): Whether verification was successfuluser(object | null): The verified user data
Example:
// Callback page: /magic-link/verify
import { useMagicLink } from '@aurisid/react';
export default function MagicLinkVerifyPage() {
const { loading, error, success } = useMagicLink({
redirectUrl: '/dashboard',
});
if (loading) {
return (
<div>
<h2>Verifying your magic link...</h2>
<p>Please wait</p>
</div>
);
}
if (error) {
return (
<div>
<h2>Verification failed</h2>
<p>{error}</p>
<a href="/sign-in">Try again</a>
</div>
);
}
if (success) {
return (
<div>
<h2>Success!</h2>
<p>Redirecting to dashboard...</p>
</div>
);
}
return null;
}User Impersonation (Admin Feature)
What is Impersonation?
Impersonation allows administrators to view the application as another user without needing their password. This is useful for:
- Customer Support: Debug issues users are experiencing
- Testing: Verify permissions and access controls
- Auditing: Ensure users see correct data based on their roles
<ImpersonationBanner>
Banner component that displays when an admin is impersonating another user.
Features:
- Bright yellow banner (impossible to miss)
- Shows impersonated user's email
- Shows original admin's email
- One-click exit button
- Automatically shown/hidden based on session state
Props:
appearance(object): Customize appearancebackgroundColor(string, default:'#fbbf24'): Banner background colortextColor(string, default:'#1f2937'): Text color
position('top' | 'bottom', default:'top'): Banner position
Example:
// Add to your root layout
import { AurisProvider, ImpersonationBanner } from '@aurisid/react';
export default function RootLayout({ children }) {
return (
<html>
<body>
<AurisProvider apiUrl={process.env.NEXT_PUBLIC_AURIS_API_URL}>
<ImpersonationBanner />
{children}
</AurisProvider>
</body>
</html>
);
}Impersonation Methods in useAuris()
The useAuris() hook provides impersonation functionality:
import { useAuris } from '@aurisid/react';
function AdminUserList() {
const { impersonate, isImpersonating, impersonator, exitImpersonation } = useAuris();
const handleViewAsUser = async (userId: string) => {
try {
await impersonate(userId);
// Page will reload with impersonated session
} catch (error) {
console.error('Failed to impersonate:', error);
}
};
return (
<div>
{isImpersonating && (
<div className="alert">
Viewing as another user (originally {impersonator?.email})
<button onClick={exitImpersonation}>Exit</button>
</div>
)}
<h2>Users</h2>
{users.map(user => (
<div key={user.id}>
<span>{user.email}</span>
<button onClick={() => handleViewAsUser(user.id)}>
View as user
</button>
</div>
))}
</div>
);
}Impersonation Methods:
impersonate(userId: string): Start impersonating another user (admin only)exitImpersonation(): Exit impersonation mode and return to original sessionisImpersonating(boolean): Whether current session is an impersonationimpersonator(AurisUser | null): The original admin user who started impersonation
Bot Protection (Cloudflare Turnstile)
Automatic Bot Protection
SignIn and SignUp components automatically detect and display Cloudflare Turnstile captcha when your backend has bot protection enabled.
Setup:
- Install Turnstile package:
npm install @marsidev/react-turnstileEnable bot protection in your backend (backend configuration required)
Components automatically adapt:
// No code changes needed - SignIn/SignUp auto-detect bot protection
<SignIn />
<SignUp />The components will:
- Query
/api/auth/security-settingson mount - Display Turnstile widget if
botProtectionEnabled: true - Include
captchaTokenin authentication requests - Show validation errors if captcha not completed
How it works:
When bot protection is enabled on your backend:
- Components fetch security settings on load
- If
botProtectionEnabledand Turnstile is installed, captcha appears - User completes captcha before submitting form
- Token is sent to backend for verification
Breached Password Detection
SignUp component automatically handles breached password detection from the backend.
When a user tries to sign up with a compromised password, the backend returns:
{
"error": "VALIDATION_ERROR",
"details": [
"This password has been found in 1,505,362 data breaches. Please choose a different password."
]
}The SignUp component automatically displays this error to the user.
Hooks
useAuris()
Access authentication state and methods.
import { useAuris } from '@aurisid/react';
function MyComponent() {
const {
user,
isSignedIn,
isLoaded,
signOut,
isImpersonating,
impersonator,
impersonate,
exitImpersonation
} = useAuris();
if (!isLoaded) {
return <div>Loading...</div>;
}
if (!isSignedIn) {
return <div>Please sign in</div>;
}
return (
<div>
<p>Welcome {user.firstName}!</p>
{isImpersonating && (
<p>Viewing as {user.email} (originally {impersonator?.email})</p>
)}
<button onClick={signOut}>Sign out</button>
</div>
);
}Returns:
user(AurisUser | null): Current user objectisSignedIn(boolean): Whether user is signed inisLoaded(boolean): Whether auth state has loadedsignOut(() => Promise): Sign out the userisImpersonating(boolean): Whether current session is impersonationimpersonator(AurisUser | null): Original admin user (when impersonating)impersonate((userId: string) => Promise): Start impersonating a user (admin only)exitImpersonation(() => void): Exit impersonation mode
AurisUser Type:
interface AurisUser {
id: string;
email: string;
emailVerified: boolean;
username?: string;
firstName?: string;
lastName?: string;
avatarUrl?: string;
}Complete Example
import {
AurisProvider,
UserButton,
SignInButton,
SignedIn,
SignedOut,
ImpersonationBanner,
useAuris
} from '@aurisid/react';
// Layout component
function Layout({ children }) {
return (
<div>
<header style={{ display: 'flex', justifyContent: 'space-between', padding: '1rem' }}>
<h1>My App</h1>
<SignedOut>
<SignInButton />
</SignedOut>
<SignedIn>
<UserButton showName />
</SignedIn>
</header>
<main>{children}</main>
</div>
);
}
// Protected page
function Dashboard() {
const { user, isImpersonating, impersonator } = useAuris();
return (
<div>
<h2>Dashboard</h2>
<p>Welcome back, {user?.firstName}!</p>
{isImpersonating && (
<div className="alert">
Viewing as {user?.email} (originally {impersonator?.email})
</div>
)}
</div>
);
}
// App root
export default function App() {
return (
<AurisProvider apiUrl="https://api.aurisid.com">
<ImpersonationBanner />
<Layout>
<SignedIn>
<Dashboard />
</SignedIn>
<SignedOut>
<div>
<h2>Welcome to My App</h2>
<SignInButton>Get started</SignInButton>
</div>
</SignedOut>
</Layout>
</AurisProvider>
);
}Next.js App Router
For Next.js 13+ with App Router, create a client component wrapper:
// components/providers/ClientProviders.tsx
'use client';
import { AurisProvider, ImpersonationBanner } from '@aurisid/react';
import { ReactNode } from 'react';
export function ClientProviders({ children }: { children: ReactNode }) {
return (
<AurisProvider apiUrl={process.env.NEXT_PUBLIC_AURIS_API_URL}>
<ImpersonationBanner />
{children}
</AurisProvider>
);
}// app/layout.tsx
import { ClientProviders } from '@/components/providers/ClientProviders';
export default function RootLayout({ children }) {
return (
<html>
<body>
<ClientProviders>{children}</ClientProviders>
</body>
</html>
);
}Styling
Components come with inline styles for framework-agnostic usage. You can customize:
1. Appearance Prop
<SignIn
appearance={{
baseColor: '#10b981' // Green theme
}}
/>
<MagicLink
appearance={{
baseColor: '#8b5cf6' // Purple theme
}}
/>
<ImpersonationBanner
appearance={{
backgroundColor: '#ef4444', // Red background
textColor: '#ffffff' // White text
}}
/>2. CSS Classes
.auris-user-button {
/* Custom styles */
}
.auris-sign-in {
/* Customize SignIn component */
}
.auris-sign-up {
/* Customize SignUp component */
}
.auris-magic-link {
/* Customize MagicLink component */
}
.auris-impersonation-banner {
/* Customize impersonation banner */
}3. Override with className
<SignInButton className="my-custom-button">
Sign in
</SignInButton>Organizations
Auris provides complete multi-tenancy support through Organizations.
<OrganizationSwitcher>
Displays a dropdown to switch between organizations and create new ones.
Props:
apiUrl(string, optional): API URL for AurisshowCreateOrganization(boolean, default:true): Show create organization buttonafterCreateUrl(string, optional): Redirect URL after creating orgorganizationProfileUrl(string, default:'/organization'): Settings page URL
import { OrganizationSwitcher } from '@aurisid/react';
function Header() {
return (
<OrganizationSwitcher
showCreateOrganization={true}
organizationProfileUrl="/settings/org"
/>
);
}<OrganizationProfile>
Full organization settings page with edit and delete capabilities.
Props:
organizationId(string, required): Organization ID to manageapiUrl(string, optional): API URL for AurisonUpdate(function, optional): Callback after successful updateonDelete(function, optional): Callback after successful deletion
import { OrganizationProfile } from '@aurisid/react';
function OrgSettingsPage() {
return (
<OrganizationProfile
organizationId="org_123"
onUpdate={() => console.log('Updated!')}
/>
);
}<OrganizationMembers>
Manage organization members, invitations, and roles.
Props:
organizationId(string, required): Organization IDapiUrl(string, optional): API URL for AurisshowInvitations(boolean, default:true): Show pending invitations
Features:
- Invite members by email
- Assign roles: Owner, Admin, Member
- Update member roles
- Remove members
- Cancel pending invitations
import { OrganizationMembers } from '@aurisid/react';
function MembersPage() {
return (
<OrganizationMembers
organizationId="org_123"
showInvitations={true}
/>
);
}Organization Hooks
useOrganizationList()
Manage the list of organizations.
import { useOrganizationList } from '@aurisid/react';
function MyComponent() {
const {
organizations, // Array of organizations
activeOrganization, // Currently active org ID
isLoading, // Loading state
error, // Error message
createOrganization, // Create new org
setActiveOrganization, // Switch active org
reloadOrganizations // Refresh list
} = useOrganizationList({ apiUrl: 'https://api.aurisid.com' });
const handleCreate = async () => {
await createOrganization({
name: 'My Organization',
slug: 'my-org',
description: 'Optional description'
});
};
return (
<div>
{organizations.map(org => (
<div key={org.id}>{org.name}</div>
))}
</div>
);
}useOrganization()
Manage a specific organization and its members.
import { useOrganization } from '@aurisid/react';
function OrgManager() {
const {
organization, // Organization object
members, // Array of members
invitations, // Pending invitations
isLoading,
error,
updateOrganization, // Update org details
deleteOrganization, // Delete org
loadMembers, // Refresh members
inviteMember, // Invite by email
updateMemberRole, // Change member role
removeMember, // Remove member
loadInvitations, // Refresh invitations
cancelInvitation // Cancel invitation
} = useOrganization({
organizationId: 'org_123',
apiUrl: 'https://api.aurisid.com'
});
const handleInvite = async () => {
await inviteMember({
email: '[email protected]',
role: 'member' // 'owner' | 'admin' | 'member'
});
};
return (
<div>
<h1>{organization?.name}</h1>
<p>{members.length} members</p>
</div>
);
}Multi-Factor Authentication (MFA)
Auris provides complete TOTP-based multi-factor authentication with backup codes.
<MFASetup />
Complete setup flow for enabling TOTP authentication with QR code and backup codes.
Props:
apiUrl(string, optional): API URL for AurisonEnabled(function, optional): Callback when MFA is successfully enabledonCancel(function, optional): Callback when setup is cancelled
import { MFASetup } from '@aurisid/react';
function SecuritySettings() {
return (
<MFASetup
onEnabled={() => console.log('MFA enabled!')}
onCancel={() => window.history.back()}
/>
);
}Features:
- QR code for easy setup with authenticator apps
- Manual key entry option
- Backup codes generation and display
- Step-by-step wizard UI
- Verification before enabling
<MFAVerify />
Verification component for signin flow when MFA is enabled.
Props:
challengeToken(string, required): Token from signin responseapiUrl(string, optional): API URL for AurisonSuccess(function, optional): Callback after successful verificationonCancel(function, optional): Callback when cancelledappearance(object, optional):{ baseColor: string }
import { MFAVerify } from '@aurisid/react';
function MFAChallengePage({ challengeToken }) {
return (
<MFAVerify
challengeToken={challengeToken}
onSuccess={() => window.location.href = '/dashboard'}
appearance={{ baseColor: '#8b5cf6' }}
/>
);
}Features:
- TOTP code verification
- Backup code support
- Toggle between methods
- Automatic token storage
- Error handling
<MFAManage />
Full MFA management interface for user settings.
Props:
apiUrl(string, optional): API URL for AurisonEnabled(function, optional): Callback when MFA is enabledonDisabled(function, optional): Callback when MFA is disabled
import { MFAManage } from '@aurisid/react';
function SecurityPage() {
return (
<MFAManage
onEnabled={() => console.log('MFA enabled')}
onDisabled={() => console.log('MFA disabled')}
/>
);
}Features:
- Display MFA status
- Enable/disable MFA
- Backup codes count
- Inline setup flow
- Confirmation before disabling
MFA Hook
useMFA()
Hook for managing MFA programmatically.
import { useMFA } from '@aurisid/react';
function CustomMFAFlow() {
const {
setupData, // QR code and backup codes
status, // MFA status
isLoading,
error,
setupTOTP, // Start TOTP setup
enableTOTP, // Enable with verification code
disableTOTP, // Disable with verification code
getStatus, // Refresh status
verifyMFA // Verify during signin
} = useMFA({ apiUrl: 'https://api.aurisid.com' });
const handleSetup = async () => {
// Start setup
const setup = await setupTOTP();
console.log('QR Code:', setup.qrCode);
console.log('Backup codes:', setup.backupCodes);
// Enable after user scans QR
await enableTOTP('123456'); // User's code
};
const handleVerify = async (challengeToken: string) => {
const result = await verifyMFA({
challengeToken,
method: 'totp',
code: '123456'
});
// User is now signed in
};
return (
<div>
<button onClick={handleSetup}>Setup MFA</button>
{status?.totpEnabled && (
<p>MFA is enabled. {status.backupCodesCount} backup codes remaining</p>
)}
</div>
);
}Session Management
Auris proporciona componentes para gestionar todas las sesiones activas del usuario:
<SessionList />
Componente completo para visualizar y gestionar sesiones activas.
Props:
apiUrl(string, optional): API URL for AurisonSessionRevoked(function, optional): Callback when a session is revokedonAllOthersRevoked(function, optional): Callback when all other sessions are revoked
import { SessionList } from '@aurisid/react';
function SecurityPage() {
return (
<SessionList
onSessionRevoked={(sessionId) => {
console.log('Session revoked:', sessionId);
}}
onAllOthersRevoked={() => {
console.log('All other sessions revoked');
}}
/>
);
}Features:
- List all active sessions
- Display device, location, and last activity information
- Revoke individual sessions
- Revoke all other sessions (keep current)
- Visual indicator for current session
- Confirmation dialogs before revocation
- Automatic token cleanup when current session is revoked
Session Management Hook
useSessions()
Hook for managing sessions programmatically.
import { useSessions } from '@aurisid/react';
function CustomSessionManager() {
const {
sessions, // List of active sessions
isLoading,
error,
getSessions, // Load sessions
revokeSession, // Revoke a specific session
revokeAllOtherSessions // Revoke all except current
} = useSessions({ apiUrl: 'https://api.aurisid.com' });
useEffect(() => {
getSessions();
}, []);
const handleRevoke = async (sessionId: string) => {
try {
await revokeSession(sessionId);
console.log('Session revoked');
} catch (err) {
console.error('Failed to revoke session');
}
};
return (
<div>
{sessions?.map((session) => (
<div key={session.id}>
<p>{session.device?.browser} on {session.device?.os}</p>
<p>Last activity: {new Date(session.lastActivityAt).toLocaleString()}</p>
{!session.isCurrent && (
<button onClick={() => handleRevoke(session.id)}>
Revoke
</button>
)}
</div>
))}
</div>
);
}Webhooks
Auris proporciona componentes para configurar y gestionar webhooks:
<WebhookList />
Componente completo para gestionar webhooks con CRUD completo.
Props:
apiUrl(string, optional): API URL for AurisonWebhookCreated(function, optional): Callback when a webhook is createdonWebhookUpdated(function, optional): Callback when a webhook is updatedonWebhookDeleted(function, optional): Callback when a webhook is deleted
import { WebhookList } from '@aurisid/react';
function DeveloperSettingsPage() {
return (
<WebhookList
onWebhookCreated={(webhook) => {
console.log('Webhook created:', webhook);
}}
onWebhookUpdated={(webhook) => {
console.log('Webhook updated:', webhook);
}}
onWebhookDeleted={(webhookId) => {
console.log('Webhook deleted:', webhookId);
}}
/>
);
}Features:
- Create, update, and delete webhooks
- Select events to subscribe to (user, session, organization events)
- Activate/deactivate webhooks
- Test webhooks with a test event
- View and copy webhook secrets
- Regenerate secrets
- Full event type selection UI
Webhooks Hook
useWebhooks()
Hook for managing webhooks programmatically.
import { useWebhooks } from '@aurisid/react';
function CustomWebhookManager() {
const {
webhooks, // List of webhooks
isLoading,
error,
getWebhooks, // Load webhooks
createWebhook, // Create new webhook
updateWebhook, // Update existing webhook
deleteWebhook, // Delete webhook
testWebhook, // Send test event
regenerateSecret // Regenerate secret
} = useWebhooks({ apiUrl: 'https://api.aurisid.com' });
useEffect(() => {
getWebhooks();
}, []);
const handleCreate = async () => {
try {
const webhook = await createWebhook({
url: 'https://example.com/webhooks',
events: ['user.created', 'user.updated'],
description: 'User sync webhook'
});
console.log('Webhook created:', webhook);
} catch (err) {
console.error('Failed to create webhook');
}
};
return (
<div>
<button onClick={handleCreate}>Create Webhook</button>
{webhooks?.map((webhook) => (
<div key={webhook.id}>
<p>{webhook.url}</p>
<p>Events: {webhook.events.join(', ')}</p>
<p>Status: {webhook.active ? 'Active' : 'Inactive'}</p>
</div>
))}
</div>
);
}Available Events:
user.created,user.updated,user.deletedsession.created,session.revokedorganization.created,organization.updated,organization.deletedorganization.member.added,organization.member.removedorganization.member.role_updated
TypeScript
All components are fully typed. Import types when needed:
import type {
AurisUser,
AurisContextValue,
UserButtonProps,
SignInProps,
SignUpProps,
MagicLinkProps,
ImpersonationBannerProps,
MagicLinkVerifyResult,
UseMagicLinkOptions,
// Organization types
Organization,
OrganizationMember,
OrganizationInvitation,
OrganizationRole,
CreateOrganizationParams,
UpdateOrganizationParams,
InviteMemberParams,
UpdateMemberRoleParams,
PaginatedResponse,
OrganizationSwitcherProps,
OrganizationProfileProps,
OrganizationMembersProps,
// MFA types
MFASetupResponse,
MFAStatus,
MFAVerifyParams,
MFAVerifyResponse,
MFASetupProps,
MFAVerifyProps,
MFAManageProps,
// Session types
Session,
SessionsListResponse,
RevokeSessionResponse,
SessionListProps,
UseSessionsOptions,
// Webhook types
Webhook,
WebhookEventType,
WebhookDelivery,
CreateWebhookParams,
UpdateWebhookParams,
WebhooksListResponse,
TestWebhookResponse,
WebhookListProps,
UseWebhooksOptions
} from '@aurisid/react';Security Features
🔐 Bot Protection
- Cloudflare Turnstile integration
- Automatic detection and display
- Backend verification of captcha tokens
🔑 Breached Password Detection
- Checks passwords against known breaches
- Automatic error display with breach count
- Prevents users from using compromised passwords
👥 User Impersonation
- Secure admin-only feature
- JWT-based session tracking
- Audit trail with impersonator information
- Clear visual indicator (banner)
🪄 Magic Links
- Token-based passwordless authentication
- Configurable expiration time
- One-time use tokens
- Secure verification flow
🔒 Multi-Factor Authentication (MFA)
- TOTP-based (Google Authenticator, Authy, etc.)
- QR code generation for easy setup
- Backup codes for account recovery
- Challenge token flow for signin verification
- Enable/disable with verification
- Status monitoring and management
📱 Session Management
- View all active sessions across devices
- Device and location information
- Last activity tracking
- Revoke individual sessions
- Revoke all other sessions at once
- Automatic cleanup on revocation
🔔 Webhooks
- Real-time event notifications
- 11+ event types (user, session, organization events)
- CRUD operations with full UI
- Secret-based signature verification
- Test webhooks with sample payloads
- Activate/deactivate webhooks
- Secret regeneration
🏢 Organizations
- Multi-tenancy support with role-based access control
- Owner, Admin, and Member roles
- Email invitations with expiration
- Member management and audit trail
License
MIT
