authmi 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2,15 +2,127 @@ import {
2
2
  AuthMiClient,
3
3
  AuthMiError,
4
4
  LocalStorageTokenStorage,
5
- MemoryTokenStorage,
6
5
  ScopeError
7
- } from "./chunk-UNKK6FP4.mjs";
6
+ } from "./chunk-EAK7C6YO.mjs";
7
+
8
+ // src/storage/cookie.ts
9
+ var CookieTokenStorage = class _CookieTokenStorage {
10
+ /**
11
+ * @param cookieStr The raw `Cookie` header value (server-side) or `document.cookie` (browser).
12
+ * Pass an empty string in environments where cookies are managed via Set-Cookie.
13
+ */
14
+ constructor(cookieStr = "", options = {}) {
15
+ this.cookieStr = cookieStr;
16
+ this.options = {
17
+ name: "authmi_token",
18
+ httpOnly: true,
19
+ secure: typeof process !== "undefined" && process.env?.NODE_ENV === "production",
20
+ sameSite: "lax",
21
+ domain: "",
22
+ path: "/",
23
+ maxAge: 86400,
24
+ ...options
25
+ };
26
+ }
27
+ /** Update the raw cookie string (e.g. per-request in server middleware) */
28
+ setCookieString(cookieStr) {
29
+ this.cookieStr = cookieStr;
30
+ }
31
+ /** Escape special regex characters in a string */
32
+ static escapeRegex(s) {
33
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
34
+ }
35
+ getToken() {
36
+ const name = _CookieTokenStorage.escapeRegex(this.options.name);
37
+ const match = this.cookieStr.match(
38
+ new RegExp(`(?:^|;\\s*)${name}=([^;]*)`)
39
+ );
40
+ return match ? decodeURIComponent(match[1]) : null;
41
+ }
42
+ setToken(token) {
43
+ const { name, httpOnly, secure, sameSite, domain, path, maxAge } = this.options;
44
+ let cookie = `${name}=${encodeURIComponent(token)}; path=${path}; max-age=${maxAge}`;
45
+ if (httpOnly) cookie += "; HttpOnly";
46
+ if (secure) cookie += "; Secure";
47
+ if (sameSite) cookie += `; SameSite=${sameSite}`;
48
+ if (domain) cookie += `; domain=${domain}`;
49
+ this.lastSetCookie = cookie;
50
+ this.cookieStr = `${name}=${encodeURIComponent(token)}`;
51
+ }
52
+ /** The last Set-Cookie header generated by setToken() or removeToken() */
53
+ getSetCookieHeader() {
54
+ return this.lastSetCookie;
55
+ }
56
+ removeToken() {
57
+ const { name, domain, path } = this.options;
58
+ let cookie = `${name}=; path=${path}; max-age=0`;
59
+ if (domain) cookie += `; domain=${domain}`;
60
+ this.lastSetCookie = cookie;
61
+ this.cookieStr = "";
62
+ }
63
+ };
64
+
65
+ // src/storage/memory.ts
66
+ var MemoryTokenStorage = class {
67
+ constructor() {
68
+ this.token = null;
69
+ }
70
+ getToken() {
71
+ return this.token;
72
+ }
73
+ setToken(token) {
74
+ this.token = token;
75
+ }
76
+ removeToken() {
77
+ this.token = null;
78
+ }
79
+ };
80
+
81
+ // src/cache.ts
82
+ var IntrospectCache = class {
83
+ constructor(ttlMs = 6e4) {
84
+ this.store = /* @__PURE__ */ new Map();
85
+ this.defaultTtlMs = ttlMs;
86
+ }
87
+ /** Build a cache key from the token (simple hash) */
88
+ key(token) {
89
+ let hash = 0;
90
+ for (let i = 0; i < token.length; i++) {
91
+ hash = hash * 31 + token.charCodeAt(i) | 0;
92
+ }
93
+ return `tok:${hash.toString(36)}`;
94
+ }
95
+ get(token) {
96
+ const entry = this.store.get(this.key(token));
97
+ if (!entry) return void 0;
98
+ if (Date.now() > entry.expiresAt) {
99
+ this.store.delete(this.key(token));
100
+ return void 0;
101
+ }
102
+ return entry.result;
103
+ }
104
+ set(token, result, ttlMs) {
105
+ if (!result.valid) return;
106
+ this.store.set(this.key(token), {
107
+ result,
108
+ expiresAt: Date.now() + (ttlMs ?? this.defaultTtlMs)
109
+ });
110
+ }
111
+ invalidate(token) {
112
+ this.store.delete(this.key(token));
113
+ }
114
+ clear() {
115
+ this.store.clear();
116
+ }
117
+ };
8
118
 
