@drmhse/authos-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,530 @@
1
+ import { createContext, useRef, useState, useCallback, useEffect, useMemo, useContext } from 'react';
2
+ import { SsoClient, SsoApiError } from '@drmhse/sso-sdk';
3
+ export { AuthErrorCodes, SsoApiError, SsoClient } from '@drmhse/sso-sdk';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ // src/context.tsx
7
+ var AuthOSContext = createContext(null);
8
+ function AuthOSProvider({ config, children, client: externalClient }) {
9
+ const clientRef = useRef(null);
10
+ if (!clientRef.current) {
11
+ clientRef.current = externalClient ?? new SsoClient(config);
12
+ }
13
+ const client = clientRef.current;
14
+ const [user, setUser] = useState(null);
15
+ const [organization, setOrganization] = useState(null);
16
+ const [isLoading, setIsLoading] = useState(true);
17
+ const refreshUser = useCallback(async () => {
18
+ try {
19
+ const profile = await client.user.getProfile();
20
+ setUser(profile);
21
+ } catch {
22
+ setUser(null);
23
+ }
24
+ }, [client]);
25
+ useEffect(() => {
26
+ const unsubscribe = client.onAuthStateChange(async (isAuthenticated) => {
27
+ if (isAuthenticated) {
28
+ try {
29
+ const profile = await client.user.getProfile();
30
+ setUser(profile);
31
+ } catch {
32
+ setUser(null);
33
+ }
34
+ } else {
35
+ setUser(null);
36
+ setOrganization(null);
37
+ }
38
+ setIsLoading(false);
39
+ });
40
+ return unsubscribe;
41
+ }, [client]);
42
+ const contextValue = useMemo(
43
+ () => ({
44
+ client,
45
+ user,
46
+ isAuthenticated: !!user,
47
+ isLoading,
48
+ organization,
49
+ setUser,
50
+ setOrganization,
51
+ refreshUser
52
+ }),
53
+ [client, user, isLoading, organization, refreshUser]
54
+ );
55
+ return /* @__PURE__ */ jsx(AuthOSContext.Provider, { value: contextValue, children });
56
+ }
57
+ function useAuthOSContext() {
58
+ const context = useContext(AuthOSContext);
59
+ if (!context) {
60
+ throw new Error("useAuthOSContext must be used within an AuthOSProvider");
61
+ }
62
+ return context;
63
+ }
64
+
65
+ // src/hooks/useAuthOS.ts
66
+ function useAuthOS() {
67
+ const { client, isLoading, isAuthenticated } = useAuthOSContext();
68
+ return { client, isLoading, isAuthenticated };
69
+ }
70
+
71
+ // src/hooks/useUser.ts
72
+ function useUser() {
73
+ const { user } = useAuthOSContext();
74
+ return user;
75
+ }
76
+ function useOrganization() {
77
+ const { client, organization, setOrganization, refreshUser } = useAuthOSContext();
78
+ const switchOrganization = useCallback(
79
+ async (slug) => {
80
+ const orgResponse = await client.organizations.get(slug);
81
+ setOrganization(orgResponse.organization);
82
+ await refreshUser();
83
+ },
84
+ [client, setOrganization, refreshUser]
85
+ );
86
+ return { organization, switchOrganization };
87
+ }
88
+ function usePermission(permission) {
89
+ const { user } = useAuthOSContext();
90
+ return useMemo(() => {
91
+ if (!user?.permissions) return false;
92
+ return user.permissions.includes(permission);
93
+ }, [user?.permissions, permission]);
94
+ }
95
+ function useAnyPermission(permissions) {
96
+ const { user } = useAuthOSContext();
97
+ return useMemo(() => {
98
+ if (!user?.permissions) return false;
99
+ return permissions.some((perm) => user.permissions.includes(perm));
100
+ }, [user?.permissions, permissions]);
101
+ }
102
+ function useAllPermissions(permissions) {
103
+ const { user } = useAuthOSContext();
104
+ return useMemo(() => {
105
+ if (!user?.permissions) return false;
106
+ return permissions.every((perm) => user.permissions.includes(perm));
107
+ }, [user?.permissions, permissions]);
108
+ }
109
+ var MFA_PREAUTH_EXPIRY = 300;
110
+ function SignIn({
111
+ onSuccess,
112
+ onError,
113
+ showForgotPassword = true,
114
+ showSignUp = true,
115
+ className
116
+ }) {
117
+ const { client, setUser } = useAuthOSContext();
118
+ const [state, setState] = useState("credentials");
119
+ const [email, setEmail] = useState("");
120
+ const [password, setPassword] = useState("");
121
+ const [mfaCode, setMfaCode] = useState("");
122
+ const [preauthToken, setPreauthToken] = useState("");
123
+ const [error, setError] = useState(null);
124
+ const [isLoading, setIsLoading] = useState(false);
125
+ const handleCredentialsSubmit = useCallback(
126
+ async (e) => {
127
+ e.preventDefault();
128
+ setError(null);
129
+ setIsLoading(true);
130
+ try {
131
+ const result = await client.auth.login({ email, password });
132
+ if (result.expires_in === MFA_PREAUTH_EXPIRY) {
133
+ setPreauthToken(result.access_token);
134
+ setState("mfa");
135
+ } else {
136
+ const profile = await client.user.getProfile();
137
+ setUser(profile);
138
+ onSuccess?.(profile);
139
+ }
140
+ } catch (err) {
141
+ const message = err instanceof SsoApiError ? err.message : "Login failed";
142
+ setError(message);
143
+ onError?.(err instanceof Error ? err : new Error(message));
144
+ } finally {
145
+ setIsLoading(false);
146
+ }
147
+ },
148
+ [client, email, password, setUser, onSuccess, onError]
149
+ );
150
+ const handleMfaSubmit = useCallback(
151
+ async (e) => {
152
+ e.preventDefault();
153
+ setError(null);
154
+ setIsLoading(true);
155
+ try {
156
+ await client.auth.verifyMfa(preauthToken, mfaCode);
157
+ const profile = await client.user.getProfile();
158
+ setUser(profile);
159
+ onSuccess?.(profile);
160
+ } catch (err) {
161
+ const message = err instanceof SsoApiError ? err.message : "Invalid MFA code";
162
+ setError(message);
163
+ onError?.(err instanceof Error ? err : new Error(message));
164
+ } finally {
165
+ setIsLoading(false);
166
+ }
167
+ },
168
+ [client, preauthToken, mfaCode, setUser, onSuccess, onError]
169
+ );
170
+ const handleBackToCredentials = useCallback(() => {
171
+ setState("credentials");
172
+ setMfaCode("");
173
+ setPreauthToken("");
174
+ setError(null);
175
+ }, []);
176
+ if (state === "mfa") {
177
+ return /* @__PURE__ */ jsx("div", { className, "data-authos-signin": "", "data-state": "mfa", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleMfaSubmit, children: [
178
+ /* @__PURE__ */ jsxs("div", { "data-authos-field": "mfa-code", children: [
179
+ /* @__PURE__ */ jsx("label", { htmlFor: "authos-mfa-code", children: "Verification Code" }),
180
+ /* @__PURE__ */ jsx(
181
+ "input",
182
+ {
183
+ id: "authos-mfa-code",
184
+ type: "text",
185
+ inputMode: "numeric",
186
+ autoComplete: "one-time-code",
187
+ value: mfaCode,
188
+ onChange: (e) => setMfaCode(e.target.value),
189
+ placeholder: "Enter 6-digit code",
190
+ required: true,
191
+ disabled: isLoading
192
+ }
193
+ )
194
+ ] }),
195
+ error && /* @__PURE__ */ jsx("div", { "data-authos-error": true, children: error }),
196
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: isLoading, "data-authos-submit": "", children: isLoading ? "Verifying..." : "Verify" }),
197
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: handleBackToCredentials, "data-authos-back": "", children: "Back to login" })
198
+ ] }) });
199
+ }
200
+ return /* @__PURE__ */ jsx("div", { className, "data-authos-signin": "", "data-state": "credentials", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleCredentialsSubmit, children: [
201
+ /* @__PURE__ */ jsxs("div", { "data-authos-field": "email", children: [
202
+ /* @__PURE__ */ jsx("label", { htmlFor: "authos-email", children: "Email" }),
203
+ /* @__PURE__ */ jsx(
204
+ "input",
205
+ {
206
+ id: "authos-email",
207
+ type: "email",
208
+ autoComplete: "email",
209
+ value: email,
210
+ onChange: (e) => setEmail(e.target.value),
211
+ placeholder: "Enter your email",
212
+ required: true,
213
+ disabled: isLoading
214
+ }
215
+ )
216
+ ] }),
217
+ /* @__PURE__ */ jsxs("div", { "data-authos-field": "password", children: [
218
+ /* @__PURE__ */ jsx("label", { htmlFor: "authos-password", children: "Password" }),
219
+ /* @__PURE__ */ jsx(
220
+ "input",
221
+ {
222
+ id: "authos-password",
223
+ type: "password",
224
+ autoComplete: "current-password",
225
+ value: password,
226
+ onChange: (e) => setPassword(e.target.value),
227
+ placeholder: "Enter your password",
228
+ required: true,
229
+ disabled: isLoading
230
+ }
231
+ )
232
+ ] }),
233
+ error && /* @__PURE__ */ jsx("div", { "data-authos-error": true, children: error }),
234
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: isLoading, "data-authos-submit": "", children: isLoading ? "Signing in..." : "Sign In" }),
235
+ showForgotPassword && /* @__PURE__ */ jsx("a", { href: "/forgot-password", "data-authos-link": "forgot-password", children: "Forgot password?" }),
236
+ showSignUp && /* @__PURE__ */ jsxs("div", { "data-authos-signup-prompt": true, children: [
237
+ "Don't have an account? ",
238
+ /* @__PURE__ */ jsx("a", { href: "/signup", "data-authos-link": "signup", children: "Sign up" })
239
+ ] })
240
+ ] }) });
241
+ }
242
+ function SignUp({ onSuccess, onError, orgSlug, showSignIn = true, className }) {
243
+ const { client } = useAuthOSContext();
244
+ const [email, setEmail] = useState("");
245
+ const [password, setPassword] = useState("");
246
+ const [confirmPassword, setConfirmPassword] = useState("");
247
+ const [error, setError] = useState(null);
248
+ const [isLoading, setIsLoading] = useState(false);
249
+ const [isSuccess, setIsSuccess] = useState(false);
250
+ const handleSubmit = useCallback(
251
+ async (e) => {
252
+ e.preventDefault();
253
+ setError(null);
254
+ if (password !== confirmPassword) {
255
+ setError("Passwords do not match");
256
+ return;
257
+ }
258
+ if (password.length < 8) {
259
+ setError("Password must be at least 8 characters");
260
+ return;
261
+ }
262
+ setIsLoading(true);
263
+ try {
264
+ await client.auth.register({
265
+ email,
266
+ password,
267
+ org_slug: orgSlug
268
+ });
269
+ setIsSuccess(true);
270
+ onSuccess?.();
271
+ } catch (err) {
272
+ const message = err instanceof SsoApiError ? err.message : "Registration failed";
273
+ setError(message);
274
+ onError?.(err instanceof Error ? err : new Error(message));
275
+ } finally {
276
+ setIsLoading(false);
277
+ }
278
+ },
279
+ [client, email, password, confirmPassword, orgSlug, onSuccess, onError]
280
+ );
281
+ if (isSuccess) {
282
+ return /* @__PURE__ */ jsx("div", { className, "data-authos-signup": true, "data-state": "success", children: /* @__PURE__ */ jsxs("div", { "data-authos-success": true, children: [
283
+ /* @__PURE__ */ jsx("h2", { children: "Check your email" }),
284
+ /* @__PURE__ */ jsxs("p", { children: [
285
+ "We've sent a verification link to ",
286
+ email,
287
+ ". Please click the link to verify your account."
288
+ ] })
289
+ ] }) });
290
+ }
291
+ return /* @__PURE__ */ jsx("div", { className, "data-authos-signup": true, "data-state": "form", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
292
+ /* @__PURE__ */ jsxs("div", { "data-authos-field": "email", children: [
293
+ /* @__PURE__ */ jsx("label", { htmlFor: "authos-signup-email", children: "Email" }),
294
+ /* @__PURE__ */ jsx(
295
+ "input",
296
+ {
297
+ id: "authos-signup-email",
298
+ type: "email",
299
+ autoComplete: "email",
300
+ value: email,
301
+ onChange: (e) => setEmail(e.target.value),
302
+ placeholder: "Enter your email",
303
+ required: true,
304
+ disabled: isLoading
305
+ }
306
+ )
307
+ ] }),
308
+ /* @__PURE__ */ jsxs("div", { "data-authos-field": "password", children: [
309
+ /* @__PURE__ */ jsx("label", { htmlFor: "authos-signup-password", children: "Password" }),
310
+ /* @__PURE__ */ jsx(
311
+ "input",
312
+ {
313
+ id: "authos-signup-password",
314
+ type: "password",
315
+ autoComplete: "new-password",
316
+ value: password,
317
+ onChange: (e) => setPassword(e.target.value),
318
+ placeholder: "Create a password",
319
+ required: true,
320
+ minLength: 8,
321
+ disabled: isLoading
322
+ }
323
+ )
324
+ ] }),
325
+ /* @__PURE__ */ jsxs("div", { "data-authos-field": "confirm-password", children: [
326
+ /* @__PURE__ */ jsx("label", { htmlFor: "authos-signup-confirm", children: "Confirm Password" }),
327
+ /* @__PURE__ */ jsx(
328
+ "input",
329
+ {
330
+ id: "authos-signup-confirm",
331
+ type: "password",
332
+ autoComplete: "new-password",
333
+ value: confirmPassword,
334
+ onChange: (e) => setConfirmPassword(e.target.value),
335
+ placeholder: "Confirm your password",
336
+ required: true,
337
+ disabled: isLoading
338
+ }
339
+ )
340
+ ] }),
341
+ error && /* @__PURE__ */ jsx("div", { "data-authos-error": true, children: error }),
342
+ /* @__PURE__ */ jsx("button", { type: "submit", disabled: isLoading, "data-authos-submit": true, children: isLoading ? "Creating account..." : "Create Account" }),
343
+ showSignIn && /* @__PURE__ */ jsxs("div", { "data-authos-signin-prompt": true, children: [
344
+ "Already have an account? ",
345
+ /* @__PURE__ */ jsx("a", { href: "/signin", "data-authos-link": "signin", children: "Sign in" })
346
+ ] })
347
+ ] }) });
348
+ }
349
+ function OrganizationSwitcher({ onSwitch, className, renderItem }) {
350
+ const { client, isAuthenticated } = useAuthOSContext();
351
+ const { organization: currentOrg, switchOrganization } = useOrganization();
352
+ const [organizations, setOrganizations] = useState([]);
353
+ const [isLoading, setIsLoading] = useState(true);
354
+ const [isOpen, setIsOpen] = useState(false);
355
+ const [isSwitching, setIsSwitching] = useState(false);
356
+ useEffect(() => {
357
+ if (!isAuthenticated) {
358
+ setOrganizations([]);
359
+ setIsLoading(false);
360
+ return;
361
+ }
362
+ const fetchOrganizations = async () => {
363
+ try {
364
+ const orgResponses = await client.organizations.list();
365
+ setOrganizations(orgResponses.map((r) => r.organization));
366
+ } catch {
367
+ setOrganizations([]);
368
+ } finally {
369
+ setIsLoading(false);
370
+ }
371
+ };
372
+ fetchOrganizations();
373
+ }, [client, isAuthenticated]);
374
+ const handleSwitch = useCallback(
375
+ async (org) => {
376
+ if (org.slug === currentOrg?.slug) {
377
+ setIsOpen(false);
378
+ return;
379
+ }
380
+ setIsSwitching(true);
381
+ try {
382
+ await switchOrganization(org.slug);
383
+ onSwitch?.(org);
384
+ setIsOpen(false);
385
+ } catch (err) {
386
+ console.error("Failed to switch organization:", err);
387
+ } finally {
388
+ setIsSwitching(false);
389
+ }
390
+ },
391
+ [currentOrg, switchOrganization, onSwitch]
392
+ );
393
+ if (!isAuthenticated) {
394
+ return /* @__PURE__ */ jsx("div", { className, "data-authos-orgswitcher": true, "data-state": "signed-out", children: /* @__PURE__ */ jsx("span", { "data-authos-org-placeholder": true, children: "Not signed in" }) });
395
+ }
396
+ if (isLoading) {
397
+ return /* @__PURE__ */ jsx("div", { className, "data-authos-orgswitcher": true, "data-state": "loading", children: /* @__PURE__ */ jsx("span", { children: "Loading..." }) });
398
+ }
399
+ if (organizations.length === 0) {
400
+ return null;
401
+ }
402
+ return /* @__PURE__ */ jsxs("div", { className, "data-authos-orgswitcher": true, "data-state": isOpen ? "open" : "closed", children: [
403
+ /* @__PURE__ */ jsxs(
404
+ "button",
405
+ {
406
+ type: "button",
407
+ onClick: () => setIsOpen(!isOpen),
408
+ disabled: isSwitching,
409
+ "data-authos-org-trigger": true,
410
+ children: [
411
+ /* @__PURE__ */ jsx("span", { "data-authos-org-name": true, children: currentOrg?.name ?? "Select Organization" }),
412
+ /* @__PURE__ */ jsx("span", { "data-authos-org-chevron": true, "aria-hidden": "true", children: isOpen ? "\u25B2" : "\u25BC" })
413
+ ]
414
+ }
415
+ ),
416
+ isOpen && /* @__PURE__ */ jsx("ul", { "data-authos-org-list": true, role: "listbox", children: organizations.map((org) => {
417
+ const isActive = org.slug === currentOrg?.slug;
418
+ if (renderItem) {
419
+ return /* @__PURE__ */ jsx("li", { role: "option", "aria-selected": isActive, children: /* @__PURE__ */ jsx(
420
+ "button",
421
+ {
422
+ type: "button",
423
+ onClick: () => handleSwitch(org),
424
+ disabled: isSwitching,
425
+ children: renderItem(org, isActive)
426
+ }
427
+ ) }, org.id);
428
+ }
429
+ return /* @__PURE__ */ jsx("li", { role: "option", "aria-selected": isActive, children: /* @__PURE__ */ jsxs(
430
+ "button",
431
+ {
432
+ type: "button",
433
+ onClick: () => handleSwitch(org),
434
+ disabled: isSwitching,
435
+ "data-authos-org-item": true,
436
+ "data-active": isActive,
437
+ children: [
438
+ /* @__PURE__ */ jsx("span", { "data-authos-org-item-name": true, children: org.name }),
439
+ isActive && /* @__PURE__ */ jsx("span", { "data-authos-org-item-check": true, children: "\u2713" })
440
+ ]
441
+ }
442
+ ) }, org.id);
443
+ }) })
444
+ ] });
445
+ }
446
+ function UserButton({ className, showEmail = false, onLogout }) {
447
+ const { client, user, setUser, setOrganization } = useAuthOSContext();
448
+ const [isOpen, setIsOpen] = useState(false);
449
+ const [isLoggingOut, setIsLoggingOut] = useState(false);
450
+ const handleLogout = useCallback(async () => {
451
+ setIsLoggingOut(true);
452
+ try {
453
+ await client.auth.logout();
454
+ } catch {
455
+ } finally {
456
+ setUser(null);
457
+ setOrganization(null);
458
+ setIsLoggingOut(false);
459
+ setIsOpen(false);
460
+ onLogout?.();
461
+ }
462
+ }, [client, setUser, setOrganization, onLogout]);
463
+ if (!user) {
464
+ return /* @__PURE__ */ jsx("div", { className, "data-authos-userbutton": true, "data-state": "signed-out", children: /* @__PURE__ */ jsx("span", { "data-authos-user-placeholder": true, children: "Not signed in" }) });
465
+ }
466
+ const initials = user.email.split("@")[0].split(".").map((part) => part[0]?.toUpperCase() ?? "").slice(0, 2).join("");
467
+ return /* @__PURE__ */ jsxs("div", { className, "data-authos-userbutton": true, "data-state": isOpen ? "open" : "closed", children: [
468
+ /* @__PURE__ */ jsxs(
469
+ "button",
470
+ {
471
+ type: "button",
472
+ onClick: () => setIsOpen(!isOpen),
473
+ disabled: isLoggingOut,
474
+ "data-authos-user-trigger": true,
475
+ children: [
476
+ /* @__PURE__ */ jsx("span", { "data-authos-user-avatar": true, "aria-hidden": "true", children: initials }),
477
+ showEmail && /* @__PURE__ */ jsx("span", { "data-authos-user-email": true, children: user.email })
478
+ ]
479
+ }
480
+ ),
481
+ isOpen && /* @__PURE__ */ jsxs("div", { "data-authos-user-menu": true, children: [
482
+ /* @__PURE__ */ jsxs("div", { "data-authos-user-info": true, children: [
483
+ /* @__PURE__ */ jsx("span", { "data-authos-user-email": true, children: user.email }),
484
+ user.is_platform_owner && /* @__PURE__ */ jsx("span", { "data-authos-user-badge": true, children: "Platform Owner" })
485
+ ] }),
486
+ /* @__PURE__ */ jsx("hr", { "data-authos-divider": true }),
487
+ /* @__PURE__ */ jsx(
488
+ "button",
489
+ {
490
+ type: "button",
491
+ onClick: handleLogout,
492
+ disabled: isLoggingOut,
493
+ "data-authos-logout": true,
494
+ children: isLoggingOut ? "Signing out..." : "Sign out"
495
+ }
496
+ )
497
+ ] })
498
+ ] });
499
+ }
500
+ function Protect({ permission, role, fallback = null, children }) {
501
+ const { user, isLoading } = useAuthOSContext();
502
+ const hasPermission = usePermission(permission ?? "");
503
+ const renderContent = () => {
504
+ if (isLoading) {
505
+ return null;
506
+ }
507
+ if (!user) {
508
+ return fallback;
509
+ }
510
+ if (permission && !hasPermission) {
511
+ return fallback;
512
+ }
513
+ if (role) {
514
+ const userRoles = user.permissions.filter((p) => p.startsWith("role:")).map((p) => p.replace("role:", ""));
515
+ const roleHierarchy = ["member", "admin", "owner"];
516
+ const requiredRoleIndex = roleHierarchy.indexOf(role);
517
+ const hasRole = userRoles.some((userRole) => {
518
+ const userRoleIndex = roleHierarchy.indexOf(userRole);
519
+ return userRoleIndex >= requiredRoleIndex;
520
+ });
521
+ if (!hasRole) {
522
+ return fallback;
523
+ }
524
+ }
525
+ return children;
526
+ };
527
+ return /* @__PURE__ */ jsx("div", { "data-authos-protect": true, children: renderContent() });
528
+ }
529
+
530
+ export { AuthOSProvider, OrganizationSwitcher, Protect, SignIn, SignUp, UserButton, useAllPermissions, useAnyPermission, useAuthOS, useAuthOSContext, useOrganization, usePermission, useUser };
@@ -0,0 +1,146 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ interface AuthMiddlewareConfig {
4
+ /**
5
+ * The JWKS URL for token verification
6
+ */
7
+ jwksUrl: string;
8
+ /**
9
+ * Protected routes that require authentication
10
+ */
11
+ protectedRoutes?: string[];
12
+ /**
13
+ * Public routes that don't require authentication
14
+ */
15
+ publicRoutes?: string[];
16
+ /**
17
+ * The URL to redirect to when not authenticated
18
+ */
19
+ signInUrl?: string;
20
+ /**
21
+ * Cookie name for the access token
22
+ */
23
+ tokenCookie?: string;
24
+ }
25
+ /**
26
+ * Creates an authentication middleware for Next.js Edge Runtime.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * // middleware.ts
31
+ * import { authMiddleware } from '@drmhse/authos-react/nextjs';
32
+ *
33
+ * export default authMiddleware({
34
+ * jwksUrl: 'https://auth.example.com/.well-known/jwks.json',
35
+ * protectedRoutes: ['/dashboard/*', '/settings/*'],
36
+ * publicRoutes: ['/', '/about', '/pricing'],
37
+ * signInUrl: '/signin',
38
+ * });
39
+ *
40
+ * export const config = {
41
+ * matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
42
+ * };
43
+ * ```
44
+ */
45
+ declare function authMiddleware(config: AuthMiddlewareConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
46
+
47
+ /**
48
+ * User information extracted from the request in server components.
49
+ */
50
+ interface AuthUser {
51
+ id: string;
52
+ email: string;
53
+ org?: string;
54
+ permissions: string[];
55
+ }
56
+ /**
57
+ * Authentication state for server components.
58
+ */
59
+ interface AuthState {
60
+ userId: string | null;
61
+ orgSlug: string | null;
62
+ isAuthenticated: boolean;
63
+ }
64
+ /**
65
+ * Get the current authenticated user in a React Server Component.
66
+ * This reads from the headers set by the authMiddleware.
67
+ *
68
+ * @returns The current user or null if not authenticated
69
+ *
70
+ * @example
71
+ * ```tsx
72
+ * // app/dashboard/page.tsx
73
+ * import { currentUser } from '@drmhse/authos-react/nextjs';
74
+ *
75
+ * export default async function DashboardPage() {
76
+ * const user = await currentUser();
77
+ *
78
+ * if (!user) {
79
+ * redirect('/signin');
80
+ * }
81
+ *
82
+ * return <div>Welcome, {user.email}!</div>;
83
+ * }
84
+ * ```
85
+ */
86
+ declare function currentUser(): Promise<AuthUser | null>;
87
+ /**
88
+ * Get the current authentication state in a React Server Component.
89
+ * Provides basic auth info without fetching full user details.
90
+ *
91
+ * @returns The current auth state
92
+ *
93
+ * @example
94
+ * ```tsx
95
+ * // app/layout.tsx
96
+ * import { auth } from '@drmhse/authos-react/nextjs';
97
+ *
98
+ * export default async function RootLayout({ children }) {
99
+ * const { isAuthenticated, userId } = await auth();
100
+ *
101
+ * return (
102
+ * <html>
103
+ * <body>
104
+ * <nav>
105
+ * {isAuthenticated ? (
106
+ * <UserMenu userId={userId} />
107
+ * ) : (
108
+ * <a href="/signin">Sign In</a>
109
+ * )}
110
+ * </nav>
111
+ * {children}
112
+ * </body>
113
+ * </html>
114
+ * );
115
+ * }
116
+ * ```
117
+ */
118
+ declare function auth(): Promise<AuthState>;
119
+ /**
120
+ * Get the access token from cookies in a server component.
121
+ * Useful when you need to make authenticated API calls from the server.
122
+ *
123
+ * @param cookieName - The name of the token cookie (default: 'authos_token')
124
+ * @returns The access token or null
125
+ *
126
+ * @example
127
+ * ```tsx
128
+ * // app/api/data/route.ts
129
+ * import { getToken } from '@drmhse/authos-react/nextjs';
130
+ *
131
+ * export async function GET() {
132
+ * const token = await getToken();
133
+ *
134
+ * if (!token) {
135
+ * return Response.json({ error: 'Unauthorized' }, { status: 401 });
136
+ * }
137
+ *
138
+ * // Use token for backend API calls
139
+ * const data = await fetchFromAPI(token);
140
+ * return Response.json(data);
141
+ * }
142
+ * ```
143
+ */
144
+ declare function getToken(cookieName?: string): Promise<string | null>;
145
+
146
+ export { type AuthMiddlewareConfig, type AuthState, type AuthUser, auth, authMiddleware, currentUser, getToken };