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/README.md +6 -0
- package/dist/cli.js +13 -27
- package/dist/cli.js.map +1 -1
- package/dist/itty.d.ts +154 -0
- package/dist/itty.js +229 -0
- package/dist/itty.js.map +1 -0
- package/dist/react.d.ts +136 -42
- package/dist/react.js +6 -4
- package/dist/react.js.map +1 -1
- package/package.json +21 -36
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
|
package/dist/itty.js.map
ADDED
|
@@ -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
|
|
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
|
|
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(
|
|
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"]}
|