Authentication components and WorkOS AuthKit wrappers for mdxui
npm install @mdxui/authAuthentication components and WorkOS AuthKit wrappers for mdxui applications. Provides a complete authentication solution with type-safe Zod schemas that extend mdxui's type system.
``bash`
pnpm add @mdxui/auth
The easiest way to get started - just set environment variables:
`bash`.env
VITE_WORKOS_CLIENT_ID=client_xxx
VITE_APP_NAME=My App
`tsx
import { AuthApp } from '@mdxui/auth/shell'
function App() {
return
}
`
That's it! You get a complete authenticated app with:
- Sidebar navigation with org switcher
- Profile, Security, Sessions, API Keys, Team, and Integrations pages
- Error boundaries with friendly messages
- Theme support
`tsx
import { AuthApp } from '@mdxui/auth/shell'
function App() {
return (
branding: { name: 'My App' },
identity: {
clientId: 'client_xxx',
redirectUri: 'https://myapp.com/callback',
},
}}
/>
)
}
`
`tsx
import { AuthApp, accountRoutes, developerRoutes } from '@mdxui/auth/shell'
import { FileText } from 'lucide-react'
import { DocsPage } from './pages/DocsPage'
function App() {
return (
branding: { name: 'My App' },
identity: { clientId: 'client_xxx' },
routes: [
...accountRoutes, // Profile, Security, Sessions
...developerRoutes, // API Keys
{
key: 'docs',
path: '/docs',
label: 'Documentation',
icon: FileText,
component: DocsPage,
group: 'developer',
},
],
}}
/>
)
}
`
For deployments where you don't want a build step, use the prebuilt app. The package includes a complete SPA in the app/ directory with all CSS (Tailwind), React, and routing bundled.
#### Option A: Serve with Hono (Recommended)
Use Hono to serve the prebuilt app with config injection from environment variables:
wrangler.toml:
`toml
name = "my-auth-app"
main = "src/index.ts"
[assets]
directory = "node_modules/@mdxui/auth/app"
[vars]
WORKOS_CLIENT_ID = "client_01EXAMPLE"
APP_NAME = "My App"
`
src/index.ts:
`ts
import { Hono } from 'hono'
type Bindings = {
ASSETS: Fetcher
WORKOS_CLIENT_ID: string
APP_NAME?: string
APP_TAGLINE?: string
LOGO_URL?: string
}
const app = new Hono<{ Bindings: Bindings }>()
// Serve config from environment variables
app.get('/auth-config.json', (c) => {
return c.json({
clientId: c.env.WORKOS_CLIENT_ID,
appName: c.env.APP_NAME ?? 'App',
tagline: c.env.APP_TAGLINE,
logoUrl: c.env.LOGO_URL,
})
})
// Serve static assets (SPA fallback handled by assets)
app.all('*', async (c) => {
return c.env.ASSETS.fetch(c.req.raw)
})
export default app
`
#### Option B: Vanilla Worker
If you're not using Hono, use the standard Worker API:
src/index.ts:
`ts
export interface Env {
ASSETS: Fetcher
WORKOS_CLIENT_ID: string
APP_NAME?: string
}
export default {
async fetch(request: Request, env: Env): Promise
const url = new URL(request.url)
// Serve config from environment variables
if (url.pathname === '/auth-config.json') {
return Response.json({
clientId: env.WORKOS_CLIENT_ID,
appName: env.APP_NAME ?? 'App',
})
}
// Serve static assets
return env.ASSETS.fetch(request)
}
}
`
Both approaches:
- No copying files needed
- Config comes from secure environment variables
- Easy to update by bumping the package version
#### Option C: Copy to Static Directory
Copy the prebuilt app and add your config file:
1. Install and copy:
`bash`
pnpm add @mdxui/auth
cp -r node_modules/@mdxui/auth/app/* public/
2. Create public/auth-config.json:
`json`
{
"clientId": "client_01EXAMPLE",
"appName": "My App"
}
3. Configure wrangler.toml:
`toml
name = "my-auth-app"
[assets]
directory = "public"
`
This approach:
- Works with any static hosting (Netlify, Vercel, S3, etc.)
- Config is a static file in your repo
- Requires re-copying after package updates
#### Config Options
| Field | Required | Description |
|-------|----------|-------------|
| clientId | Yes | WorkOS client ID |appName
| | No | App name (default: "App") |tagline
| | No | Subtitle shown in sidebar |redirectUri
| | No | OAuth redirect URI |apiHostname
| | No | WorkOS API hostname |devMode
| | No | Enable dev mode (default: false) |logoUrl
| | No | URL to logo image |
`tsx
import {
IdentityProvider,
AuthGate,
useAuth,
UserProfile,
} from '@mdxui/auth'
function App() {
return (
)
}
function Dashboard() {
const { user, getAccessToken } = useAuth()
return (
Features
- Zero-Config AuthApp - Complete authenticated app shell with environment variable support
- Pre-built Pages - Profile, Security, Sessions, API Keys, Team, and Integrations pages
- Route Presets - Composable route groups (
accountRoutes, developerRoutes, adminRoutes)
- SidebarOrgSwitcher - Auto-wired org switcher with branding fallback
- WidgetErrorBoundary - Friendly, contextual error messages for widget failures
- Authentication Providers - IdentityProvider and AuthGate for managing auth state
- WorkOS Widgets - Pre-built components for user management (profile, security, API keys)
- Vault Components - UI for managing encrypted secrets with VaultProvider
- Secrets Manager - Full-featured secrets management widget
- Type-Safe Schemas - Zod schemas extending mdxui's UserIdentity and Session types
- React Hooks - useAuth, useWidgetToken, and useVault for accessing state
- UI Components - Sign in/out buttons, user menu, team switcherExports
$3
Everything you need for most use cases:
`tsx
import {
// Providers
IdentityProvider,
IdentityProviderMinimal,
AuthGate,
WidgetsProvider,
VaultProvider, // Widgets
UserProfile,
UserSecurity,
UserSessions,
ApiKeys,
UsersManagement,
OrganizationSwitcher,
// Vault Components
VaultList,
VaultItemCard,
VaultInputModal,
VaultDeleteDialog,
VaultEmptyState,
SecretsManager,
// Components
SignInButton,
SignOutButton,
UserMenu,
TeamSwitcher,
// Hooks
useAuth,
useWidgetToken,
useVault,
useVaultContext,
// Schemas
AuthUserSchema,
AuthSessionSchema,
AuthOrganizationSchema,
} from '@mdxui/auth'
// Types
import type {
AuthUser,
AuthSession,
AuthOrganization,
AuthToken,
VaultClient,
VaultItem,
VaultField,
} from '@mdxui/auth'
`$3
Complete authenticated app shell with routing:
`tsx
import {
// App Components
AuthApp, // Zero-config app with built-in routing
AuthAppWithChildren, // App shell without routing (bring your own)
AuthAppProvider, // Providers only (for custom layouts)
AuthShell, // Shell layout component
AuthShellNav, // Navigation component // Shell Components
SidebarOrgSwitcher, // Org switcher with branding fallback
WidgetErrorBoundary, // Error boundary with friendly messages
Breadcrumbs, // Breadcrumb navigation
// Pre-built Pages
ProfilePage, // User profile management
SecurityPage, // Password and MFA settings
SessionsPage, // Active sessions management
ApiKeysPage, // API key management
TeamPage, // Team member management (requires org)
IntegrationsPage, // Third-party integrations
// Route Presets
defaultRoutes, // All default routes
defaultGroups, // Default route groups
accountRoutes, // Profile, Security, Sessions
developerRoutes, // API Keys
adminRoutes, // Team management
integrationRoutes, // Integrations
// Config Hooks
useAuthShellConfig,
useAuthShellRoutes,
useAuthShellBranding,
} from '@mdxui/auth/shell'
// Types
import type {
AuthAppConfig,
AuthAppProps,
AuthAppRoute,
AuthShellBranding,
AuthShellIdentity,
} from '@mdxui/auth/shell'
`$3
For more granular imports:
`tsx
// Only providers
import { IdentityProvider, AuthGate } from '@mdxui/auth/providers'// Only widgets
import { UserProfile, ApiKeys } from '@mdxui/auth/widgets'
// Only components
import { SignInButton, UserMenu } from '@mdxui/auth/components'
// Only hooks
import { useAuth, useWidgetToken } from '@mdxui/auth/hooks'
// Only schemas (for runtime validation)
import { AuthUserSchema, AuthSessionSchema } from '@mdxui/auth/schemas'
// Only types
import type { AuthUser, AuthGateProps } from '@mdxui/auth/types'
`Type System
$3
AuthUser extends mdxui's UserIdentity with WorkOS-specific fields:`tsx
import type { UserIdentity } from 'mdxui/admin'
import type { AuthUser } from '@mdxui/auth'// AuthUser includes all UserIdentity fields plus WorkOS extras
const user: AuthUser = {
// From UserIdentity
id: 'user_123',
email: 'john@example.com',
firstName: 'John',
lastName: 'Doe',
roles: ['admin'],
permissions: ['users:read', 'users:write'],
organizationId: 'org_123',
// WorkOS-specific
emailVerified: true,
createdAt: '2024-01-01T00:00:00Z',
updatedAt: '2024-01-15T00:00:00Z',
}
// AuthUser is assignable to UserIdentity
const identity: UserIdentity = user // Works!
`$3
Use schemas for validating API responses:
`tsx
import { AuthUserSchema, AuthSessionSchema } from '@mdxui/auth/schemas'// Validate user data
const result = AuthUserSchema.safeParse(apiResponse)
if (result.success) {
console.log('Valid user:', result.data.email)
} else {
console.error('Invalid user:', result.error)
}
// Session with impersonation support
const sessionResult = AuthSessionSchema.safeParse({
id: 'session_123',
userId: 'user_123',
createdAt: '2024-01-01T00:00:00Z',
expiresAt: '2024-01-02T00:00:00Z',
impersonator: {
email: 'admin@example.com',
reason: 'Customer support',
},
})
`AuthApp (Shell)
$3
AuthApp can read configuration from environment variables, perfect for Cloudflare Workers Static Assets:
`bash
.env
VITE_WORKOS_CLIENT_ID=client_xxx # Required
VITE_WORKOS_REDIRECT_URI=https://... # Optional
VITE_WORKOS_API_HOSTNAME=auth.apis.do # Optional
VITE_WORKOS_DEV_MODE=true # Optional
VITE_APP_NAME=My App # Optional (defaults to "App")
VITE_APP_TAGLINE=Best app ever # Optional
``tsx
import { AuthApp } from '@mdxui/auth/shell'// That's it - reads config from env vars
function App() {
return
}
`$3
Compose routes from presets:
`tsx
import {
AuthApp,
accountRoutes, // Profile, Security, Sessions
developerRoutes, // API Keys
adminRoutes, // Team
integrationRoutes, // Integrations
defaultGroups,
} from '@mdxui/auth/shell'function App() {
return (
config={{
branding: { name: 'My App' },
identity: { clientId: 'client_xxx' },
groups: defaultGroups,
routes: [
...accountRoutes,
...developerRoutes,
// Exclude adminRoutes if you don't need team management
],
}}
/>
)
}
`$3
Wraps WorkOS widgets with friendly error handling:
`tsx
import { WidgetErrorBoundary } from '@mdxui/auth/shell'
import { UserProfile } from '@mdxui/auth/widgets'function ProfilePage() {
return (
)
}
// On error: "Your profile is camera shy right now..."
// Unknown widgets: "Something went wrong loading your API Keys..."
`$3
`tsx
import { AuthApp, SidebarOrgSwitcher } from '@mdxui/auth/shell'// Default: SidebarOrgSwitcher is included automatically
// Custom header content
config={config}
sidebarHeaderContent={ }
/>
`Components
$3
Wraps your app with authentication context:
`tsx
clientId="client_xxx"
devMode={process.env.NODE_ENV === 'development'}
redirectUri="http://localhost:3000/callback"
>
`$3
Protects routes requiring authentication:
`tsx
// Redirect unauthenticated users
// Show landing page for unauthenticated users
onUnauthenticated="landing"
landingComponent={ }
loadingComponent={ }
>
// Allow access but with different content
{({ user }) => user ? : }
`$3
Pre-built WorkOS widgets for user management:
`tsx
function SettingsPage() {
const { getAccessToken } = useAuth() return (
)
}
`$3
#### useAuth
Access authentication state and methods:
`tsx
function ProfileButton() {
const {
user, // Current user or null
isLoading, // Loading state
isAuthenticated,// Boolean auth status
signIn, // Sign in method
signOut, // Sign out method
getAccessToken, // Get access token for API calls
} = useAuth() if (isLoading) return
if (!isAuthenticated) return
return
}
`#### useWidgetToken
Fetch tokens for WorkOS widgets:
`tsx
function ApiKeysWidget() {
const { token, loading, error, refetch } = useWidgetToken({
widget: 'api-keys',
organizationId: 'org_123',
endpoint: '/api/workos/widget-token', // default
}) if (loading) return
if (error) return
return
}
`Vault Components
@mdxui/auth includes components for managing encrypted secrets via WorkOS Vault.
$3
Wrap your app with
VaultProvider to enable vault functionality:`tsx
import { VaultProvider, useVault } from '@mdxui/auth'function App() {
const vaultClient = useMyVaultClient() // Your vault client implementation
return (
)
}
`$3
Access vault state and operations:
`tsx
function SecretsPage() {
const {
items, // Array of vault items
isLoading, // Loading state
error, // Error message if any
createItem, // Create new secret
updateItem, // Update existing secret
deleteItem, // Delete a secret
refresh, // Refresh the list
} = useVault() return
}
`$3
Pre-built components for secrets management:
`tsx
import {
VaultList,
VaultItemCard,
VaultInputModal,
VaultDeleteDialog,
VaultEmptyState,
} from '@mdxui/auth'function SecretsManager() {
const { items, isLoading, createItem, deleteItem } = useVault()
const [showCreate, setShowCreate] = useState(false)
const [deleteTarget, setDeleteTarget] = useState(null)
if (isLoading) return
if (items.length === 0) return setShowCreate(true)} />
return (
<>
items={items}
onItemClick={(item) => console.log('View', item)}
onItemDelete={(item) => setDeleteTarget(item)}
/>
open={showCreate}
onClose={() => setShowCreate(false)}
onSubmit={async (data) => {
await createItem(data)
setShowCreate(false)
}}
/>
open={!!deleteTarget}
item={deleteTarget}
onClose={() => setDeleteTarget(null)}
onConfirm={async () => {
await deleteItem(deleteTarget.id)
setDeleteTarget(null)
}}
/>
>
)
}
`$3
A complete, ready-to-use secrets management interface:
`tsx
import { SecretsManager } from '@mdxui/auth'function SettingsPage() {
return (
context={{ organizationId: 'org_123' }}
onSecretChange={(secret) => console.log('Changed:', secret)}
/>
)
}
`API Reference
$3
| Schema | Extends | Description |
|--------|---------|-------------|
|
AuthUserSchema | UserIdentitySchema | User with WorkOS fields |
| AuthSessionSchema | SessionSchema | Session with impersonation |
| AuthOrganizationSchema | - | WorkOS organization |
| ImpersonatorSchema | - | Admin impersonation info |
| AuthGatePropsSchema | - | AuthGate component props |
| WidgetsProviderPropsSchema | - | WidgetsProvider props |$3
| Type | Description |
|------|-------------|
|
AuthUser | Inferred from AuthUserSchema |
| AuthSession | Inferred from AuthSessionSchema |
| AuthOrganization | WorkOS organization |
| AuthToken | string \| (() => Promise |
| Impersonator` | Admin performing impersonation |MIT