@mdxui/auth 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # @mdxui/auth
2
+
3
+ Authentication components and WorkOS AuthKit wrappers for mdxui applications. Provides a complete authentication solution with type-safe Zod schemas that extend mdxui's type system.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @mdxui/auth
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```tsx
14
+ import {
15
+ IdentityProvider,
16
+ AuthGate,
17
+ useAuth,
18
+ UserProfile,
19
+ } from '@mdxui/auth'
20
+
21
+ function App() {
22
+ return (
23
+ <IdentityProvider clientId="client_xxx">
24
+ <AuthGate>
25
+ <Dashboard />
26
+ </AuthGate>
27
+ </IdentityProvider>
28
+ )
29
+ }
30
+
31
+ function Dashboard() {
32
+ const { user, getAccessToken } = useAuth()
33
+
34
+ return (
35
+ <div>
36
+ <h1>Welcome, {user?.firstName}!</h1>
37
+ <UserProfile authToken={getAccessToken} />
38
+ </div>
39
+ )
40
+ }
41
+ ```
42
+
43
+ ## Features
44
+
45
+ - **Authentication Providers** - `IdentityProvider` and `AuthGate` for managing auth state
46
+ - **WorkOS Widgets** - Pre-built components for user management (profile, security, API keys)
47
+ - **Type-Safe Schemas** - Zod schemas extending mdxui's `UserIdentity` and `Session` types
48
+ - **React Hooks** - `useAuth` and `useWidgetToken` for accessing auth state
49
+ - **UI Components** - Sign in/out buttons, user menu, team switcher
50
+
51
+ ## Exports
52
+
53
+ ### Main Entry (`@mdxui/auth`)
54
+
55
+ Everything you need for most use cases:
56
+
57
+ ```tsx
58
+ import {
59
+ // Providers
60
+ IdentityProvider,
61
+ IdentityProviderMinimal,
62
+ AuthGate,
63
+ WidgetsProvider,
64
+
65
+ // Widgets
66
+ UserProfile,
67
+ UserSecurity,
68
+ UserSessions,
69
+ ApiKeys,
70
+ UsersManagement,
71
+ OrganizationSwitcher,
72
+
73
+ // Components
74
+ SignInButton,
75
+ SignOutButton,
76
+ UserMenu,
77
+ TeamSwitcher,
78
+
79
+ // Hooks
80
+ useAuth,
81
+ useWidgetToken,
82
+
83
+ // Schemas
84
+ AuthUserSchema,
85
+ AuthSessionSchema,
86
+ AuthOrganizationSchema,
87
+ } from '@mdxui/auth'
88
+
89
+ // Types
90
+ import type {
91
+ AuthUser,
92
+ AuthSession,
93
+ AuthOrganization,
94
+ AuthToken,
95
+ } from '@mdxui/auth'
96
+ ```
97
+
98
+ ### Subpath Exports
99
+
100
+ For more granular imports:
101
+
102
+ ```tsx
103
+ // Only providers
104
+ import { IdentityProvider, AuthGate } from '@mdxui/auth/providers'
105
+
106
+ // Only widgets
107
+ import { UserProfile, ApiKeys } from '@mdxui/auth/widgets'
108
+
109
+ // Only components
110
+ import { SignInButton, UserMenu } from '@mdxui/auth/components'
111
+
112
+ // Only hooks
113
+ import { useAuth, useWidgetToken } from '@mdxui/auth/hooks'
114
+
115
+ // Only schemas (for runtime validation)
116
+ import { AuthUserSchema, AuthSessionSchema } from '@mdxui/auth/schemas'
117
+
118
+ // Only types
119
+ import type { AuthUser, AuthGateProps } from '@mdxui/auth/types'
120
+ ```
121
+
122
+ ## Type System
123
+
124
+ ### AuthUser extends UserIdentity
125
+
126
+ `AuthUser` extends mdxui's `UserIdentity` with WorkOS-specific fields:
127
+
128
+ ```tsx
129
+ import type { UserIdentity } from 'mdxui/admin'
130
+ import type { AuthUser } from '@mdxui/auth'
131
+
132
+ // AuthUser includes all UserIdentity fields plus WorkOS extras
133
+ const user: AuthUser = {
134
+ // From UserIdentity
135
+ id: 'user_123',
136
+ email: 'john@example.com',
137
+ firstName: 'John',
138
+ lastName: 'Doe',
139
+ roles: ['admin'],
140
+ permissions: ['users:read', 'users:write'],
141
+ organizationId: 'org_123',
142
+
143
+ // WorkOS-specific
144
+ emailVerified: true,
145
+ createdAt: '2024-01-01T00:00:00Z',
146
+ updatedAt: '2024-01-15T00:00:00Z',
147
+ }
148
+
149
+ // AuthUser is assignable to UserIdentity
150
+ const identity: UserIdentity = user // Works!
151
+ ```
152
+
153
+ ### Runtime Validation with Zod
154
+
155
+ Use schemas for validating API responses:
156
+
157
+ ```tsx
158
+ import { AuthUserSchema, AuthSessionSchema } from '@mdxui/auth/schemas'
159
+
160
+ // Validate user data
161
+ const result = AuthUserSchema.safeParse(apiResponse)
162
+ if (result.success) {
163
+ console.log('Valid user:', result.data.email)
164
+ } else {
165
+ console.error('Invalid user:', result.error)
166
+ }
167
+
168
+ // Session with impersonation support
169
+ const sessionResult = AuthSessionSchema.safeParse({
170
+ id: 'session_123',
171
+ userId: 'user_123',
172
+ createdAt: '2024-01-01T00:00:00Z',
173
+ expiresAt: '2024-01-02T00:00:00Z',
174
+ impersonator: {
175
+ email: 'admin@example.com',
176
+ reason: 'Customer support',
177
+ },
178
+ })
179
+ ```
180
+
181
+ ## Components
182
+
183
+ ### IdentityProvider
184
+
185
+ Wraps your app with authentication context:
186
+
187
+ ```tsx
188
+ <IdentityProvider
189
+ clientId="client_xxx"
190
+ devMode={process.env.NODE_ENV === 'development'}
191
+ redirectUri="http://localhost:3000/callback"
192
+ >
193
+ <App />
194
+ </IdentityProvider>
195
+ ```
196
+
197
+ ### AuthGate
198
+
199
+ Protects routes requiring authentication:
200
+
201
+ ```tsx
202
+ // Redirect unauthenticated users
203
+ <AuthGate onUnauthenticated="redirect" redirectUrl="/login">
204
+ <ProtectedContent />
205
+ </AuthGate>
206
+
207
+ // Show landing page for unauthenticated users
208
+ <AuthGate
209
+ onUnauthenticated="landing"
210
+ landingComponent={<LandingPage />}
211
+ loadingComponent={<LoadingSpinner />}
212
+ >
213
+ <Dashboard />
214
+ </AuthGate>
215
+
216
+ // Allow access but with different content
217
+ <AuthGate onUnauthenticated="allow">
218
+ {({ user }) => user ? <Dashboard /> : <PublicView />}
219
+ </AuthGate>
220
+ ```
221
+
222
+ ### Widgets
223
+
224
+ Pre-built WorkOS widgets for user management:
225
+
226
+ ```tsx
227
+ function SettingsPage() {
228
+ const { getAccessToken } = useAuth()
229
+
230
+ return (
231
+ <WidgetsProvider appearance="dark">
232
+ <Tabs>
233
+ <TabPanel label="Profile">
234
+ <UserProfile authToken={getAccessToken} />
235
+ </TabPanel>
236
+ <TabPanel label="Security">
237
+ <UserSecurity authToken={getAccessToken} />
238
+ </TabPanel>
239
+ <TabPanel label="Sessions">
240
+ <UserSessions authToken={getAccessToken} />
241
+ </TabPanel>
242
+ <TabPanel label="API Keys">
243
+ <ApiKeys authToken={getAccessToken} />
244
+ </TabPanel>
245
+ </Tabs>
246
+ </WidgetsProvider>
247
+ )
248
+ }
249
+ ```
250
+
251
+ ### Hooks
252
+
253
+ #### useAuth
254
+
255
+ Access authentication state and methods:
256
+
257
+ ```tsx
258
+ function ProfileButton() {
259
+ const {
260
+ user, // Current user or null
261
+ isLoading, // Loading state
262
+ isAuthenticated,// Boolean auth status
263
+ signIn, // Sign in method
264
+ signOut, // Sign out method
265
+ getAccessToken, // Get access token for API calls
266
+ } = useAuth()
267
+
268
+ if (isLoading) return <Spinner />
269
+ if (!isAuthenticated) return <SignInButton />
270
+
271
+ return <UserMenu user={user} onSignOut={signOut} />
272
+ }
273
+ ```
274
+
275
+ #### useWidgetToken
276
+
277
+ Fetch tokens for WorkOS widgets:
278
+
279
+ ```tsx
280
+ function ApiKeysWidget() {
281
+ const { token, loading, error, refetch } = useWidgetToken({
282
+ widget: 'api-keys',
283
+ organizationId: 'org_123',
284
+ endpoint: '/api/workos/widget-token', // default
285
+ })
286
+
287
+ if (loading) return <Spinner />
288
+ if (error) return <Error message={error} onRetry={refetch} />
289
+
290
+ return <ApiKeys authToken={token} />
291
+ }
292
+ ```
293
+
294
+ ## API Reference
295
+
296
+ ### Schemas
297
+
298
+ | Schema | Extends | Description |
299
+ |--------|---------|-------------|
300
+ | `AuthUserSchema` | `UserIdentitySchema` | User with WorkOS fields |
301
+ | `AuthSessionSchema` | `SessionSchema` | Session with impersonation |
302
+ | `AuthOrganizationSchema` | - | WorkOS organization |
303
+ | `ImpersonatorSchema` | - | Admin impersonation info |
304
+ | `AuthGatePropsSchema` | - | AuthGate component props |
305
+ | `WidgetsProviderPropsSchema` | - | WidgetsProvider props |
306
+
307
+ ### Types
308
+
309
+ | Type | Description |
310
+ |------|-------------|
311
+ | `AuthUser` | Inferred from `AuthUserSchema` |
312
+ | `AuthSession` | Inferred from `AuthSessionSchema` |
313
+ | `AuthOrganization` | WorkOS organization |
314
+ | `AuthToken` | `string \| (() => Promise<string>)` |
315
+ | `Impersonator` | Admin performing impersonation |
316
+
317
+ ## License
318
+
319
+ MIT
@@ -0,0 +1,116 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ /**
4
+ * Authentication & Authorization Types
5
+ *
6
+ * Types for WorkOS AuthKit integration and identity management.
7
+ *
8
+ * Core types (AuthUser, AuthSession, AuthOrganization) are inferred
9
+ * from Zod schemas and extend mdxui's base types.
10
+ *
11
+ * React-specific props types include ReactNode fields that can't be
12
+ * represented in Zod schemas.
13
+ */
14
+
15
+ /**
16
+ * Props for IdentityProvider
17
+ *
18
+ * Extends the schema type with React-specific fields.
19
+ */
20
+ interface IdentityProviderProps {
21
+ /** WorkOS client ID */
22
+ clientId: string;
23
+ /** Optional API hostname override */
24
+ apiHostname?: string;
25
+ /** Enable dev mode for local development */
26
+ devMode?: boolean;
27
+ /** Redirect URI after authentication */
28
+ redirectUri?: string;
29
+ /** Callback after redirect */
30
+ onRedirectCallback?: () => void;
31
+ /** Children to render */
32
+ children: ReactNode;
33
+ }
34
+ /**
35
+ * Props for AuthGate
36
+ *
37
+ * Extends the schema type with React-specific fields.
38
+ */
39
+ interface AuthGateProps {
40
+ /** Children to show when authenticated */
41
+ children: ReactNode;
42
+ /** Whether authentication is required (default: true) */
43
+ required?: boolean;
44
+ /** Component to show while loading */
45
+ loadingComponent?: ReactNode;
46
+ /** Component to show when not authenticated (landing page) */
47
+ landingComponent?: ReactNode;
48
+ /** What to do when unauthenticated */
49
+ onUnauthenticated?: 'landing' | 'redirect' | 'allow';
50
+ /** URL to redirect to when unauthenticated (if onUnauthenticated is 'redirect') */
51
+ redirectUrl?: string;
52
+ }
53
+ /**
54
+ * Props for WidgetsProvider
55
+ *
56
+ * Extends the schema type with React-specific fields.
57
+ */
58
+ interface WidgetsProviderProps {
59
+ /** Children to render */
60
+ children: ReactNode;
61
+ /** Theme appearance mode */
62
+ appearance?: 'light' | 'dark' | 'inherit';
63
+ /** Border radius style */
64
+ radius?: 'none' | 'small' | 'medium' | 'large' | 'full';
65
+ /** Scaling factor */
66
+ scaling?: '90%' | '95%' | '100%' | '105%' | '110%';
67
+ }
68
+ /**
69
+ * Auth token type - can be a string or a function that returns a Promise<string>
70
+ *
71
+ * Note: This matches WorkOS's AuthToken type. For functions, the return type
72
+ * must be Promise<string>, not string | Promise<string>.
73
+ */
74
+ type AuthToken = string | (() => Promise<string>);
75
+ /**
76
+ * Common props for widget wrappers
77
+ */
78
+ interface BaseWidgetProps {
79
+ /** Auth token for the widget (string or getter function) */
80
+ authToken: AuthToken;
81
+ /** CSS class name */
82
+ className?: string;
83
+ }
84
+ /**
85
+ * Props for widgets that support organization context
86
+ */
87
+ interface OrganizationWidgetProps extends BaseWidgetProps {
88
+ /** Organization ID for org-scoped widgets */
89
+ organizationId?: string;
90
+ }
91
+ /**
92
+ * Props for useWidgetToken hook
93
+ */
94
+ interface UseWidgetTokenOptions {
95
+ /** Widget type to fetch token for */
96
+ widget: string;
97
+ /** Organization ID for org-scoped widgets */
98
+ organizationId?: string;
99
+ /** Custom endpoint for fetching widget token (default: /api/workos/widget-token) */
100
+ endpoint?: string;
101
+ }
102
+ /**
103
+ * Result from useWidgetToken hook
104
+ */
105
+ interface UseWidgetTokenResult {
106
+ /** The fetched token */
107
+ token: string | null;
108
+ /** Whether token is being fetched */
109
+ loading: boolean;
110
+ /** Error message if fetch failed */
111
+ error: string | null;
112
+ /** Function to manually refetch token */
113
+ refetch: () => Promise<void>;
114
+ }
115
+
116
+ export type { AuthGateProps as A, BaseWidgetProps as B, IdentityProviderProps as I, OrganizationWidgetProps as O, UseWidgetTokenOptions as U, WidgetsProviderProps as W, AuthToken as a, UseWidgetTokenResult as b };
@@ -0,0 +1,126 @@
1
+ import * as zod_v4_core from 'zod/v4/core';
2
+ import * as zod from 'zod';
3
+ import { z } from 'zod';
4
+
5
+ /**
6
+ * AuthUserSchema - Extended user identity for WorkOS AuthKit
7
+ *
8
+ * Extends UserIdentitySchema with WorkOS-specific fields like
9
+ * verification status and timestamps.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * import { AuthUserSchema } from '@mdxui/auth/schemas'
14
+ *
15
+ * const result = AuthUserSchema.safeParse(user)
16
+ * if (result.success) {
17
+ * console.log(result.data.emailVerified)
18
+ * }
19
+ * ```
20
+ */
21
+ declare const AuthUserSchema: zod.ZodObject<{
22
+ fullName: zod.ZodOptional<zod.ZodString>;
23
+ avatar: zod.ZodOptional<zod.ZodString>;
24
+ firstName: zod.ZodOptional<zod.ZodString>;
25
+ lastName: zod.ZodOptional<zod.ZodString>;
26
+ profilePictureUrl: zod.ZodOptional<zod.ZodString>;
27
+ roles: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
28
+ permissions: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
29
+ organizationId: zod.ZodOptional<zod.ZodString>;
30
+ organizationName: zod.ZodOptional<zod.ZodString>;
31
+ metadata: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodUnknown>>;
32
+ id: z.ZodString;
33
+ email: z.ZodString;
34
+ emailVerified: z.ZodBoolean;
35
+ createdAt: z.ZodString;
36
+ updatedAt: z.ZodString;
37
+ lastSignInAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
38
+ }, zod_v4_core.$strip>;
39
+ /**
40
+ * AuthUser type inferred from schema
41
+ *
42
+ * This type is compatible with UserIdentity - an AuthUser can be
43
+ * assigned to a variable of type UserIdentity.
44
+ */
45
+ type AuthUser = z.infer<typeof AuthUserSchema>;
46
+
47
+ /**
48
+ * ImpersonatorSchema - Info about admin impersonating a user
49
+ */
50
+ declare const ImpersonatorSchema: z.ZodObject<{
51
+ email: z.ZodString;
52
+ reason: z.ZodOptional<z.ZodString>;
53
+ }, z.core.$strip>;
54
+ type Impersonator = z.infer<typeof ImpersonatorSchema>;
55
+ /**
56
+ * AuthSessionSchema - Extended session for WorkOS AuthKit
57
+ *
58
+ * Extends SessionSchema with WorkOS-specific fields like
59
+ * impersonation support.
60
+ *
61
+ * @example
62
+ * ```tsx
63
+ * import { AuthSessionSchema } from '@mdxui/auth/schemas'
64
+ *
65
+ * const result = AuthSessionSchema.safeParse(session)
66
+ * if (result.success && result.data.impersonator) {
67
+ * console.log('Being impersonated by:', result.data.impersonator.email)
68
+ * }
69
+ * ```
70
+ */
71
+ declare const AuthSessionSchema: zod.ZodObject<{
72
+ id: zod.ZodString;
73
+ createdAt: zod.ZodString;
74
+ expiresAt: zod.ZodString;
75
+ ipAddress: zod.ZodOptional<zod.ZodString>;
76
+ userAgent: zod.ZodOptional<zod.ZodString>;
77
+ organizationId: zod.ZodOptional<zod.ZodString>;
78
+ accessToken: zod.ZodOptional<zod.ZodString>;
79
+ refreshToken: zod.ZodOptional<zod.ZodString>;
80
+ userId: z.ZodString;
81
+ impersonator: z.ZodOptional<z.ZodObject<{
82
+ email: z.ZodString;
83
+ reason: z.ZodOptional<z.ZodString>;
84
+ }, z.core.$strip>>;
85
+ }, zod_v4_core.$strip>;
86
+ /**
87
+ * AuthSession type inferred from schema
88
+ */
89
+ type AuthSession = z.infer<typeof AuthSessionSchema>;
90
+
91
+ /**
92
+ * AuthOrganization Schema
93
+ *
94
+ * Organization type for WorkOS AuthKit.
95
+ */
96
+
97
+ /**
98
+ * AuthOrganizationSchema - WorkOS organization
99
+ *
100
+ * Represents an organization/workspace in WorkOS.
101
+ *
102
+ * @example
103
+ * ```tsx
104
+ * import { AuthOrganizationSchema } from '@mdxui/auth/schemas'
105
+ *
106
+ * const result = AuthOrganizationSchema.safeParse(org)
107
+ * if (result.success) {
108
+ * console.log('Organization:', result.data.name)
109
+ * }
110
+ * ```
111
+ */
112
+ declare const AuthOrganizationSchema: z.ZodObject<{
113
+ id: z.ZodString;
114
+ name: z.ZodString;
115
+ slug: z.ZodOptional<z.ZodString>;
116
+ logoUrl: z.ZodOptional<z.ZodString>;
117
+ active: z.ZodOptional<z.ZodBoolean>;
118
+ domains: z.ZodOptional<z.ZodArray<z.ZodString>>;
119
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
120
+ }, z.core.$strip>;
121
+ /**
122
+ * AuthOrganization type inferred from schema
123
+ */
124
+ type AuthOrganization = z.infer<typeof AuthOrganizationSchema>;
125
+
126
+ export { type AuthUser as A, type Impersonator as I, type AuthOrganization as a, type AuthSession as b, AuthUserSchema as c, AuthSessionSchema as d, AuthOrganizationSchema as e, ImpersonatorSchema as f };