9
119
  // src/index.ts
10
- var VERSION = "1.0.0";
120
+ var VERSION = "1.1.0";
11
121
  export {
12
122
  AuthMiClient,
13
123
  AuthMiError,
124
+ CookieTokenStorage,
125
+ IntrospectCache,
14
126
  LocalStorageTokenStorage,
15
127
  MemoryTokenStorage,
16
128
  ScopeError,
package/dist/next.d.mts CHANGED
@@ -1,7 +1,5 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import { NextRequest, NextResponse } from 'next/server';
3
- import { b as AuthMiConfig } from './client-D6JiIhlU.mjs';
4
- export { A as ApiKey, a as AuthMiClient, c as AuthMiError, d as AuthToken, C as CreateApiKeyRequest, e as CreateApiKeyResponse, f as CreateScopeRequest, g as CreateUserRequest, I as IntrospectRequest, h as IntrospectResponse, L as LocalStorageTokenStorage, i as LoginCredentials, M as MemoryTokenStorage, O as OAuthCallbackResult, j as OAuthInitiateResponse, k as OAuthProvider, l as OnboardRequest, m as OnboardResponse, R as RegisterWebhookRequest, S as Scope, n as ScopeError, o as Service, T as TokenStorage, U as User, p as UserListResponse, V as ValidationResult, W as Webhook } from './client-D6JiIhlU.mjs';
2
+ export { A as ApiKey, a as AuditLog, b as AuditLogQuery, c as AuthMiClient, e as AuthMiError, f as AuthToken, B as BackupCodesResult, C as Challenge2FARequest, g as CheckoutResponse, h as ClientOptions, j as CreateApiKeyRequest, k as CreateApiKeyResponse, l as CreateRoleRequest, m as CreateSamlConnectionRequest, n as CreateScopeRequest, o as CreateUserRequest, E as Enable2FAResult, F as ForgotPasswordRequest, p as IntrospectRequest, q as IntrospectResponse, J as JwksResponse, L as LoginCredentials, O as OAuthCallbackResult, r as OAuthInitiateResponse, s as OAuthProvider, P as Plan, t as PortalResponse, R as RegisterWebhookRequest, u as ResendVerificationRequest, v as ResetPasswordRequest, w as Role, S as SamlConnection, x as SamlInitiateRequest, y as Scope, z as ScopeError, D as ServiceDetail, G as Setup2FAResult, H as SignupCredentials, K as Subscription, U as UpdateServiceRequest, M as User, V as ValidationResult, N as VerifyEmailRequest, W as Webhook } from './client-DmZsG2xs.mjs';
5
3
 
6
4
  interface MiddlewareOptions {
7
5
  /** Base URL of Auth Mi service */
@@ -21,17 +19,11 @@ interface MiddlewareOptions {
21
19
  /** Forbidden page path (insufficient scopes) */
22
20
  forbiddenPath?: string;
23
21
  }
24
- interface MiddlewareContext {
25
- valid: boolean;
26
- userId?: string;
27
- email?: string;
28
- scopes?: string[];
29
- error?: string;
30
- }
31
22
  /**
32
23
  * Create a Next.js middleware with scope-based protection
33
24
  *
34
25
  * @example
26
+ * ```ts
35
27
  * // middleware.ts
36
28
  * import { createAuthMiMiddleware } from "authmi/next";
37
29
  *
@@ -41,36 +33,18 @@ interface MiddlewareContext {
41
33
  * protectedPaths: ["/dashboard", "/api/protected"],
42
34
  * scopedPaths: {
43
35
  * "/api/users": ["users:read"],
44
- * "/api/users/create": ["users:write"],
45
- * "/api/billing": ["billing:read"],
46
36
  * "/api/admin": ["admin"],
47
37
  * },
48
38
  * publicPaths: ["/", "/login", "/register"],
49
39
  * });
40
+ * ```
50
41
  */
51
42
  declare function createAuthMiMiddleware(options: MiddlewareOptions): (request: NextRequest) => Promise<NextResponse<unknown>>;
52
- /**
53
- * Higher-order component to protect a page with required scopes
54
- *
55
- * @example
56
- * // pages/admin.tsx
57
- * import { withScope } from "authmi/next";
58
- *
59
- * function AdminPage() {
60
- * return <div>Admin Only</div>;
61
- * }
62
- *
63
- * export default withScope(AdminPage, ["admin"], {
64
- * baseUrl: process.env.NEXT_PUBLIC_AUTHMI_URL!,
65
- * apiKey: process.env.NEXT_PUBLIC_AUTHMI_API_KEY!,
66
- * });
67
- */
68
- declare function withScope<P extends object>(Component: React.ComponentType<P>, _requiredScopes: string[], _config: AuthMiConfig): (props: P) => react_jsx_runtime.JSX.Element;
69
43
  /**
70
44
  * Server-side helper to validate scopes in API routes
71
45
  *
72
46
  * @example
73
- * // app/api/users/route.ts
47
+ * ```ts
74
48
  * import { validateScopes } from "authmi/next";
75
49
  *
76
50
  * export async function GET(request: Request) {
@@ -79,16 +53,12 @@ declare function withScope<P extends object>(Component: React.ComponentType<P>,
79
53
  * apiKey: process.env.AUTHMI_API_KEY!,
80
54
  * requiredScopes: ["users:read"],
81
55
  * });
82
- *
83
56
  * if (!result.valid) {
84
- * return new Response(JSON.stringify({ error: result.error }), {
85
- * status: result.status || 401,
86
- * });
57
+ * return Response.json({ error: result.error }, { status: result.status });
87
58
  * }
88
- *
89
- * // Proceed with the request
90
59
  * return Response.json({ users: [] });
91
60
  * }
61
+ * ```
92
62
  */
93
63
  declare function validateScopes(request: Request, options: {
94
64
  baseUrl: string;
@@ -106,4 +76,4 @@ declare function validateScopes(request: Request, options: {
106
76
  status: number;
107
77
  }>;
108
78
 
109
- export { AuthMiConfig, type MiddlewareContext, type MiddlewareOptions, createAuthMiMiddleware, validateScopes, withScope };
79
+ export { type MiddlewareOptions, createAuthMiMiddleware, validateScopes };
package/dist/next.d.ts CHANGED
@@ -1,7 +1,5 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import { NextRequest, NextResponse } from 'next/server';
3
- import { b as AuthMiConfig } from './client-D6JiIhlU.js';
4
- export { A as ApiKey, a as AuthMiClient, c as AuthMiError, d as AuthToken, C as CreateApiKeyRequest, e as CreateApiKeyResponse, f as CreateScopeRequest, g as CreateUserRequest, I as IntrospectRequest, h as IntrospectResponse, L as LocalStorageTokenStorage, i as LoginCredentials, M as MemoryTokenStorage, O as OAuthCallbackResult, j as OAuthInitiateResponse, k as OAuthProvider, l as OnboardRequest, m as OnboardResponse, R as RegisterWebhookRequest, S as Scope, n as ScopeError, o as Service, T as TokenStorage, U as User, p as UserListResponse, V as ValidationResult, W as Webhook } from './client-D6JiIhlU.js';
2
+ export { A as ApiKey, a as AuditLog, b as AuditLogQuery, c as AuthMiClient, e as AuthMiError, f as AuthToken, B as BackupCodesResult, C as Challenge2FARequest, g as CheckoutResponse, h as ClientOptions, j as CreateApiKeyRequest, k as CreateApiKeyResponse, l as CreateRoleRequest, m as CreateSamlConnectionRequest, n as CreateScopeRequest, o as CreateUserRequest, E as Enable2FAResult, F as ForgotPasswordRequest, p as IntrospectRequest, q as IntrospectResponse, J as JwksResponse, L as LoginCredentials, O as OAuthCallbackResult, r as OAuthInitiateResponse, s as OAuthProvider, P as Plan, t as PortalResponse, R as RegisterWebhookRequest, u as ResendVerificationRequest, v as ResetPasswordRequest, w as Role, S as SamlConnection, x as SamlInitiateRequest, y as Scope, z as ScopeError, D as ServiceDetail, G as Setup2FAResult, H as SignupCredentials, K as Subscription, U as UpdateServiceRequest, M as User, V as ValidationResult, N as VerifyEmailRequest, W as Webhook } from './client-DmZsG2xs.js';
5
3
 
6
4
  interface MiddlewareOptions {
7
5
  /** Base URL of Auth Mi service */
@@ -21,17 +19,11 @@ interface MiddlewareOptions {
21
19
  /** Forbidden page path (insufficient scopes) */
22
20
  forbiddenPath?: string;
23
21
  }
24
- interface MiddlewareContext {
25
- valid: boolean;
26
- userId?: string;
27
- email?: string;
28
- scopes?: string[];
29
- error?: string;
30
- }
31
22
  /**
32
23
  * Create a Next.js middleware with scope-based protection
33
24
  *
34
25
  * @example
26
+ * ```ts
35
27
  * // middleware.ts
36
28
  * import { createAuthMiMiddleware } from "authmi/next";
37
29
  *
@@ -41,36 +33,18 @@ interface MiddlewareContext {
41
33
  * protectedPaths: ["/dashboard", "/api/protected"],
42
34
  * scopedPaths: {
43
35
  * "/api/users": ["users:read"],
44
- * "/api/users/create": ["users:write"],
45
- * "/api/billing": ["billing:read"],
46
36
  * "/api/admin": ["admin"],
47
37
  * },
48
38
  * publicPaths: ["/", "/login", "/register"],
49
39
  * });
40
+ * ```
50
41
  */
51
42
  declare function createAuthMiMiddleware(options: MiddlewareOptions): (request: NextRequest) => Promise<NextResponse<unknown>>;
52
- /**
53
- * Higher-order component to protect a page with required scopes
54
- *
55
- * @example
56
- * // pages/admin.tsx
57
- * import { withScope } from "authmi/next";
58
- *
59
- * function AdminPage() {
60
- * return <div>Admin Only</div>;
61
- * }
62
- *
63
- * export default withScope(AdminPage, ["admin"], {
64
- * baseUrl: process.env.NEXT_PUBLIC_AUTHMI_URL!,
65
- * apiKey: process.env.NEXT_PUBLIC_AUTHMI_API_KEY!,
66
- * });
67
- */
68
- declare function withScope<P extends object>(Component: React.ComponentType<P>, _requiredScopes: string[], _config: AuthMiConfig): (props: P) => react_jsx_runtime.JSX.Element;
69
43
  /**
70
44
  * Server-side helper to validate scopes in API routes
71
45
  *
72
46
  * @example
73
- * // app/api/users/route.ts
47
+ * ```ts
74
48
  * import { validateScopes } from "authmi/next";
75
49
  *
76
50
  * export async function GET(request: Request) {
@@ -79,16 +53,12 @@ declare function withScope<P extends object>(Component: React.ComponentType<P>,
79
53
  * apiKey: process.env.AUTHMI_API_KEY!,
80
54
  * requiredScopes: ["users:read"],
81
55
  * });
82
- *
83
56
  * if (!result.valid) {
84
- * return new Response(JSON.stringify({ error: result.error }), {
85
- * status: result.status || 401,
86
- * });
57
+ * return Response.json({ error: result.error }, { status: result.status });
87
58
  * }
88
- *
89
- * // Proceed with the request
90
59
  * return Response.json({ users: [] });
91
60
  * }
61
+ * ```
92
62
  */
93
63
  declare function validateScopes(request: Request, options: {
94
64
  baseUrl: string;
@@ -106,4 +76,4 @@ declare function validateScopes(request: Request, options: {
106
76
  status: number;
107
77
  }>;
108
78
 
109
- export { AuthMiConfig, type MiddlewareContext, type MiddlewareOptions, createAuthMiMiddleware, validateScopes, withScope };
79
+ export { type MiddlewareOptions, createAuthMiMiddleware, validateScopes };