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/README.md +7 -7
- package/dist/chunk-EAK7C6YO.mjs +688 -0
- package/dist/client-DmZsG2xs.d.mts +406 -0
- package/dist/client-DmZsG2xs.d.ts +406 -0
- package/dist/index.d.mts +48 -23
- package/dist/index.d.ts +48 -23
- package/dist/index.js +581 -386
- package/dist/index.mjs +115 -3
- package/dist/next.d.mts +7 -37
- package/dist/next.d.ts +7 -37
- package/dist/next.js +476 -416
- package/dist/next.mjs +5 -24
- package/dist/react.d.mts +29 -30
- package/dist/react.d.ts +29 -30
- package/dist/react.js +549 -444
- package/dist/react.mjs +77 -52
- package/package.json +8 -6
- package/dist/chunk-UNKK6FP4.mjs +0 -609
- package/dist/client-D6JiIhlU.d.mts +0 -332
- package/dist/client-D6JiIhlU.d.ts +0 -332
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-
|
|
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.
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
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 {
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
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 {
|
|
79
|
+
export { type MiddlewareOptions, createAuthMiMiddleware, validateScopes };
|