oauth.do 0.2.3 → 0.2.4

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/dist/itty.js ADDED
@@ -0,0 +1,229 @@
1
+ import * as jose from 'jose';
2
+
3
+ // src/itty.ts
4
+ var OAUTH_DO_CONFIG = {
5
+ clientId: "client_01JQYTRXK9ZPD8JPJTKDCRB656",
6
+ jwksUri: "https://api.workos.com/sso/jwks/client_01JQYTRXK9ZPD8JPJTKDCRB656"
7
+ };
8
+ var TOKEN_CACHE_TTL = 5 * 60;
9
+ var CACHE_URL_PREFIX = "https://oauth.do/_cache/token/";
10
+ async function hashToken(token) {
11
+ const data = new TextEncoder().encode(token);
12
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
13
+ return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
14
+ }
15
+ async function getCachedUser(token) {
16
+ try {
17
+ const cache = caches.default;
18
+ const hash = await hashToken(token);
19
+ const cacheKey = new Request(`${CACHE_URL_PREFIX}${hash}`);
20
+ const cached = await cache.match(cacheKey);
21
+ if (!cached) return null;
22
+ const data = await cached.json();
23
+ if (data.expiresAt < Date.now()) return null;
24
+ return data.user;
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
29
+ async function cacheUser(token, user) {
30
+ try {
31
+ const cache = caches.default;
32
+ const hash = await hashToken(token);
33
+ const cacheKey = new Request(`${CACHE_URL_PREFIX}${hash}`);
34
+ const data = { user, expiresAt: Date.now() + TOKEN_CACHE_TTL * 1e3 };
35
+ const response = new Response(JSON.stringify(data), {
36
+ headers: { "Cache-Control": `max-age=${TOKEN_CACHE_TTL}` }
37
+ });
38
+ await cache.put(cacheKey, response);
39
+ } catch {
40
+ }
41
+ }
42
+ function parseCookies(request) {
43
+ const cookieHeader = request.headers.get("Cookie");
44
+ if (!cookieHeader) return {};
45
+ const cookies = {};
46
+ for (const pair of cookieHeader.split(";")) {
47
+ const [name, ...rest] = pair.trim().split("=");
48
+ if (name && rest.length > 0) {
49
+ cookies[name] = rest.join("=");
50
+ }
51
+ }
52
+ return cookies;
53
+ }
54
+ function extractToken(request, cookieName, headerName) {
55
+ const authHeader = request.headers.get(headerName);
56
+ if (authHeader?.startsWith("Bearer ")) {
57
+ return authHeader.slice(7);
58
+ }
59
+ const cookies = parseCookies(request);
60
+ const cookie = cookies[cookieName];
61
+ if (cookie) return cookie;
62
+ return null;
63
+ }
64
+ function payloadToUser(payload) {
65
+ return {
66
+ id: payload.sub || "",
67
+ email: payload.email,
68
+ name: payload.name,
69
+ organizationId: payload.org_id,
70
+ roles: payload.roles,
71
+ permissions: payload.permissions,
72
+ metadata: payload.metadata
73
+ };
74
+ }
75
+ var jwksCache = null;
76
+ var jwksCacheExpiry = 0;
77
+ async function getJwks(jwksUri, cacheTtl) {
78
+ const now = Date.now();
79
+ if (jwksCache && jwksCacheExpiry > now) {
80
+ return jwksCache;
81
+ }
82
+ jwksCache = jose.createRemoteJWKSet(new URL(jwksUri));
83
+ jwksCacheExpiry = now + cacheTtl * 1e3;
84
+ return jwksCache;
85
+ }
86
+ function createDefaultAuthContext() {
87
+ return {
88
+ user: null,
89
+ userId: null,
90
+ isAuth: false,
91
+ token: null
92
+ };
93
+ }
94
+ function jsonError(message, status) {
95
+ return new Response(JSON.stringify({ error: message }), {
96
+ status,
97
+ headers: { "Content-Type": "application/json" }
98
+ });
99
+ }
100
+ function optionalAuth(options = {}) {
101
+ const {
102
+ cookieName = "auth",
103
+ headerName = "Authorization",
104
+ clientId = OAUTH_DO_CONFIG.clientId,
105
+ jwksUri = OAUTH_DO_CONFIG.jwksUri,
106
+ skip,
107
+ jwksCacheTtl = 3600
108
+ } = options;
109
+ return async (request) => {
110
+ const authRequest = request;
111
+ authRequest.auth = createDefaultAuthContext();
112
+ if (skip?.(request)) {
113
+ return;
114
+ }
115
+ const token = extractToken(request, cookieName, headerName);
116
+ if (!token) {
117
+ return;
118
+ }
119
+ authRequest.auth.token = token;
120
+ const cached = await getCachedUser(token);
121
+ if (cached) {
122
+ authRequest.auth.user = cached;
123
+ authRequest.auth.userId = cached.id;
124
+ authRequest.auth.isAuth = true;
125
+ return;
126
+ }
127
+ try {
128
+ const jwks = await getJwks(jwksUri, jwksCacheTtl);
129
+ const { payload } = await jose.jwtVerify(token, jwks, {
130
+ audience: clientId
131
+ });
132
+ const user = payloadToUser(payload);
133
+ authRequest.auth.user = user;
134
+ authRequest.auth.userId = user.id;
135
+ authRequest.auth.isAuth = true;
136
+ await cacheUser(token, user);
137
+ } catch {
138
+ }
139
+ };
140
+ }
141
+ function requireAuth(options = {}) {
142
+ const { redirectTo, roles, permissions, ...authOptions } = options;
143
+ return async (request) => {
144
+ const authRequest = request;
145
+ if (!authRequest.auth) {
146
+ await optionalAuth(authOptions)(request);
147
+ }
148
+ if (!authRequest.auth.isAuth || !authRequest.auth.user) {
149
+ if (redirectTo) {
150
+ return Response.redirect(redirectTo, 302);
151
+ }
152
+ return jsonError("Authentication required", 401);
153
+ }
154
+ if (roles?.length) {
155
+ const userRoles = authRequest.auth.user.roles || [];
156
+ const hasRole = roles.some((r) => userRoles.includes(r));
157
+ if (!hasRole) {
158
+ return jsonError("Insufficient permissions", 403);
159
+ }
160
+ }
161
+ if (permissions?.length) {
162
+ const userPerms = authRequest.auth.user.permissions || [];
163
+ const hasAllPerms = permissions.every((p) => userPerms.includes(p));
164
+ if (!hasAllPerms) {
165
+ return jsonError("Insufficient permissions", 403);
166
+ }
167
+ }
168
+ };
169
+ }
170
+ function apiKey(options) {
171
+ const { headerName = "X-API-Key", verify } = options;
172
+ return async (request) => {
173
+ const authRequest = request;
174
+ authRequest.auth = createDefaultAuthContext();
175
+ const key = request.headers.get(headerName);
176
+ if (!key) {
177
+ return jsonError("API key required", 401);
178
+ }
179
+ const user = await verify(key, request);
180
+ if (!user) {
181
+ return jsonError("Invalid API key", 401);
182
+ }
183
+ authRequest.auth.user = user;
184
+ authRequest.auth.userId = user.id;
185
+ authRequest.auth.isAuth = true;
186
+ authRequest.auth.token = key;
187
+ };
188
+ }
189
+ function combined(options) {
190
+ return async (request) => {
191
+ const authRequest = request;
192
+ if (options.auth) {
193
+ await optionalAuth(options.auth)(request);
194
+ if (authRequest.auth?.isAuth) {
195
+ return;
196
+ }
197
+ }
198
+ if (options.apiKey) {
199
+ const key = request.headers.get(options.apiKey.headerName || "X-API-Key");
200
+ if (key) {
201
+ const user = await options.apiKey.verify(key, request);
202
+ if (user) {
203
+ if (!authRequest.auth) {
204
+ authRequest.auth = createDefaultAuthContext();
205
+ }
206
+ authRequest.auth.user = user;
207
+ authRequest.auth.userId = user.id;
208
+ authRequest.auth.isAuth = true;
209
+ authRequest.auth.token = key;
210
+ return;
211
+ }
212
+ }
213
+ }
214
+ return jsonError("Authentication required", 401);
215
+ };
216
+ }
217
+ function getAuth(request) {
218
+ return request.auth || createDefaultAuthContext();
219
+ }
220
+ function isAuthenticated(request) {
221
+ return request.auth?.isAuth === true;
222
+ }
223
+ function getUser(request) {
224
+ return request.auth?.user || null;
225
+ }
226
+
227
+ export { apiKey, combined, getAuth, getUser, isAuthenticated, optionalAuth, requireAuth };
228
+ //# sourceMappingURL=itty.js.map
229
+ //# sourceMappingURL=itty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/itty.ts"],"names":[],"mappings":"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","file":"itty.js","sourcesContent":["/**\n * oauth.do/itty - itty-router middleware for authentication\n *\n * Lightweight authentication middleware for Cloudflare Workers using itty-router.\n * Uses jose for JWT verification - no heavy WorkOS SDK dependency.\n *\n * @packageDocumentation\n */\n\nimport type { JWTPayload } from 'jose'\nimport * as jose from 'jose'\n\n// Cloudflare Workers Cache API type\ndeclare const caches: {\n default: Cache\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Types\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport interface AuthUser {\n id: string\n email?: string\n name?: string\n organizationId?: string\n roles?: string[]\n permissions?: string[]\n metadata?: Record<string, unknown>\n}\n\nexport interface AuthContext {\n user: AuthUser | null\n userId: string | null\n isAuth: boolean\n token: string | null\n}\n\n/**\n * Extended request type with auth context\n */\nexport interface AuthRequest extends Request {\n auth: AuthContext\n}\n\n/**\n * Environment bindings with auth context\n */\nexport interface AuthEnv {\n auth?: AuthContext\n [key: string]: unknown\n}\n\nexport interface AuthOptions {\n /** Cookie name for JWT token (default: 'auth') */\n cookieName?: string\n /** Header name for Bearer token (default: 'Authorization') */\n headerName?: string\n /** WorkOS Client ID (default: oauth.do client ID) */\n clientId?: string\n /** JWKS URI for token verification (default: WorkOS JWKS) */\n jwksUri?: string\n /** Skip auth for certain paths */\n skip?: (request: Request) => boolean\n /** Cache duration for JWKS in seconds (default: 3600) */\n jwksCacheTtl?: number\n}\n\nexport interface RequireAuthOptions extends AuthOptions {\n /** Redirect to login page instead of 401 */\n redirectTo?: string\n /** Required roles (any of) */\n roles?: string[]\n /** Required permissions (all of) */\n permissions?: string[]\n}\n\nexport interface ApiKeyOptions {\n /** Header name (default: 'X-API-Key') */\n headerName?: string\n /** Verify function - return user if valid, null if not */\n verify: (key: string, request: Request) => Promise<AuthUser | null>\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Constants\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst OAUTH_DO_CONFIG = {\n clientId: 'client_01JQYTRXK9ZPD8JPJTKDCRB656',\n jwksUri: 'https://api.workos.com/sso/jwks/client_01JQYTRXK9ZPD8JPJTKDCRB656',\n}\n\nconst TOKEN_CACHE_TTL = 5 * 60 // 5 minutes\nconst CACHE_URL_PREFIX = 'https://oauth.do/_cache/token/'\n\n// ═══════════════════════════════════════════════════════════════════════════\n// JWT Utilities\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Hash a token for cache key (avoids storing raw tokens in cache)\n */\nasync function hashToken(token: string): Promise<string> {\n const data = new TextEncoder().encode(token)\n const hashBuffer = await crypto.subtle.digest('SHA-256', data)\n return Array.from(new Uint8Array(hashBuffer))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * Get cached user from Cache API\n */\nasync function getCachedUser(token: string): Promise<AuthUser | null> {\n try {\n const cache = caches.default\n const hash = await hashToken(token)\n const cacheKey = new Request(`${CACHE_URL_PREFIX}${hash}`)\n const cached = await cache.match(cacheKey)\n\n if (!cached) return null\n\n const data = (await cached.json()) as { user: AuthUser; expiresAt: number }\n if (data.expiresAt < Date.now()) return null\n\n return data.user\n } catch {\n return null\n }\n}\n\n/**\n * Cache user in Cache API\n */\nasync function cacheUser(token: string, user: AuthUser): Promise<void> {\n try {\n const cache = caches.default\n const hash = await hashToken(token)\n const cacheKey = new Request(`${CACHE_URL_PREFIX}${hash}`)\n const data = { user, expiresAt: Date.now() + TOKEN_CACHE_TTL * 1000 }\n const response = new Response(JSON.stringify(data), {\n headers: { 'Cache-Control': `max-age=${TOKEN_CACHE_TTL}` },\n })\n await cache.put(cacheKey, response)\n } catch {\n // Cache failures are non-fatal\n }\n}\n\n/**\n * Parse cookies from request\n */\nfunction parseCookies(request: Request): Record<string, string> {\n const cookieHeader = request.headers.get('Cookie')\n if (!cookieHeader) return {}\n\n const cookies: Record<string, string> = {}\n for (const pair of cookieHeader.split(';')) {\n const [name, ...rest] = pair.trim().split('=')\n if (name && rest.length > 0) {\n cookies[name] = rest.join('=')\n }\n }\n return cookies\n}\n\n/**\n * Extract JWT from request (cookie or Bearer header)\n */\nfunction extractToken(request: Request, cookieName: string, headerName: string): string | null {\n // Try Bearer header first\n const authHeader = request.headers.get(headerName)\n if (authHeader?.startsWith('Bearer ')) {\n return authHeader.slice(7)\n }\n\n // Try cookie\n const cookies = parseCookies(request)\n const cookie = cookies[cookieName]\n if (cookie) return cookie\n\n return null\n}\n\n/**\n * Convert JWT payload to AuthUser\n */\nfunction payloadToUser(payload: JWTPayload): AuthUser {\n return {\n id: payload.sub || '',\n email: payload.email as string | undefined,\n name: payload.name as string | undefined,\n organizationId: payload.org_id as string | undefined,\n roles: payload.roles as string[] | undefined,\n permissions: payload.permissions as string[] | undefined,\n metadata: payload.metadata as Record<string, unknown> | undefined,\n }\n}\n\n// JWKS cache (module-level, persists across requests)\nlet jwksCache: jose.JWTVerifyGetKey | null = null\nlet jwksCacheExpiry = 0\n\n/**\n * Get JWKS verifier with caching\n */\nasync function getJwks(jwksUri: string, cacheTtl: number): Promise<jose.JWTVerifyGetKey> {\n const now = Date.now()\n if (jwksCache && jwksCacheExpiry > now) {\n return jwksCache\n }\n\n jwksCache = jose.createRemoteJWKSet(new URL(jwksUri))\n jwksCacheExpiry = now + cacheTtl * 1000\n return jwksCache\n}\n\n/**\n * Create default auth context\n */\nfunction createDefaultAuthContext(): AuthContext {\n return {\n user: null,\n userId: null,\n isAuth: false,\n token: null,\n }\n}\n\n/**\n * JSON error response helper\n */\nfunction jsonError(message: string, status: number): Response {\n return new Response(JSON.stringify({ error: message }), {\n status,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Middleware\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Optional auth middleware - populates request.auth if authenticated\n *\n * Does NOT reject unauthenticated requests. Use requireAuth() for that.\n *\n * @example\n * ```ts\n * import { Router } from 'itty-router'\n * import { optionalAuth } from 'oauth.do/itty'\n *\n * const router = Router()\n * router.all('*', optionalAuth())\n *\n * router.get('/api/me', (request) => {\n * if (!request.auth.user) {\n * return new Response(JSON.stringify({ error: 'Not authenticated' }), { status: 401 })\n * }\n * return new Response(JSON.stringify(request.auth.user))\n * })\n * ```\n */\nexport function optionalAuth(options: AuthOptions = {}) {\n const {\n cookieName = 'auth',\n headerName = 'Authorization',\n clientId = OAUTH_DO_CONFIG.clientId,\n jwksUri = OAUTH_DO_CONFIG.jwksUri,\n skip,\n jwksCacheTtl = 3600,\n } = options\n\n return async (request: Request): Promise<void> => {\n // Initialize auth context on request\n const authRequest = request as AuthRequest\n authRequest.auth = createDefaultAuthContext()\n\n // Skip if configured\n if (skip?.(request)) {\n return\n }\n\n const token = extractToken(request, cookieName, headerName)\n if (!token) {\n return\n }\n\n authRequest.auth.token = token\n\n // Check cache first\n const cached = await getCachedUser(token)\n if (cached) {\n authRequest.auth.user = cached\n authRequest.auth.userId = cached.id\n authRequest.auth.isAuth = true\n return\n }\n\n // Verify JWT\n try {\n const jwks = await getJwks(jwksUri, jwksCacheTtl)\n const { payload } = await jose.jwtVerify(token, jwks, {\n audience: clientId,\n })\n\n const user = payloadToUser(payload)\n authRequest.auth.user = user\n authRequest.auth.userId = user.id\n authRequest.auth.isAuth = true\n\n // Cache the result\n await cacheUser(token, user)\n } catch {\n // Invalid token - leave user as null\n }\n }\n}\n\n/**\n * Require auth middleware - rejects unauthenticated requests\n *\n * @example\n * ```ts\n * import { Router } from 'itty-router'\n * import { requireAuth } from 'oauth.do/itty'\n *\n * const router = Router()\n * router.get('/api/secret', requireAuth(), (request) => {\n * return new Response(JSON.stringify({ secret: 'data', user: request.auth.user }))\n * })\n * ```\n */\nexport function requireAuth(options: RequireAuthOptions = {}) {\n const { redirectTo, roles, permissions, ...authOptions } = options\n\n return async (request: Request): Promise<Response | void> => {\n const authRequest = request as AuthRequest\n\n // Run optional auth first if not already done\n if (!authRequest.auth) {\n await optionalAuth(authOptions)(request)\n }\n\n if (!authRequest.auth.isAuth || !authRequest.auth.user) {\n if (redirectTo) {\n return Response.redirect(redirectTo, 302)\n }\n return jsonError('Authentication required', 401)\n }\n\n // Check roles (any of)\n if (roles?.length) {\n const userRoles = authRequest.auth.user.roles || []\n const hasRole = roles.some((r) => userRoles.includes(r))\n if (!hasRole) {\n return jsonError('Insufficient permissions', 403)\n }\n }\n\n // Check permissions (all of)\n if (permissions?.length) {\n const userPerms = authRequest.auth.user.permissions || []\n const hasAllPerms = permissions.every((p) => userPerms.includes(p))\n if (!hasAllPerms) {\n return jsonError('Insufficient permissions', 403)\n }\n }\n\n // Continue to next handler (return undefined)\n }\n}\n\n/**\n * API key middleware - authenticates via API key header\n *\n * @example\n * ```ts\n * import { Router } from 'itty-router'\n * import { apiKey } from 'oauth.do/itty'\n *\n * const router = Router()\n * router.use('/api/*', apiKey({\n * verify: async (key, request) => {\n * // Verify key against your database/service\n * const user = await verifyApiKey(key)\n * return user\n * }\n * }))\n * ```\n */\nexport function apiKey(options: ApiKeyOptions) {\n const { headerName = 'X-API-Key', verify } = options\n\n return async (request: Request): Promise<Response | void> => {\n const authRequest = request as AuthRequest\n authRequest.auth = createDefaultAuthContext()\n\n const key = request.headers.get(headerName)\n if (!key) {\n return jsonError('API key required', 401)\n }\n\n const user = await verify(key, request)\n if (!user) {\n return jsonError('Invalid API key', 401)\n }\n\n authRequest.auth.user = user\n authRequest.auth.userId = user.id\n authRequest.auth.isAuth = true\n authRequest.auth.token = key\n }\n}\n\n/**\n * Combined auth middleware - tries JWT first, then API key\n *\n * @example\n * ```ts\n * import { Router } from 'itty-router'\n * import { combined } from 'oauth.do/itty'\n *\n * const router = Router()\n * router.all('/api/*', combined({\n * apiKey: {\n * verify: async (key) => verifyApiKey(key)\n * }\n * }))\n * ```\n */\nexport function combined(options: { auth?: AuthOptions; apiKey?: ApiKeyOptions }) {\n return async (request: Request): Promise<Response | void> => {\n const authRequest = request as AuthRequest\n\n // Try JWT auth first\n if (options.auth) {\n await optionalAuth(options.auth)(request)\n if (authRequest.auth?.isAuth) {\n return\n }\n }\n\n // Fall back to API key\n if (options.apiKey) {\n const key = request.headers.get(options.apiKey.headerName || 'X-API-Key')\n if (key) {\n const user = await options.apiKey.verify(key, request)\n if (user) {\n if (!authRequest.auth) {\n authRequest.auth = createDefaultAuthContext()\n }\n authRequest.auth.user = user\n authRequest.auth.userId = user.id\n authRequest.auth.isAuth = true\n authRequest.auth.token = key\n return\n }\n }\n }\n\n return jsonError('Authentication required', 401)\n }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Utility exports\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Helper to get auth context from request\n */\nexport function getAuth(request: Request): AuthContext {\n return (request as AuthRequest).auth || createDefaultAuthContext()\n}\n\n/**\n * Helper to check if request is authenticated\n */\nexport function isAuthenticated(request: Request): boolean {\n return (request as AuthRequest).auth?.isAuth === true\n}\n\n/**\n * Helper to get user from request\n */\nexport function getUser(request: Request): AuthUser | null {\n return (request as AuthRequest).auth?.user || null\n}\n"]}
package/dist/react.d.ts CHANGED
@@ -1,58 +1,34 @@
1
- import { User, Impersonator, AuthenticationMethod } from '@workos-inc/authkit-react';
2
- export { AuthenticationMethod, Impersonator, User } from '@workos-inc/authkit-react';
3
1
  import { ReactNode } from 'react';
2
+ import { AuthToken, AuthUser, Impersonator, OrganizationSwitcher as OrganizationSwitcher$1, TeamSwitcher as TeamSwitcher$1, UserMenu as UserMenu$1 } from '@mdxui/auth';
3
+ export { AuthToken, AuthUser, IdentityProviderProps, Impersonator } from '@mdxui/auth';
4
4
 
5
5
  /**
6
6
  * oauth.do/react - React components for authentication
7
7
  *
8
- * Wraps WorkOS AuthKit widgets with oauth.do configuration.
9
- * Pre-configured with oauth.do WorkOS client ID.
8
+ * Wraps @mdxui/auth with oauth.do configuration.
9
+ * Pre-configured with oauth.do WorkOS client ID and domain.
10
10
  *
11
11
  * @packageDocumentation
12
12
  */
13
13
 
14
- /**
15
- * Auth token can be a string or a function that returns a Promise<string>
16
- */
17
- type AuthToken = string | (() => Promise<string>);
18
-
19
- /**
20
- * Options for switching organization
21
- */
22
- interface SwitchToOrganizationOptions {
23
- organizationId: string;
24
- signInOpts?: {
25
- screenHint?: 'sign-in' | 'sign-up';
26
- loginHint?: string;
27
- };
28
- }
29
- /**
30
- * Auth state and methods returned by useAuth hook
31
- */
32
- interface AuthState {
33
- isLoading: boolean;
34
- user: User | null;
35
- role: string | null;
36
- roles: string[] | null;
37
- organizationId: string | null;
38
- permissions: string[];
39
- featureFlags: string[];
40
- impersonator: Impersonator | null;
41
- authenticationMethod: AuthenticationMethod | null;
42
- signIn: () => void;
43
- signUp: () => void;
44
- getUser: () => User | null;
45
- getAccessToken: () => Promise<string>;
46
- signOut: () => void;
47
- switchToOrganization: (options: SwitchToOrganizationOptions) => Promise<void>;
48
- getSignInUrl: () => Promise<string>;
49
- getSignUpUrl: () => Promise<string>;
50
- }
51
14
  interface OAuthDoContextValue {
52
15
  clientId: string;
53
16
  apiUrl: string;
54
17
  authKitDomain: string;
55
18
  }
19
+ /**
20
+ * Hook to access oauth.do-specific configuration
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * import { useOAuthDoConfig } from 'oauth.do/react'
25
+ *
26
+ * function MyComponent() {
27
+ * const { clientId, apiUrl, authKitDomain } = useOAuthDoConfig()
28
+ * // Use config values...
29
+ * }
30
+ * ```
31
+ */
56
32
  declare function useOAuthDoConfig(): OAuthDoContextValue;
57
33
  interface OAuthDoProviderProps {
58
34
  children: ReactNode;
@@ -66,6 +42,11 @@ interface OAuthDoProviderProps {
66
42
  /**
67
43
  * OAuth.do Provider - wraps your app with authentication context
68
44
  *
45
+ * Pre-configured with oauth.do defaults:
46
+ * - clientId: client_01JQYTRXK9ZPD8JPJTKDCRB656
47
+ * - authKitDomain: login.oauth.do
48
+ * - apiUrl: https://apis.do
49
+ *
69
50
  * @example
70
51
  * ```tsx
71
52
  * import { OAuthDoProvider } from 'oauth.do/react'
@@ -78,11 +59,56 @@ interface OAuthDoProviderProps {
78
59
  * )
79
60
  * }
80
61
  * ```
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * // With custom overrides
66
+ * <OAuthDoProvider
67
+ * clientId="custom-client-id"
68
+ * apiUrl="https://custom.api.do"
69
+ * >
70
+ * {children}
71
+ * </OAuthDoProvider>
72
+ * ```
81
73
  */
82
74
  declare function OAuthDoProvider({ children, clientId, apiUrl, authKitDomain, }: OAuthDoProviderProps): JSX.Element;
75
+ /**
76
+ * Options for switching organization
77
+ */
78
+ interface SwitchToOrganizationOptions {
79
+ organizationId: string;
80
+ signInOpts?: {
81
+ screenHint?: 'sign-in' | 'sign-up';
82
+ loginHint?: string;
83
+ };
84
+ }
85
+ /**
86
+ * Auth state and methods returned by useAuth hook
87
+ */
88
+ interface AuthState {
89
+ isLoading: boolean;
90
+ user: AuthUser | null;
91
+ role: string | null;
92
+ roles: string[] | null;
93
+ organizationId: string | null;
94
+ permissions: string[];
95
+ featureFlags: string[];
96
+ impersonator: Impersonator | null;
97
+ authenticationMethod: string | null;
98
+ signIn: () => void;
99
+ signUp: () => void;
100
+ getUser: () => AuthUser | null;
101
+ getAccessToken: () => Promise<string>;
102
+ signOut: () => void;
103
+ switchToOrganization: (options: SwitchToOrganizationOptions) => Promise<void>;
104
+ getSignInUrl: () => Promise<string>;
105
+ getSignUpUrl: () => Promise<string>;
106
+ }
83
107
  /**
84
108
  * useAuth hook - access current user and auth state
85
109
  *
110
+ * Re-exported from @mdxui/auth with AuthState typing.
111
+ *
86
112
  * @example
87
113
  * ```tsx
88
114
  * import { useAuth } from 'oauth.do/react'
@@ -168,6 +194,8 @@ interface SignInButtonProps {
168
194
  /**
169
195
  * Sign In Button - redirects to oauth.do login
170
196
  *
197
+ * Uses oauth.do-specific URL-based redirect for authentication.
198
+ *
171
199
  * @example
172
200
  * ```tsx
173
201
  * import { SignInButton } from 'oauth.do/react'
@@ -196,5 +224,71 @@ interface SignOutButtonProps {
196
224
  * ```
197
225
  */
198
226
  declare function SignOutButton({ children, className, redirectTo, }: SignOutButtonProps): JSX.Element;
227
+ /**
228
+ * UserMenu - A customizable user menu component
229
+ *
230
+ * Re-exported from @mdxui/auth. Displays user info and provides sign-out functionality.
231
+ *
232
+ * @example
233
+ * ```tsx
234
+ * import { UserMenu } from 'oauth.do/react'
235
+ *
236
+ * function Header() {
237
+ * return (
238
+ * <UserMenu
239
+ * renderTrigger={({ user, initials }) => (
240
+ * <button>{user.firstName}</button>
241
+ * )}
242
+ * renderMenu={({ signOut }) => (
243
+ * <button onClick={signOut}>Sign Out</button>
244
+ * )}
245
+ * />
246
+ * )
247
+ * }
248
+ * ```
249
+ */
250
+ declare const UserMenu: typeof UserMenu$1;
251
+ /**
252
+ * TeamSwitcher - Organization switching component
253
+ *
254
+ * Re-exported from @mdxui/auth. Shows WorkOS OrganizationSwitcher widget.
255
+ *
256
+ * @example
257
+ * ```tsx
258
+ * import { TeamSwitcher } from 'oauth.do/react'
259
+ *
260
+ * function Sidebar() {
261
+ * return <TeamSwitcher className="my-team-switcher" />
262
+ * }
263
+ * ```
264
+ */
265
+ declare const TeamSwitcher: typeof TeamSwitcher$1;
266
+ /**
267
+ * OrganizationSwitcher - Lower-level organization switcher widget
268
+ *
269
+ * Re-exported from @mdxui/auth. Use with useAuth() for full control.
270
+ *
271
+ * @example
272
+ * ```tsx
273
+ * import { OrganizationSwitcher, useAuth } from 'oauth.do/react'
274
+ *
275
+ * function OrgSwitcher() {
276
+ * const { getAccessToken, switchToOrganization } = useAuth()
277
+ *
278
+ * return (
279
+ * <OrganizationSwitcher
280
+ * authToken={getAccessToken}
281
+ * switchToOrganization={({ organizationId }) =>
282
+ * switchToOrganization({ organizationId })
283
+ * }
284
+ * />
285
+ * )
286
+ * }
287
+ * ```
288
+ */
289
+ declare const OrganizationSwitcher: typeof OrganizationSwitcher$1;
290
+
291
+ type User = AuthUser;
292
+ type AuthenticationMethod = string | null;
199
293
 
200
- export { ApiKeys, type ApiKeysProps, type AuthState, type AuthToken, OAuthDoProvider, type OAuthDoProviderProps, SignInButton, type SignInButtonProps, SignOutButton, type SignOutButtonProps, type SwitchToOrganizationOptions, UserProfile, type UserProfileProps, UsersManagement, type UsersManagementProps, useAuth, useOAuthDoConfig };
294
+ export { ApiKeys, type ApiKeysProps, type AuthState, type AuthenticationMethod, OAuthDoProvider, type OAuthDoProviderProps, OrganizationSwitcher, SignInButton, type SignInButtonProps, SignOutButton, type SignOutButtonProps, type SwitchToOrganizationOptions, TeamSwitcher, type User, UserMenu, UserProfile, type UserProfileProps, UsersManagement, type UsersManagementProps, useAuth, useOAuthDoConfig };
package/dist/react.js CHANGED
@@ -1,6 +1,5 @@
1
- import { WorkOsWidgets, ApiKeys as ApiKeys$1, UsersManagement as UsersManagement$1, UserProfile as UserProfile$1 } from '@workos-inc/widgets';
2
- import { AuthKitProvider, useAuth as useAuth$1 } from '@workos-inc/authkit-react';
3
1
  import React, { createContext, useContext } from 'react';
2
+ import { OrganizationSwitcher as OrganizationSwitcher$1, TeamSwitcher as TeamSwitcher$1, UserMenu as UserMenu$1, IdentityProvider, useAuth as useAuth$1, ApiKeys as ApiKeys$1, UsersManagement as UsersManagement$1, UserProfile as UserProfile$1 } from '@mdxui/auth';
4
3
 
5
4
  var OAUTH_DO_CONFIG = {
6
5
  clientId: "client_01JQYTRXK9ZPD8JPJTKDCRB656",
@@ -18,7 +17,7 @@ function OAuthDoProvider({
18
17
  authKitDomain = OAUTH_DO_CONFIG.authKitDomain
19
18
  }) {
20
19
  const config = { clientId, apiUrl, authKitDomain };
21
- return /* @__PURE__ */ React.createElement(OAuthDoContext.Provider, { value: config }, /* @__PURE__ */ React.createElement(AuthKitProvider, { clientId }, /* @__PURE__ */ React.createElement(WorkOsWidgets, null, children)));
20
+ return /* @__PURE__ */ React.createElement(OAuthDoContext.Provider, { value: config }, /* @__PURE__ */ React.createElement(IdentityProvider, { clientId, apiHostname: authKitDomain }, children));
22
21
  }
23
22
  function useAuth() {
24
23
  return useAuth$1();
@@ -61,7 +60,10 @@ function SignOutButton({
61
60
  };
62
61
  return /* @__PURE__ */ React.createElement("button", { onClick: handleClick, className }, children);
63
62
  }
63
+ var UserMenu = UserMenu$1;
64
+ var TeamSwitcher = TeamSwitcher$1;
65
+ var OrganizationSwitcher = OrganizationSwitcher$1;
64
66
 
65
- export { ApiKeys, OAuthDoProvider, SignInButton, SignOutButton, UserProfile, UsersManagement, useAuth, useOAuthDoConfig };
67
+ export { ApiKeys, OAuthDoProvider, OrganizationSwitcher, SignInButton, SignOutButton, TeamSwitcher, UserMenu, UserProfile, UsersManagement, useAuth, useOAuthDoConfig };
66
68
  //# sourceMappingURL=react.js.map
67
69
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.tsx"],"names":["WorkOSAuthKitProvider","useWorkOSAuth","WorkOSApiKeys","WorkOSUsersManagement","WorkOSUserProfile"],"mappings":"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","file":"react.js","sourcesContent":["/**\n * oauth.do/react - React components for authentication\n *\n * Wraps WorkOS AuthKit widgets with oauth.do configuration.\n * Pre-configured with oauth.do WorkOS client ID.\n *\n * @packageDocumentation\n */\n\n'use client'\n\nimport {\n WorkOsWidgets,\n ApiKeys as WorkOSApiKeys,\n UsersManagement as WorkOSUsersManagement,\n UserProfile as WorkOSUserProfile\n} from '@workos-inc/widgets'\nimport {\n AuthKitProvider as WorkOSAuthKitProvider,\n useAuth as useWorkOSAuth,\n type Impersonator,\n type User,\n type AuthenticationMethod\n} from '@workos-inc/authkit-react'\n\n/**\n * Auth token can be a string or a function that returns a Promise<string>\n */\nexport type AuthToken = string | (() => Promise<string>)\nimport React, { createContext, useContext, type ReactNode } from 'react'\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Auth Types (re-exported from authkit-react context)\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Options for switching organization\n */\nexport interface SwitchToOrganizationOptions {\n organizationId: string\n signInOpts?: {\n screenHint?: 'sign-in' | 'sign-up'\n loginHint?: string\n }\n}\n\n/**\n * Auth state and methods returned by useAuth hook\n */\nexport interface AuthState {\n isLoading: boolean\n user: User | null\n role: string | null\n roles: string[] | null\n organizationId: string | null\n permissions: string[]\n featureFlags: string[]\n impersonator: Impersonator | null\n authenticationMethod: AuthenticationMethod | null\n signIn: () => void\n signUp: () => void\n getUser: () => User | null\n getAccessToken: () => Promise<string>\n signOut: () => void\n switchToOrganization: (options: SwitchToOrganizationOptions) => Promise<void>\n getSignInUrl: () => Promise<string>\n getSignUpUrl: () => Promise<string>\n}\n\n// oauth.do default configuration\nconst OAUTH_DO_CONFIG = {\n clientId: 'client_01JQYTRXK9ZPD8JPJTKDCRB656',\n apiUrl: 'https://apis.do',\n authKitDomain: 'login.oauth.do',\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Context\n// ═══════════════════════════════════════════════════════════════════════════\n\ninterface OAuthDoContextValue {\n clientId: string\n apiUrl: string\n authKitDomain: string\n}\n\nconst OAuthDoContext = createContext<OAuthDoContextValue>(OAUTH_DO_CONFIG)\n\nexport function useOAuthDoConfig(): OAuthDoContextValue {\n return useContext(OAuthDoContext)\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Provider\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport interface OAuthDoProviderProps {\n children: ReactNode\n /** Override the default client ID */\n clientId?: string\n /** Override the API URL */\n apiUrl?: string\n /** Override the AuthKit domain */\n authKitDomain?: string\n}\n\n/**\n * OAuth.do Provider - wraps your app with authentication context\n *\n * @example\n * ```tsx\n * import { OAuthDoProvider } from 'oauth.do/react'\n *\n * export default function App({ children }) {\n * return (\n * <OAuthDoProvider>\n * {children}\n * </OAuthDoProvider>\n * )\n * }\n * ```\n */\nexport function OAuthDoProvider({\n children,\n clientId = OAUTH_DO_CONFIG.clientId,\n apiUrl = OAUTH_DO_CONFIG.apiUrl,\n authKitDomain = OAUTH_DO_CONFIG.authKitDomain,\n}: OAuthDoProviderProps): JSX.Element {\n const config = { clientId, apiUrl, authKitDomain }\n\n return (\n <OAuthDoContext.Provider value={config}>\n <WorkOSAuthKitProvider clientId={clientId}>\n <WorkOsWidgets>\n {children}\n </WorkOsWidgets>\n </WorkOSAuthKitProvider>\n </OAuthDoContext.Provider>\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Hooks\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * useAuth hook - access current user and auth state\n *\n * @example\n * ```tsx\n * import { useAuth } from 'oauth.do/react'\n *\n * function UserGreeting() {\n * const { user, isLoading } = useAuth()\n *\n * if (isLoading) return <span>Loading...</span>\n * if (!user) return <span>Please sign in</span>\n *\n * return <span>Hello, {user.firstName}!</span>\n * }\n * ```\n */\nexport function useAuth(): AuthState {\n return useWorkOSAuth() as AuthState\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Widgets\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport interface ApiKeysProps {\n /** Auth token for the widget (from useAuth().getAccessToken or server-generated) */\n authToken: AuthToken\n}\n\n/**\n * API Keys Widget - manage API keys for your organization\n *\n * Requires the `widgets:api-keys:manage` permission.\n *\n * @example\n * ```tsx\n * import { ApiKeys, useAuth } from 'oauth.do/react'\n *\n * function ApiKeysPage() {\n * const { user, getAccessToken } = useAuth()\n * if (!user) return <p>Please sign in</p>\n *\n * return <ApiKeys authToken={getAccessToken} />\n * }\n * ```\n */\nexport function ApiKeys({ authToken }: ApiKeysProps): JSX.Element {\n return <WorkOSApiKeys authToken={authToken} />\n}\n\nexport interface UsersManagementProps {\n /** Auth token for the widget */\n authToken: AuthToken\n}\n\n/**\n * Users Management Widget - invite, remove, and manage users\n *\n * @example\n * ```tsx\n * import { UsersManagement, useAuth } from 'oauth.do/react'\n *\n * function UsersPage() {\n * const { user, getAccessToken } = useAuth()\n * if (!user) return <p>Please sign in</p>\n *\n * return <UsersManagement authToken={getAccessToken} />\n * }\n * ```\n */\nexport function UsersManagement({ authToken }: UsersManagementProps): JSX.Element {\n return <WorkOSUsersManagement authToken={authToken} />\n}\n\nexport interface UserProfileProps {\n /** Auth token for the widget */\n authToken: AuthToken\n}\n\n/**\n * User Profile Widget - view and edit user profile\n *\n * @example\n * ```tsx\n * import { UserProfile, useAuth } from 'oauth.do/react'\n *\n * function ProfilePage() {\n * const { user, getAccessToken } = useAuth()\n * if (!user) return <p>Please sign in</p>\n *\n * return <UserProfile authToken={getAccessToken} />\n * }\n * ```\n */\nexport function UserProfile({ authToken }: UserProfileProps): JSX.Element {\n return <WorkOSUserProfile authToken={authToken} />\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Login Components\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport interface SignInButtonProps {\n children?: ReactNode\n className?: string\n redirectTo?: string\n}\n\n/**\n * Sign In Button - redirects to oauth.do login\n *\n * @example\n * ```tsx\n * import { SignInButton } from 'oauth.do/react'\n *\n * function Header() {\n * return <SignInButton>Sign In</SignInButton>\n * }\n * ```\n */\nexport function SignInButton({\n children = 'Sign In',\n className,\n redirectTo = typeof window !== 'undefined' ? window.location.href : '/',\n}: SignInButtonProps): JSX.Element {\n const { authKitDomain, clientId } = useOAuthDoConfig()\n\n const handleClick = () => {\n const url = new URL(`https://${authKitDomain}`)\n url.searchParams.set('client_id', clientId)\n url.searchParams.set('redirect_uri', redirectTo)\n url.searchParams.set('response_type', 'code')\n window.location.href = url.toString()\n }\n\n return (\n <button onClick={handleClick} className={className}>\n {children}\n </button>\n )\n}\n\nexport interface SignOutButtonProps {\n children?: ReactNode\n className?: string\n redirectTo?: string\n}\n\n/**\n * Sign Out Button - clears auth state and optionally redirects\n *\n * @example\n * ```tsx\n * import { SignOutButton } from 'oauth.do/react'\n *\n * function Header() {\n * return <SignOutButton>Sign Out</SignOutButton>\n * }\n * ```\n */\nexport function SignOutButton({\n children = 'Sign Out',\n className,\n redirectTo = '/',\n}: SignOutButtonProps): JSX.Element {\n const { signOut } = useAuth()\n\n const handleClick = () => {\n signOut()\n // Redirect after signOut if a custom redirectTo is provided\n if (redirectTo !== '/' && typeof window !== 'undefined') {\n window.location.href = redirectTo\n }\n }\n\n return (\n <button onClick={handleClick} className={className}>\n {children}\n </button>\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Re-exports\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport type { User, Impersonator, AuthenticationMethod }\n"]}
1
+ {"version":3,"sources":["../src/react.tsx"],"names":["useMdxuiAuth","MdxuiApiKeys","MdxuiUsersManagement","MdxuiUserProfile","MdxuiUserMenu","MdxuiTeamSwitcher","MdxuiOrganizationSwitcher"],"mappings":"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","file":"react.js","sourcesContent":["/**\n * oauth.do/react - React components for authentication\n *\n * Wraps @mdxui/auth with oauth.do configuration.\n * Pre-configured with oauth.do WorkOS client ID and domain.\n *\n * @packageDocumentation\n */\n\n'use client'\n\nimport React, { createContext, useContext, type ReactNode } from 'react'\n\n// Import from @mdxui/auth instead of direct WorkOS packages\nimport {\n IdentityProvider,\n useAuth as useMdxuiAuth,\n SignInButton as MdxuiSignInButton,\n SignOutButton as MdxuiSignOutButton,\n ApiKeys as MdxuiApiKeys,\n UsersManagement as MdxuiUsersManagement,\n UserProfile as MdxuiUserProfile,\n UserMenu as MdxuiUserMenu,\n TeamSwitcher as MdxuiTeamSwitcher,\n OrganizationSwitcher as MdxuiOrganizationSwitcher,\n type AuthToken,\n type AuthUser,\n type Impersonator,\n type IdentityProviderProps,\n} from '@mdxui/auth'\n\n// ===============================================================================\n// oauth.do default configuration\n// ===============================================================================\n\nconst OAUTH_DO_CONFIG = {\n clientId: 'client_01JQYTRXK9ZPD8JPJTKDCRB656',\n apiUrl: 'https://apis.do',\n authKitDomain: 'login.oauth.do',\n}\n\n// ===============================================================================\n// Context for oauth.do-specific config\n// ===============================================================================\n\ninterface OAuthDoContextValue {\n clientId: string\n apiUrl: string\n authKitDomain: string\n}\n\nconst OAuthDoContext = createContext<OAuthDoContextValue>(OAUTH_DO_CONFIG)\n\n/**\n * Hook to access oauth.do-specific configuration\n *\n * @example\n * ```tsx\n * import { useOAuthDoConfig } from 'oauth.do/react'\n *\n * function MyComponent() {\n * const { clientId, apiUrl, authKitDomain } = useOAuthDoConfig()\n * // Use config values...\n * }\n * ```\n */\nexport function useOAuthDoConfig(): OAuthDoContextValue {\n return useContext(OAuthDoContext)\n}\n\n// ===============================================================================\n// Provider\n// ===============================================================================\n\nexport interface OAuthDoProviderProps {\n children: ReactNode\n /** Override the default client ID */\n clientId?: string\n /** Override the API URL */\n apiUrl?: string\n /** Override the AuthKit domain */\n authKitDomain?: string\n}\n\n/**\n * OAuth.do Provider - wraps your app with authentication context\n *\n * Pre-configured with oauth.do defaults:\n * - clientId: client_01JQYTRXK9ZPD8JPJTKDCRB656\n * - authKitDomain: login.oauth.do\n * - apiUrl: https://apis.do\n *\n * @example\n * ```tsx\n * import { OAuthDoProvider } from 'oauth.do/react'\n *\n * export default function App({ children }) {\n * return (\n * <OAuthDoProvider>\n * {children}\n * </OAuthDoProvider>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With custom overrides\n * <OAuthDoProvider\n * clientId=\"custom-client-id\"\n * apiUrl=\"https://custom.api.do\"\n * >\n * {children}\n * </OAuthDoProvider>\n * ```\n */\nexport function OAuthDoProvider({\n children,\n clientId = OAUTH_DO_CONFIG.clientId,\n apiUrl = OAUTH_DO_CONFIG.apiUrl,\n authKitDomain = OAUTH_DO_CONFIG.authKitDomain,\n}: OAuthDoProviderProps): JSX.Element {\n const config = { clientId, apiUrl, authKitDomain }\n\n return (\n <OAuthDoContext.Provider value={config}>\n <IdentityProvider clientId={clientId} apiHostname={authKitDomain}>\n {children}\n </IdentityProvider>\n </OAuthDoContext.Provider>\n )\n}\n\n// ===============================================================================\n// Re-exported Auth Types\n// ===============================================================================\n\n/**\n * Options for switching organization\n */\nexport interface SwitchToOrganizationOptions {\n organizationId: string\n signInOpts?: {\n screenHint?: 'sign-in' | 'sign-up'\n loginHint?: string\n }\n}\n\n/**\n * Auth state and methods returned by useAuth hook\n */\nexport interface AuthState {\n isLoading: boolean\n user: AuthUser | null\n role: string | null\n roles: string[] | null\n organizationId: string | null\n permissions: string[]\n featureFlags: string[]\n impersonator: Impersonator | null\n authenticationMethod: string | null\n signIn: () => void\n signUp: () => void\n getUser: () => AuthUser | null\n getAccessToken: () => Promise<string>\n signOut: () => void\n switchToOrganization: (options: SwitchToOrganizationOptions) => Promise<void>\n getSignInUrl: () => Promise<string>\n getSignUpUrl: () => Promise<string>\n}\n\n// ===============================================================================\n// Hooks\n// ===============================================================================\n\n/**\n * useAuth hook - access current user and auth state\n *\n * Re-exported from @mdxui/auth with AuthState typing.\n *\n * @example\n * ```tsx\n * import { useAuth } from 'oauth.do/react'\n *\n * function UserGreeting() {\n * const { user, isLoading } = useAuth()\n *\n * if (isLoading) return <span>Loading...</span>\n * if (!user) return <span>Please sign in</span>\n *\n * return <span>Hello, {user.firstName}!</span>\n * }\n * ```\n */\nexport function useAuth(): AuthState {\n return useMdxuiAuth() as AuthState\n}\n\n// ===============================================================================\n// Widgets - Re-exported from @mdxui/auth\n// ===============================================================================\n\nexport interface ApiKeysProps {\n /** Auth token for the widget (from useAuth().getAccessToken or server-generated) */\n authToken: AuthToken\n}\n\n/**\n * API Keys Widget - manage API keys for your organization\n *\n * Requires the `widgets:api-keys:manage` permission.\n *\n * @example\n * ```tsx\n * import { ApiKeys, useAuth } from 'oauth.do/react'\n *\n * function ApiKeysPage() {\n * const { user, getAccessToken } = useAuth()\n * if (!user) return <p>Please sign in</p>\n *\n * return <ApiKeys authToken={getAccessToken} />\n * }\n * ```\n */\nexport function ApiKeys({ authToken }: ApiKeysProps): JSX.Element {\n return <MdxuiApiKeys authToken={authToken} />\n}\n\nexport interface UsersManagementProps {\n /** Auth token for the widget */\n authToken: AuthToken\n}\n\n/**\n * Users Management Widget - invite, remove, and manage users\n *\n * @example\n * ```tsx\n * import { UsersManagement, useAuth } from 'oauth.do/react'\n *\n * function UsersPage() {\n * const { user, getAccessToken } = useAuth()\n * if (!user) return <p>Please sign in</p>\n *\n * return <UsersManagement authToken={getAccessToken} />\n * }\n * ```\n */\nexport function UsersManagement({ authToken }: UsersManagementProps): JSX.Element {\n return <MdxuiUsersManagement authToken={authToken} />\n}\n\nexport interface UserProfileProps {\n /** Auth token for the widget */\n authToken: AuthToken\n}\n\n/**\n * User Profile Widget - view and edit user profile\n *\n * @example\n * ```tsx\n * import { UserProfile, useAuth } from 'oauth.do/react'\n *\n * function ProfilePage() {\n * const { user, getAccessToken } = useAuth()\n * if (!user) return <p>Please sign in</p>\n *\n * return <UserProfile authToken={getAccessToken} />\n * }\n * ```\n */\nexport function UserProfile({ authToken }: UserProfileProps): JSX.Element {\n return <MdxuiUserProfile authToken={authToken} />\n}\n\n// ===============================================================================\n// Login Components - oauth.do specific with URL-based redirect\n// ===============================================================================\n\nexport interface SignInButtonProps {\n children?: ReactNode\n className?: string\n redirectTo?: string\n}\n\n/**\n * Sign In Button - redirects to oauth.do login\n *\n * Uses oauth.do-specific URL-based redirect for authentication.\n *\n * @example\n * ```tsx\n * import { SignInButton } from 'oauth.do/react'\n *\n * function Header() {\n * return <SignInButton>Sign In</SignInButton>\n * }\n * ```\n */\nexport function SignInButton({\n children = 'Sign In',\n className,\n redirectTo = typeof window !== 'undefined' ? window.location.href : '/',\n}: SignInButtonProps): JSX.Element {\n const { authKitDomain, clientId } = useOAuthDoConfig()\n\n const handleClick = () => {\n const url = new URL(`https://${authKitDomain}`)\n url.searchParams.set('client_id', clientId)\n url.searchParams.set('redirect_uri', redirectTo)\n url.searchParams.set('response_type', 'code')\n window.location.href = url.toString()\n }\n\n return (\n <button onClick={handleClick} className={className}>\n {children}\n </button>\n )\n}\n\nexport interface SignOutButtonProps {\n children?: ReactNode\n className?: string\n redirectTo?: string\n}\n\n/**\n * Sign Out Button - clears auth state and optionally redirects\n *\n * @example\n * ```tsx\n * import { SignOutButton } from 'oauth.do/react'\n *\n * function Header() {\n * return <SignOutButton>Sign Out</SignOutButton>\n * }\n * ```\n */\nexport function SignOutButton({\n children = 'Sign Out',\n className,\n redirectTo = '/',\n}: SignOutButtonProps): JSX.Element {\n const { signOut } = useAuth()\n\n const handleClick = () => {\n signOut()\n // Redirect after signOut if a custom redirectTo is provided\n if (redirectTo !== '/' && typeof window !== 'undefined') {\n window.location.href = redirectTo\n }\n }\n\n return (\n <button onClick={handleClick} className={className}>\n {children}\n </button>\n )\n}\n\n// ===============================================================================\n// New Components - Re-exported from @mdxui/auth\n// ===============================================================================\n\n/**\n * UserMenu - A customizable user menu component\n *\n * Re-exported from @mdxui/auth. Displays user info and provides sign-out functionality.\n *\n * @example\n * ```tsx\n * import { UserMenu } from 'oauth.do/react'\n *\n * function Header() {\n * return (\n * <UserMenu\n * renderTrigger={({ user, initials }) => (\n * <button>{user.firstName}</button>\n * )}\n * renderMenu={({ signOut }) => (\n * <button onClick={signOut}>Sign Out</button>\n * )}\n * />\n * )\n * }\n * ```\n */\nexport const UserMenu = MdxuiUserMenu\n\n/**\n * TeamSwitcher - Organization switching component\n *\n * Re-exported from @mdxui/auth. Shows WorkOS OrganizationSwitcher widget.\n *\n * @example\n * ```tsx\n * import { TeamSwitcher } from 'oauth.do/react'\n *\n * function Sidebar() {\n * return <TeamSwitcher className=\"my-team-switcher\" />\n * }\n * ```\n */\nexport const TeamSwitcher = MdxuiTeamSwitcher\n\n/**\n * OrganizationSwitcher - Lower-level organization switcher widget\n *\n * Re-exported from @mdxui/auth. Use with useAuth() for full control.\n *\n * @example\n * ```tsx\n * import { OrganizationSwitcher, useAuth } from 'oauth.do/react'\n *\n * function OrgSwitcher() {\n * const { getAccessToken, switchToOrganization } = useAuth()\n *\n * return (\n * <OrganizationSwitcher\n * authToken={getAccessToken}\n * switchToOrganization={({ organizationId }) =>\n * switchToOrganization({ organizationId })\n * }\n * />\n * )\n * }\n * ```\n */\nexport const OrganizationSwitcher = MdxuiOrganizationSwitcher\n\n// ===============================================================================\n// Type Re-exports\n// ===============================================================================\n\nexport type { AuthToken, AuthUser, Impersonator, IdentityProviderProps }\n\n// Re-export User as alias for AuthUser for backward compatibility\nexport type User = AuthUser\n\n// Re-export AuthenticationMethod type\nexport type AuthenticationMethod = string | null\n"]}