cloudflare-access 1.0.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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +452 -0
  3. package/dist/adapters/effect/index.d.mts +167 -0
  4. package/dist/adapters/effect/index.d.ts +167 -0
  5. package/dist/adapters/effect/index.js +221 -0
  6. package/dist/adapters/effect/index.js.map +1 -0
  7. package/dist/adapters/effect/index.mjs +221 -0
  8. package/dist/adapters/effect/index.mjs.map +1 -0
  9. package/dist/adapters/express/index.d.mts +74 -0
  10. package/dist/adapters/express/index.d.ts +74 -0
  11. package/dist/adapters/express/index.js +129 -0
  12. package/dist/adapters/express/index.js.map +1 -0
  13. package/dist/adapters/express/index.mjs +129 -0
  14. package/dist/adapters/express/index.mjs.map +1 -0
  15. package/dist/adapters/fastify/index.d.mts +111 -0
  16. package/dist/adapters/fastify/index.d.ts +111 -0
  17. package/dist/adapters/fastify/index.js +140 -0
  18. package/dist/adapters/fastify/index.js.map +1 -0
  19. package/dist/adapters/fastify/index.mjs +140 -0
  20. package/dist/adapters/fastify/index.mjs.map +1 -0
  21. package/dist/adapters/hono/index.d.mts +19 -0
  22. package/dist/adapters/hono/index.d.ts +19 -0
  23. package/dist/adapters/hono/index.js +45 -0
  24. package/dist/adapters/hono/index.js.map +1 -0
  25. package/dist/adapters/hono/index.mjs +45 -0
  26. package/dist/adapters/hono/index.mjs.map +1 -0
  27. package/dist/adapters/nestjs/index.d.mts +123 -0
  28. package/dist/adapters/nestjs/index.d.ts +123 -0
  29. package/dist/adapters/nestjs/index.js +117 -0
  30. package/dist/adapters/nestjs/index.js.map +1 -0
  31. package/dist/adapters/nestjs/index.mjs +117 -0
  32. package/dist/adapters/nestjs/index.mjs.map +1 -0
  33. package/dist/chunk-DM2KGIQX.mjs +320 -0
  34. package/dist/chunk-DM2KGIQX.mjs.map +1 -0
  35. package/dist/chunk-LQWCGHLJ.mjs +108 -0
  36. package/dist/chunk-LQWCGHLJ.mjs.map +1 -0
  37. package/dist/chunk-PMFPT3SI.js +108 -0
  38. package/dist/chunk-PMFPT3SI.js.map +1 -0
  39. package/dist/chunk-WUJPWM4T.js +320 -0
  40. package/dist/chunk-WUJPWM4T.js.map +1 -0
  41. package/dist/config-D4O7DXNT.d.mts +12 -0
  42. package/dist/config-ottUdc-K.d.ts +12 -0
  43. package/dist/core/index.d.mts +24 -0
  44. package/dist/core/index.d.ts +24 -0
  45. package/dist/core/index.js +41 -0
  46. package/dist/core/index.js.map +1 -0
  47. package/dist/core/index.mjs +41 -0
  48. package/dist/core/index.mjs.map +1 -0
  49. package/dist/index.d.mts +6 -0
  50. package/dist/index.d.ts +6 -0
  51. package/dist/index.js +41 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/index.mjs +41 -0
  54. package/dist/index.mjs.map +1 -0
  55. package/dist/jwks-ChdyyS_L.d.mts +173 -0
  56. package/dist/jwks-ChdyyS_L.d.ts +173 -0
  57. package/dist/middleware-BDl6jUCu.d.mts +83 -0
  58. package/dist/middleware-CgFsjM20.d.ts +83 -0
  59. package/examples/basic.ts +52 -0
  60. package/examples/cloudflare-workers.ts +84 -0
  61. package/examples/custom-handlers.ts +85 -0
  62. package/examples/effect/http-server.ts +205 -0
  63. package/examples/email-allowlist.ts +50 -0
  64. package/examples/express/basic.ts +26 -0
  65. package/examples/fastify/basic.ts +24 -0
  66. package/examples/hono/basic.ts +26 -0
  67. package/examples/hono-router.ts +74 -0
  68. package/examples/nestjs/basic.ts +39 -0
  69. package/examples/skip-dev-mode.ts +89 -0
  70. package/package.json +178 -0
@@ -0,0 +1,320 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+
12
+ // src/core/types.ts
13
+ var CloudflareAccessErrorCode = {
14
+ /** Missing or invalid authentication token */
15
+ AUTH_REQUIRED: "AUTH_REQUIRED",
16
+ /** Token validation failed (expired, wrong signature, etc.) */
17
+ INVALID_TOKEN: "INVALID_TOKEN",
18
+ /** User email not in allowlist */
19
+ ACCESS_DENIED: "ACCESS_DENIED",
20
+ /** Invalid team domain configuration */
21
+ INVALID_TEAM_DOMAIN: "INVALID_TEAM_DOMAIN",
22
+ /** Missing audience tag configuration */
23
+ MISSING_AUDIENCE_TAG: "MISSING_AUDIENCE_TAG",
24
+ /** Missing environment configuration */
25
+ MISSING_CONFIG: "MISSING_CONFIG",
26
+ /** JWKS fetch failed */
27
+ JWKS_FETCH_ERROR: "JWKS_FETCH_ERROR"
28
+ };
29
+
30
+ // src/core/errors.ts
31
+ var CloudflareAccessError = class extends Error {
32
+
33
+
34
+
35
+
36
+ constructor(code, message, options) {
37
+ super(message, { cause: _optionalChain([options, 'optionalAccess', _ => _.cause]) });
38
+ this.name = "CloudflareAccessError";
39
+ this.code = code;
40
+ this.context = _optionalChain([options, 'optionalAccess', _2 => _2.context]);
41
+ this.requestUrl = _optionalChain([options, 'optionalAccess', _3 => _3.requestUrl]);
42
+ this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
43
+ }
44
+ /**
45
+ * Get a user-friendly error message with fix instructions
46
+ */
47
+ toJSON() {
48
+ return {
49
+ name: this.name,
50
+ code: this.code,
51
+ message: this.message,
52
+ timestamp: this.timestamp,
53
+ context: this.context,
54
+ fix: this.getFixInstructions()
55
+ };
56
+ }
57
+ /**
58
+ * Get fix instructions based on error code
59
+ */
60
+ getFixInstructions() {
61
+ switch (this.code) {
62
+ case CloudflareAccessErrorCode.AUTH_REQUIRED:
63
+ return "Ensure you're accessing through Cloudflare Access or provide a valid CF-Access-JWT-Assertion token";
64
+ case CloudflareAccessErrorCode.INVALID_TOKEN:
65
+ return "Your session may have expired. Please re-authenticate through Cloudflare Access";
66
+ case CloudflareAccessErrorCode.ACCESS_DENIED:
67
+ return "Contact your administrator to request access";
68
+ case CloudflareAccessErrorCode.MISSING_CONFIG:
69
+ return "Set CF_ACCESS_TEAM_DOMAIN and CF_ACCESS_AUD environment variables";
70
+ case CloudflareAccessErrorCode.INVALID_TEAM_DOMAIN:
71
+ return "Verify your team domain URL format (should be https://yourteam.cloudflareaccess.com)";
72
+ case CloudflareAccessErrorCode.MISSING_AUDIENCE_TAG:
73
+ return "Set CF_ACCESS_AUD to your application's audience tag";
74
+ case CloudflareAccessErrorCode.JWKS_FETCH_ERROR:
75
+ return "Unable to fetch signing keys. Check network connectivity and team domain";
76
+ default:
77
+ return "Check Cloudflare Access configuration and try again";
78
+ }
79
+ }
80
+ };
81
+ var AuthRequiredError = class extends CloudflareAccessError {
82
+ constructor(options) {
83
+ super(
84
+ CloudflareAccessErrorCode.AUTH_REQUIRED,
85
+ "Authentication required via Cloudflare Access",
86
+ { requestUrl: _optionalChain([options, 'optionalAccess', _4 => _4.requestUrl]), context: _optionalChain([options, 'optionalAccess', _5 => _5.context]) }
87
+ );
88
+ this.name = "AuthRequiredError";
89
+ }
90
+ };
91
+ var InvalidTokenError = class extends CloudflareAccessError {
92
+
93
+ constructor(reason, options) {
94
+ super(CloudflareAccessErrorCode.INVALID_TOKEN, `Invalid authentication token: ${reason}`, {
95
+ requestUrl: _optionalChain([options, 'optionalAccess', _6 => _6.requestUrl])
96
+ });
97
+ this.name = "InvalidTokenError";
98
+ this.reason = reason;
99
+ }
100
+ };
101
+ var AccessDeniedError = class extends CloudflareAccessError {
102
+
103
+ constructor(email, options) {
104
+ super(CloudflareAccessErrorCode.ACCESS_DENIED, `Access denied for ${email}`, {
105
+ requestUrl: _optionalChain([options, 'optionalAccess', _7 => _7.requestUrl]),
106
+ context: { email, allowedEmails: _optionalChain([options, 'optionalAccess', _8 => _8.allowedEmails]) }
107
+ });
108
+ this.name = "AccessDeniedError";
109
+ this.email = email;
110
+ }
111
+ };
112
+ var ConfigurationError = class extends CloudflareAccessError {
113
+ constructor(message, options) {
114
+ super(CloudflareAccessErrorCode.MISSING_CONFIG, message, options);
115
+ this.name = "ConfigurationError";
116
+ }
117
+ };
118
+ function isCloudflareAccessError(error) {
119
+ return error instanceof CloudflareAccessError;
120
+ }
121
+ function isAuthRequiredError(error) {
122
+ return error instanceof AuthRequiredError;
123
+ }
124
+ function isInvalidTokenError(error) {
125
+ return error instanceof InvalidTokenError;
126
+ }
127
+ function isAccessDeniedError(error) {
128
+ return error instanceof AccessDeniedError;
129
+ }
130
+ function isConfigurationError(error) {
131
+ return error instanceof ConfigurationError;
132
+ }
133
+ function toAuthError(error) {
134
+ if (isCloudflareAccessError(error)) {
135
+ return error;
136
+ }
137
+ if (error instanceof Error) {
138
+ return new CloudflareAccessError(CloudflareAccessErrorCode.INVALID_TOKEN, error.message, {
139
+ cause: error
140
+ });
141
+ }
142
+ return new CloudflareAccessError(
143
+ CloudflareAccessErrorCode.INVALID_TOKEN,
144
+ "Unknown authentication error",
145
+ { context: { error } }
146
+ );
147
+ }
148
+
149
+ // src/core/jwks.ts
150
+ var _jose = require('jose');
151
+ var jwksCache = /* @__PURE__ */ new Map();
152
+ function __clearJwksCache() {
153
+ jwksCache.clear();
154
+ }
155
+ function getRemoteJwks(teamDomain) {
156
+ const cached = jwksCache.get(teamDomain);
157
+ if (cached) {
158
+ return cached;
159
+ }
160
+ const jwks = _jose.createRemoteJWKSet.call(void 0, new URL(`${teamDomain}/cdn-cgi/access/certs`));
161
+ jwksCache.set(teamDomain, jwks);
162
+ return jwks;
163
+ }
164
+ function isLocalDevelopmentRequest(url) {
165
+ try {
166
+ const hostname = new URL(url).hostname;
167
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname.endsWith(".localhost");
168
+ } catch (e) {
169
+ return false;
170
+ }
171
+ }
172
+
173
+ // src/core/config.ts
174
+ function normalizeTeamDomain(teamDomain) {
175
+ return teamDomain.replace(/\/+$/, "");
176
+ }
177
+ function validateAccessConfig(config, requestUrl) {
178
+ const teamDomain = normalizeTeamDomain(config.teamDomain);
179
+ if (!teamDomain.startsWith("https://") || !teamDomain.endsWith(".cloudflareaccess.com")) {
180
+ throw new ConfigurationError(`Invalid Cloudflare Access team domain: ${config.teamDomain}`, {
181
+ context: { requestUrl, expectedFormat: "https://<team>.cloudflareaccess.com" }
182
+ });
183
+ }
184
+ if (!config.audTag) {
185
+ throw new ConfigurationError("Missing Cloudflare Access audience tag", {
186
+ context: {
187
+ requestUrl,
188
+ expectedFormat: "Application AUD tag from Cloudflare Access dashboard"
189
+ }
190
+ });
191
+ }
192
+ return { teamDomain, audTag: config.audTag };
193
+ }
194
+ function getCloudflareAccessConfigFromEnv(env) {
195
+ const teamDomain = env.CF_ACCESS_TEAM_DOMAIN;
196
+ const audTag = env.CF_ACCESS_AUD;
197
+ if (!teamDomain || !audTag) {
198
+ const missing = [!teamDomain && "CF_ACCESS_TEAM_DOMAIN", !audTag && "CF_ACCESS_AUD"].filter(Boolean).join(" and ");
199
+ throw new ConfigurationError(`Missing Cloudflare Access bindings: ${missing}`, {
200
+ context: {
201
+ expectedFormat: "CF_ACCESS_TEAM_DOMAIN=https://<team>.cloudflareaccess.com, CF_ACCESS_AUD=<audience-tag>"
202
+ }
203
+ });
204
+ }
205
+ return { teamDomain, audTag };
206
+ }
207
+
208
+ // src/core/validator.ts
209
+
210
+ async function validateCloudflareAccessToken(token, options, requestUrl) {
211
+ const { accessConfig, allowedEmails, skipInDev, environment } = options;
212
+ const isDev = environment !== "prod";
213
+ if (!token) {
214
+ if (isDev && skipInDev && isLocalDevelopmentRequest(requestUrl)) {
215
+ return { success: true, user: null };
216
+ }
217
+ return {
218
+ success: false,
219
+ error: {
220
+ code: CloudflareAccessErrorCode.AUTH_REQUIRED,
221
+ message: "Unauthorized",
222
+ why: "Missing CF-Access-JWT-Assertion header",
223
+ fix: "Sign in via Cloudflare Access",
224
+ context: { requestUrl }
225
+ }
226
+ };
227
+ }
228
+ try {
229
+ const { teamDomain, audTag } = validateAccessConfig(accessConfig, requestUrl);
230
+ const jwks = getRemoteJwks(teamDomain);
231
+ const { payload } = await _jose.jwtVerify.call(void 0, token, jwks, {
232
+ issuer: teamDomain,
233
+ audience: audTag,
234
+ algorithms: ["RS256"]
235
+ });
236
+ const accessPayload = payload;
237
+ const email = accessPayload.email;
238
+ if (!email) {
239
+ throw new InvalidTokenError("Email not found in validated Cloudflare Access token", {
240
+ requestUrl
241
+ });
242
+ }
243
+ if (allowedEmails && !allowedEmails.includes(email)) {
244
+ return {
245
+ success: false,
246
+ user: {
247
+ email,
248
+ userId: typeof accessPayload.sub === "string" ? accessPayload.sub : void 0,
249
+ country: accessPayload.country
250
+ },
251
+ error: {
252
+ code: CloudflareAccessErrorCode.ACCESS_DENIED,
253
+ message: "Forbidden",
254
+ why: "Your email is not authorized to access this resource",
255
+ fix: "Contact an administrator if you need access",
256
+ context: {
257
+ email,
258
+ allowedEmails,
259
+ requestUrl
260
+ }
261
+ }
262
+ };
263
+ }
264
+ return {
265
+ success: true,
266
+ user: {
267
+ email,
268
+ userId: typeof accessPayload.sub === "string" ? accessPayload.sub : void 0,
269
+ country: accessPayload.country
270
+ }
271
+ };
272
+ } catch (error) {
273
+ if (error instanceof CloudflareAccessError) {
274
+ return {
275
+ success: false,
276
+ error: {
277
+ code: error.code,
278
+ message: error.message,
279
+ why: error.message,
280
+ fix: _optionalChain([error, 'access', _9 => _9.context, 'optionalAccess', _10 => _10.fix]) || "Please sign in again via Cloudflare Access",
281
+ context: error.context
282
+ }
283
+ };
284
+ }
285
+ const reason = error instanceof Error ? error.message : "Token validation failed";
286
+ return {
287
+ success: false,
288
+ error: {
289
+ code: CloudflareAccessErrorCode.INVALID_TOKEN,
290
+ message: "Invalid authentication token",
291
+ why: reason,
292
+ fix: "Please sign in again via Cloudflare Access",
293
+ context: { requestUrl, originalError: reason }
294
+ }
295
+ };
296
+ }
297
+ }
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
+
308
+
309
+
310
+
311
+
312
+
313
+
314
+
315
+
316
+
317
+
318
+
319
+ exports.__decorateClass = __decorateClass; exports.CloudflareAccessErrorCode = CloudflareAccessErrorCode; exports.CloudflareAccessError = CloudflareAccessError; exports.AuthRequiredError = AuthRequiredError; exports.InvalidTokenError = InvalidTokenError; exports.AccessDeniedError = AccessDeniedError; exports.ConfigurationError = ConfigurationError; exports.isCloudflareAccessError = isCloudflareAccessError; exports.isAuthRequiredError = isAuthRequiredError; exports.isInvalidTokenError = isInvalidTokenError; exports.isAccessDeniedError = isAccessDeniedError; exports.isConfigurationError = isConfigurationError; exports.toAuthError = toAuthError; exports.__clearJwksCache = __clearJwksCache; exports.getRemoteJwks = getRemoteJwks; exports.isLocalDevelopmentRequest = isLocalDevelopmentRequest; exports.validateAccessConfig = validateAccessConfig; exports.getCloudflareAccessConfigFromEnv = getCloudflareAccessConfigFromEnv; exports.validateCloudflareAccessToken = validateCloudflareAccessToken;
320
+ //# sourceMappingURL=chunk-WUJPWM4T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/v000281/personal/hono-cloudflare-access-middleware/dist/chunk-WUJPWM4T.js","../src/core/types.ts","../src/core/errors.ts","../src/core/jwks.ts","../src/core/config.ts","../src/core/validator.ts"],"names":[],"mappings":"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","file":"/Users/v000281/personal/hono-cloudflare-access-middleware/dist/chunk-WUJPWM4T.js","sourcesContent":[null,"import type { JWTPayload } from \"jose\";\n\n/**\n * Cloudflare Access JWT payload with additional claims\n */\nexport interface CloudflareAccessPayload extends JWTPayload {\n /** User's email address */\n email?: string;\n /** Token type */\n type?: string;\n /** Identity nonce for additional verification */\n identity_nonce?: string;\n /** User's country */\n country?: string;\n}\n\n/**\n * Cloudflare Access configuration\n */\nexport interface CloudflareAccessConfig {\n /** Exact Cloudflare Access issuer domain, e.g. https://myteam.cloudflareaccess.com */\n teamDomain: string;\n /** Exact Access application audience tag */\n audTag: string;\n}\n\n/**\n * User information extracted from Cloudflare Access token\n */\nexport interface CloudflareAccessUser {\n email: string;\n userId?: string;\n country?: string;\n}\n\n/**\n * Expected environment bindings for Cloudflare Access\n */\nexport interface CloudflareAccessMiddlewareEnv {\n CF_ACCESS_TEAM_DOMAIN?: string;\n CF_ACCESS_AUD?: string;\n ENVIRONMENT?: string;\n}\n\n/**\n * Error codes for Cloudflare Access authentication\n */\nexport const CloudflareAccessErrorCode = {\n /** Missing or invalid authentication token */\n AUTH_REQUIRED: \"AUTH_REQUIRED\",\n /** Token validation failed (expired, wrong signature, etc.) */\n INVALID_TOKEN: \"INVALID_TOKEN\",\n /** User email not in allowlist */\n ACCESS_DENIED: \"ACCESS_DENIED\",\n /** Invalid team domain configuration */\n INVALID_TEAM_DOMAIN: \"INVALID_TEAM_DOMAIN\",\n /** Missing audience tag configuration */\n MISSING_AUDIENCE_TAG: \"MISSING_AUDIENCE_TAG\",\n /** Missing environment configuration */\n MISSING_CONFIG: \"MISSING_CONFIG\",\n /** JWKS fetch failed */\n JWKS_FETCH_ERROR: \"JWKS_FETCH_ERROR\",\n} as const;\n\nexport type CloudflareAccessErrorCode =\n (typeof CloudflareAccessErrorCode)[keyof typeof CloudflareAccessErrorCode];\n\n/**\n * Rich authentication error with actionable information\n */\nexport interface AuthError {\n code: CloudflareAccessErrorCode;\n message: string;\n why: string;\n fix: string;\n context?: Record<string, unknown>;\n}\n\n/**\n * Authentication result\n */\nexport type AuthResult =\n | { success: true; user: CloudflareAccessUser | null; error?: never }\n | { success: false; user?: CloudflareAccessUser | null; error: AuthError };\n","import { CloudflareAccessErrorCode } from \"./types\";\n\n/**\n * Base error class for Cloudflare Access authentication errors\n */\nexport class CloudflareAccessError extends Error {\n readonly code: CloudflareAccessErrorCode;\n readonly context?: Record<string, unknown>;\n readonly requestUrl?: string;\n readonly timestamp: string;\n\n constructor(\n code: CloudflareAccessErrorCode,\n message: string,\n options?: {\n cause?: Error;\n context?: Record<string, unknown>;\n requestUrl?: string;\n },\n ) {\n super(message, { cause: options?.cause });\n this.name = \"CloudflareAccessError\";\n this.code = code;\n this.context = options?.context;\n this.requestUrl = options?.requestUrl;\n this.timestamp = new Date().toISOString();\n }\n\n /**\n * Get a user-friendly error message with fix instructions\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n timestamp: this.timestamp,\n context: this.context,\n fix: this.getFixInstructions(),\n };\n }\n\n /**\n * Get fix instructions based on error code\n */\n private getFixInstructions(): string {\n switch (this.code) {\n case CloudflareAccessErrorCode.AUTH_REQUIRED:\n return \"Ensure you're accessing through Cloudflare Access or provide a valid CF-Access-JWT-Assertion token\";\n case CloudflareAccessErrorCode.INVALID_TOKEN:\n return \"Your session may have expired. Please re-authenticate through Cloudflare Access\";\n case CloudflareAccessErrorCode.ACCESS_DENIED:\n return \"Contact your administrator to request access\";\n case CloudflareAccessErrorCode.MISSING_CONFIG:\n return \"Set CF_ACCESS_TEAM_DOMAIN and CF_ACCESS_AUD environment variables\";\n case CloudflareAccessErrorCode.INVALID_TEAM_DOMAIN:\n return \"Verify your team domain URL format (should be https://yourteam.cloudflareaccess.com)\";\n case CloudflareAccessErrorCode.MISSING_AUDIENCE_TAG:\n return \"Set CF_ACCESS_AUD to your application's audience tag\";\n case CloudflareAccessErrorCode.JWKS_FETCH_ERROR:\n return \"Unable to fetch signing keys. Check network connectivity and team domain\";\n default:\n return \"Check Cloudflare Access configuration and try again\";\n }\n }\n}\n\n/**\n * Error thrown when authentication is required but missing/invalid\n */\nexport class AuthRequiredError extends CloudflareAccessError {\n constructor(options?: { requestUrl?: string; context?: Record<string, unknown> }) {\n super(\n CloudflareAccessErrorCode.AUTH_REQUIRED,\n \"Authentication required via Cloudflare Access\",\n { requestUrl: options?.requestUrl, context: options?.context },\n );\n this.name = \"AuthRequiredError\";\n }\n}\n\n/**\n * Error thrown when token validation fails\n */\nexport class InvalidTokenError extends CloudflareAccessError {\n readonly reason: string;\n\n constructor(reason: string, options?: { requestUrl?: string }) {\n super(CloudflareAccessErrorCode.INVALID_TOKEN, `Invalid authentication token: ${reason}`, {\n requestUrl: options?.requestUrl,\n });\n this.name = \"InvalidTokenError\";\n this.reason = reason;\n }\n}\n\n/**\n * Error thrown when user is not in email allowlist\n */\nexport class AccessDeniedError extends CloudflareAccessError {\n readonly email: string;\n\n constructor(email: string, options?: { requestUrl?: string; allowedEmails?: string[] }) {\n super(CloudflareAccessErrorCode.ACCESS_DENIED, `Access denied for ${email}`, {\n requestUrl: options?.requestUrl,\n context: { email, allowedEmails: options?.allowedEmails },\n });\n this.name = \"AccessDeniedError\";\n this.email = email;\n }\n}\n\n/**\n * Error thrown when configuration is invalid or missing\n */\nexport class ConfigurationError extends CloudflareAccessError {\n constructor(message: string, options?: { cause?: Error; context?: Record<string, unknown> }) {\n super(CloudflareAccessErrorCode.MISSING_CONFIG, message, options);\n this.name = \"ConfigurationError\";\n }\n}\n\n/**\n * Type guard to check if error is a CloudflareAccessError\n */\nexport function isCloudflareAccessError(error: unknown): error is CloudflareAccessError {\n return error instanceof CloudflareAccessError;\n}\n\n/**\n * Type guard for specific error types\n */\nexport function isAuthRequiredError(error: unknown): error is AuthRequiredError {\n return error instanceof AuthRequiredError;\n}\n\nexport function isInvalidTokenError(error: unknown): error is InvalidTokenError {\n return error instanceof InvalidTokenError;\n}\n\nexport function isAccessDeniedError(error: unknown): error is AccessDeniedError {\n return error instanceof AccessDeniedError;\n}\n\nexport function isConfigurationError(error: unknown): error is ConfigurationError {\n return error instanceof ConfigurationError;\n}\n\n/**\n * Convert unknown error to CloudflareAccessError\n */\nexport function toAuthError(error: unknown): CloudflareAccessError {\n if (isCloudflareAccessError(error)) {\n return error;\n }\n\n if (error instanceof Error) {\n return new CloudflareAccessError(CloudflareAccessErrorCode.INVALID_TOKEN, error.message, {\n cause: error,\n });\n }\n\n return new CloudflareAccessError(\n CloudflareAccessErrorCode.INVALID_TOKEN,\n \"Unknown authentication error\",\n { context: { error } },\n );\n}\n","import { createRemoteJWKSet } from \"jose\";\n\n/** JWK Set cache by team domain */\nconst jwksCache = new Map<string, ReturnType<typeof createRemoteJWKSet>>();\n\n/**\n * Clear the JWKS cache. Useful for testing.\n * @internal\n */\nexport function __clearJwksCache(): void {\n jwksCache.clear();\n}\n\n/**\n * Get or create cached JWKS for a team domain\n */\nexport function getRemoteJwks(teamDomain: string): ReturnType<typeof createRemoteJWKSet> {\n const cached = jwksCache.get(teamDomain);\n if (cached) {\n return cached;\n }\n\n const jwks = createRemoteJWKSet(new URL(`${teamDomain}/cdn-cgi/access/certs`));\n jwksCache.set(teamDomain, jwks);\n return jwks;\n}\n\n/**\n * Check if request is from local development\n */\nexport function isLocalDevelopmentRequest(url: string): boolean {\n try {\n const hostname = new URL(url).hostname;\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"[::1]\" ||\n hostname.endsWith(\".localhost\")\n );\n } catch {\n return false;\n }\n}\n","import { type CloudflareAccessConfig, type CloudflareAccessMiddlewareEnv } from \"./types\";\nimport { ConfigurationError } from \"./errors\";\n\n/**\n * Remove trailing slashes from team domain\n */\nfunction normalizeTeamDomain(teamDomain: string): string {\n return teamDomain.replace(/\\/+$/, \"\");\n}\n\n/**\n * Validate and normalize access configuration\n */\nexport function validateAccessConfig(\n config: CloudflareAccessConfig,\n requestUrl?: string,\n): CloudflareAccessConfig {\n const teamDomain = normalizeTeamDomain(config.teamDomain);\n\n if (!teamDomain.startsWith(\"https://\") || !teamDomain.endsWith(\".cloudflareaccess.com\")) {\n throw new ConfigurationError(`Invalid Cloudflare Access team domain: ${config.teamDomain}`, {\n context: { requestUrl, expectedFormat: \"https://<team>.cloudflareaccess.com\" },\n });\n }\n\n if (!config.audTag) {\n throw new ConfigurationError(\"Missing Cloudflare Access audience tag\", {\n context: {\n requestUrl,\n expectedFormat: \"Application AUD tag from Cloudflare Access dashboard\",\n },\n });\n }\n\n return { teamDomain, audTag: config.audTag };\n}\n\n/**\n * Get Cloudflare Access configuration from environment variables/bindings\n */\nexport function getCloudflareAccessConfigFromEnv(\n env: CloudflareAccessMiddlewareEnv,\n): CloudflareAccessConfig {\n const teamDomain = env.CF_ACCESS_TEAM_DOMAIN;\n const audTag = env.CF_ACCESS_AUD;\n\n if (!teamDomain || !audTag) {\n const missing = [!teamDomain && \"CF_ACCESS_TEAM_DOMAIN\", !audTag && \"CF_ACCESS_AUD\"]\n .filter(Boolean)\n .join(\" and \");\n\n throw new ConfigurationError(`Missing Cloudflare Access bindings: ${missing}`, {\n context: {\n expectedFormat:\n \"CF_ACCESS_TEAM_DOMAIN=https://<team>.cloudflareaccess.com, CF_ACCESS_AUD=<audience-tag>\",\n },\n });\n }\n\n return { teamDomain, audTag };\n}\n","import { jwtVerify } from \"jose\";\nimport {\n CloudflareAccessErrorCode,\n type CloudflareAccessConfig,\n type CloudflareAccessPayload,\n type AuthResult,\n} from \"./types\";\nimport { validateAccessConfig } from \"./config\";\nimport { getRemoteJwks, isLocalDevelopmentRequest } from \"./jwks\";\nimport { InvalidTokenError, CloudflareAccessError } from \"./errors\";\n\n/**\n * Options for token validation\n */\nexport interface ValidateTokenOptions {\n /** Cloudflare Access configuration */\n accessConfig: CloudflareAccessConfig;\n /** Optional email allowlist */\n allowedEmails?: string[];\n /** Whether to skip JWT validation outside production */\n skipInDev?: boolean;\n /** Environment indicator */\n environment?: string;\n}\n\n/**\n * Validate Cloudflare Access JWT token\n */\nexport async function validateCloudflareAccessToken(\n token: string | undefined,\n options: ValidateTokenOptions,\n requestUrl: string,\n): Promise<AuthResult> {\n const { accessConfig, allowedEmails, skipInDev, environment } = options;\n const isDev = environment !== \"prod\";\n\n // Skip OPTIONS requests\n if (!token) {\n // Check if we should skip auth in dev\n if (isDev && skipInDev && isLocalDevelopmentRequest(requestUrl)) {\n return { success: true, user: null };\n }\n\n return {\n success: false,\n error: {\n code: CloudflareAccessErrorCode.AUTH_REQUIRED,\n message: \"Unauthorized\",\n why: \"Missing CF-Access-JWT-Assertion header\",\n fix: \"Sign in via Cloudflare Access\",\n context: { requestUrl },\n },\n };\n }\n\n try {\n const { teamDomain, audTag } = validateAccessConfig(accessConfig, requestUrl);\n const jwks = getRemoteJwks(teamDomain);\n\n // Verify the JWT token\n const { payload } = await jwtVerify(token, jwks, {\n issuer: teamDomain,\n audience: audTag,\n algorithms: [\"RS256\"],\n });\n\n const accessPayload = payload as CloudflareAccessPayload;\n const email = accessPayload.email;\n\n if (!email) {\n throw new InvalidTokenError(\"Email not found in validated Cloudflare Access token\", {\n requestUrl,\n });\n }\n\n // Check email allowlist if configured\n if (allowedEmails && !allowedEmails.includes(email)) {\n return {\n success: false,\n user: {\n email,\n userId: typeof accessPayload.sub === \"string\" ? accessPayload.sub : undefined,\n country: accessPayload.country,\n },\n error: {\n code: CloudflareAccessErrorCode.ACCESS_DENIED,\n message: \"Forbidden\",\n why: \"Your email is not authorized to access this resource\",\n fix: \"Contact an administrator if you need access\",\n context: {\n email,\n allowedEmails,\n requestUrl,\n },\n },\n };\n }\n\n return {\n success: true,\n user: {\n email,\n userId: typeof accessPayload.sub === \"string\" ? accessPayload.sub : undefined,\n country: accessPayload.country,\n },\n };\n } catch (error) {\n if (error instanceof CloudflareAccessError) {\n return {\n success: false,\n error: {\n code: error.code,\n message: error.message,\n why: error.message,\n fix: (error.context?.fix as string) || \"Please sign in again via Cloudflare Access\",\n context: error.context,\n },\n };\n }\n\n const reason = error instanceof Error ? error.message : \"Token validation failed\";\n return {\n success: false,\n error: {\n code: CloudflareAccessErrorCode.INVALID_TOKEN,\n message: \"Invalid authentication token\",\n why: reason,\n fix: \"Please sign in again via Cloudflare Access\",\n context: { requestUrl, originalError: reason },\n },\n };\n }\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { e as CloudflareAccessMiddlewareEnv, C as CloudflareAccessConfig } from './jwks-ChdyyS_L.mjs';
2
+
3
+ /**
4
+ * Validate and normalize access configuration
5
+ */
6
+ declare function validateAccessConfig(config: CloudflareAccessConfig, requestUrl?: string): CloudflareAccessConfig;
7
+ /**
8
+ * Get Cloudflare Access configuration from environment variables/bindings
9
+ */
10
+ declare function getCloudflareAccessConfigFromEnv(env: CloudflareAccessMiddlewareEnv): CloudflareAccessConfig;
11
+
12
+ export { getCloudflareAccessConfigFromEnv as g, validateAccessConfig as v };
@@ -0,0 +1,12 @@
1
+ import { e as CloudflareAccessMiddlewareEnv, C as CloudflareAccessConfig } from './jwks-ChdyyS_L.js';
2
+
3
+ /**
4
+ * Validate and normalize access configuration
5
+ */
6
+ declare function validateAccessConfig(config: CloudflareAccessConfig, requestUrl?: string): CloudflareAccessConfig;
7
+ /**
8
+ * Get Cloudflare Access configuration from environment variables/bindings
9
+ */
10
+ declare function getCloudflareAccessConfigFromEnv(env: CloudflareAccessMiddlewareEnv): CloudflareAccessConfig;
11
+
12
+ export { getCloudflareAccessConfigFromEnv as g, validateAccessConfig as v };
@@ -0,0 +1,24 @@
1
+ import { C as CloudflareAccessConfig, b as AuthResult } from '../jwks-ChdyyS_L.mjs';
2
+ export { A as AccessDeniedError, n as AuthError, a as AuthRequiredError, c as CloudflareAccessError, d as CloudflareAccessErrorCode, e as CloudflareAccessMiddlewareEnv, f as CloudflareAccessPayload, g as CloudflareAccessUser, h as ConfigurationError, I as InvalidTokenError, _ as __clearJwksCache, o as getRemoteJwks, i as isAccessDeniedError, j as isAuthRequiredError, k as isCloudflareAccessError, l as isConfigurationError, m as isInvalidTokenError, p as isLocalDevelopmentRequest, t as toAuthError } from '../jwks-ChdyyS_L.mjs';
3
+ export { g as getCloudflareAccessConfigFromEnv, v as validateAccessConfig } from '../config-D4O7DXNT.mjs';
4
+ import 'jose';
5
+
6
+ /**
7
+ * Options for token validation
8
+ */
9
+ interface ValidateTokenOptions {
10
+ /** Cloudflare Access configuration */
11
+ accessConfig: CloudflareAccessConfig;
12
+ /** Optional email allowlist */
13
+ allowedEmails?: string[];
14
+ /** Whether to skip JWT validation outside production */
15
+ skipInDev?: boolean;
16
+ /** Environment indicator */
17
+ environment?: string;
18
+ }
19
+ /**
20
+ * Validate Cloudflare Access JWT token
21
+ */
22
+ declare function validateCloudflareAccessToken(token: string | undefined, options: ValidateTokenOptions, requestUrl: string): Promise<AuthResult>;
23
+
24
+ export { AuthResult, CloudflareAccessConfig, type ValidateTokenOptions, validateCloudflareAccessToken };
@@ -0,0 +1,24 @@
1
+ import { C as CloudflareAccessConfig, b as AuthResult } from '../jwks-ChdyyS_L.js';
2
+ export { A as AccessDeniedError, n as AuthError, a as AuthRequiredError, c as CloudflareAccessError, d as CloudflareAccessErrorCode, e as CloudflareAccessMiddlewareEnv, f as CloudflareAccessPayload, g as CloudflareAccessUser, h as ConfigurationError, I as InvalidTokenError, _ as __clearJwksCache, o as getRemoteJwks, i as isAccessDeniedError, j as isAuthRequiredError, k as isCloudflareAccessError, l as isConfigurationError, m as isInvalidTokenError, p as isLocalDevelopmentRequest, t as toAuthError } from '../jwks-ChdyyS_L.js';
3
+ export { g as getCloudflareAccessConfigFromEnv, v as validateAccessConfig } from '../config-ottUdc-K.js';
4
+ import 'jose';
5
+
6
+ /**
7
+ * Options for token validation
8
+ */
9
+ interface ValidateTokenOptions {
10
+ /** Cloudflare Access configuration */
11
+ accessConfig: CloudflareAccessConfig;
12
+ /** Optional email allowlist */
13
+ allowedEmails?: string[];
14
+ /** Whether to skip JWT validation outside production */
15
+ skipInDev?: boolean;
16
+ /** Environment indicator */
17
+ environment?: string;
18
+ }
19
+ /**
20
+ * Validate Cloudflare Access JWT token
21
+ */
22
+ declare function validateCloudflareAccessToken(token: string | undefined, options: ValidateTokenOptions, requestUrl: string): Promise<AuthResult>;
23
+
24
+ export { AuthResult, CloudflareAccessConfig, type ValidateTokenOptions, validateCloudflareAccessToken };
@@ -0,0 +1,41 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+ var _chunkWUJPWM4Tjs = require('../chunk-WUJPWM4T.js');
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+ exports.AccessDeniedError = _chunkWUJPWM4Tjs.AccessDeniedError; exports.AuthRequiredError = _chunkWUJPWM4Tjs.AuthRequiredError; exports.CloudflareAccessError = _chunkWUJPWM4Tjs.CloudflareAccessError; exports.CloudflareAccessErrorCode = _chunkWUJPWM4Tjs.CloudflareAccessErrorCode; exports.ConfigurationError = _chunkWUJPWM4Tjs.ConfigurationError; exports.InvalidTokenError = _chunkWUJPWM4Tjs.InvalidTokenError; exports.__clearJwksCache = _chunkWUJPWM4Tjs.__clearJwksCache; exports.getCloudflareAccessConfigFromEnv = _chunkWUJPWM4Tjs.getCloudflareAccessConfigFromEnv; exports.getRemoteJwks = _chunkWUJPWM4Tjs.getRemoteJwks; exports.isAccessDeniedError = _chunkWUJPWM4Tjs.isAccessDeniedError; exports.isAuthRequiredError = _chunkWUJPWM4Tjs.isAuthRequiredError; exports.isCloudflareAccessError = _chunkWUJPWM4Tjs.isCloudflareAccessError; exports.isConfigurationError = _chunkWUJPWM4Tjs.isConfigurationError; exports.isInvalidTokenError = _chunkWUJPWM4Tjs.isInvalidTokenError; exports.isLocalDevelopmentRequest = _chunkWUJPWM4Tjs.isLocalDevelopmentRequest; exports.toAuthError = _chunkWUJPWM4Tjs.toAuthError; exports.validateAccessConfig = _chunkWUJPWM4Tjs.validateAccessConfig; exports.validateCloudflareAccessToken = _chunkWUJPWM4Tjs.validateCloudflareAccessToken;
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/v000281/personal/hono-cloudflare-access-middleware/dist/core/index.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,uDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,6uCAAC","file":"/Users/v000281/personal/hono-cloudflare-access-middleware/dist/core/index.js"}
@@ -0,0 +1,41 @@
1
+ import {
2
+ AccessDeniedError,
3
+ AuthRequiredError,
4
+ CloudflareAccessError,
5
+ CloudflareAccessErrorCode,
6
+ ConfigurationError,
7
+ InvalidTokenError,
8
+ __clearJwksCache,
9
+ getCloudflareAccessConfigFromEnv,
10
+ getRemoteJwks,
11
+ isAccessDeniedError,
12
+ isAuthRequiredError,
13
+ isCloudflareAccessError,
14
+ isConfigurationError,
15
+ isInvalidTokenError,
16
+ isLocalDevelopmentRequest,
17
+ toAuthError,
18
+ validateAccessConfig,
19
+ validateCloudflareAccessToken
20
+ } from "../chunk-DM2KGIQX.mjs";
21
+ export {
22
+ AccessDeniedError,
23
+ AuthRequiredError,
24
+ CloudflareAccessError,
25
+ CloudflareAccessErrorCode,
26
+ ConfigurationError,
27
+ InvalidTokenError,
28
+ __clearJwksCache,
29
+ getCloudflareAccessConfigFromEnv,
30
+ getRemoteJwks,
31
+ isAccessDeniedError,
32
+ isAuthRequiredError,
33
+ isCloudflareAccessError,
34
+ isConfigurationError,
35
+ isInvalidTokenError,
36
+ isLocalDevelopmentRequest,
37
+ toAuthError,
38
+ validateAccessConfig,
39
+ validateCloudflareAccessToken
40
+ };
41
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,6 @@
1
+ export { A as AccessDeniedError, a as AuthRequiredError, b as AuthResult, C as CloudflareAccessConfig, c as CloudflareAccessError, d as CloudflareAccessErrorCode, e as CloudflareAccessMiddlewareEnv, f as CloudflareAccessPayload, g as CloudflareAccessUser, h as ConfigurationError, I as InvalidTokenError, _ as __clearJwksCache, i as isAccessDeniedError, j as isAuthRequiredError, k as isCloudflareAccessError, l as isConfigurationError, m as isInvalidTokenError, t as toAuthError } from './jwks-ChdyyS_L.mjs';
2
+ export { g as getCloudflareAccessConfigFromEnv } from './config-D4O7DXNT.mjs';
3
+ export { validateCloudflareAccessToken } from './core/index.mjs';
4
+ export { C as CloudflareAccessAuthOptions, a as CloudflareAccessConfigResolver, b as CloudflareAccessHono, c as CloudflareAccessVariables, d as createCloudflareAccessAuth, g as getCloudflareAccessConfigFromBindings } from './middleware-BDl6jUCu.mjs';
5
+ import 'jose';
6
+ import 'hono';
@@ -0,0 +1,6 @@
1
+ export { A as AccessDeniedError, a as AuthRequiredError, b as AuthResult, C as CloudflareAccessConfig, c as CloudflareAccessError, d as CloudflareAccessErrorCode, e as CloudflareAccessMiddlewareEnv, f as CloudflareAccessPayload, g as CloudflareAccessUser, h as ConfigurationError, I as InvalidTokenError, _ as __clearJwksCache, i as isAccessDeniedError, j as isAuthRequiredError, k as isCloudflareAccessError, l as isConfigurationError, m as isInvalidTokenError, t as toAuthError } from './jwks-ChdyyS_L.js';
2
+ export { g as getCloudflareAccessConfigFromEnv } from './config-ottUdc-K.js';
3
+ export { validateCloudflareAccessToken } from './core/index.js';
4
+ export { C as CloudflareAccessAuthOptions, a as CloudflareAccessConfigResolver, b as CloudflareAccessHono, c as CloudflareAccessVariables, d as createCloudflareAccessAuth, g as getCloudflareAccessConfigFromBindings } from './middleware-CgFsjM20.js';
5
+ import 'jose';
6
+ import 'hono';
package/dist/index.js ADDED
@@ -0,0 +1,41 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+ var _chunkPMFPT3SIjs = require('./chunk-PMFPT3SI.js');
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+ var _chunkWUJPWM4Tjs = require('./chunk-WUJPWM4T.js');
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+ exports.AccessDeniedError = _chunkWUJPWM4Tjs.AccessDeniedError; exports.AuthRequiredError = _chunkWUJPWM4Tjs.AuthRequiredError; exports.CloudflareAccessError = _chunkWUJPWM4Tjs.CloudflareAccessError; exports.CloudflareAccessErrorCode = _chunkWUJPWM4Tjs.CloudflareAccessErrorCode; exports.ConfigurationError = _chunkWUJPWM4Tjs.ConfigurationError; exports.InvalidTokenError = _chunkWUJPWM4Tjs.InvalidTokenError; exports.__clearJwksCache = _chunkWUJPWM4Tjs.__clearJwksCache; exports.createCloudflareAccessAuth = _chunkPMFPT3SIjs.createCloudflareAccessAuth; exports.getCloudflareAccessConfigFromBindings = _chunkPMFPT3SIjs.getCloudflareAccessConfigFromBindings; exports.getCloudflareAccessConfigFromEnv = _chunkWUJPWM4Tjs.getCloudflareAccessConfigFromEnv; exports.isAccessDeniedError = _chunkWUJPWM4Tjs.isAccessDeniedError; exports.isAuthRequiredError = _chunkWUJPWM4Tjs.isAuthRequiredError; exports.isCloudflareAccessError = _chunkWUJPWM4Tjs.isCloudflareAccessError; exports.isConfigurationError = _chunkWUJPWM4Tjs.isConfigurationError; exports.isInvalidTokenError = _chunkWUJPWM4Tjs.isInvalidTokenError; exports.toAuthError = _chunkWUJPWM4Tjs.toAuthError; exports.validateCloudflareAccessToken = _chunkWUJPWM4Tjs.validateCloudflareAccessToken;
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/v000281/personal/hono-cloudflare-access-middleware/dist/index.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACF,sDAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,ytCAAC","file":"/Users/v000281/personal/hono-cloudflare-access-middleware/dist/index.js"}
package/dist/index.mjs ADDED
@@ -0,0 +1,41 @@
1
+ import {
2
+ createCloudflareAccessAuth,
3
+ getCloudflareAccessConfigFromBindings
4
+ } from "./chunk-LQWCGHLJ.mjs";
5
+ import {
6
+ AccessDeniedError,
7
+ AuthRequiredError,
8
+ CloudflareAccessError,
9
+ CloudflareAccessErrorCode,
10
+ ConfigurationError,
11
+ InvalidTokenError,
12
+ __clearJwksCache,
13
+ getCloudflareAccessConfigFromEnv,
14
+ isAccessDeniedError,
15
+ isAuthRequiredError,
16
+ isCloudflareAccessError,
17
+ isConfigurationError,
18
+ isInvalidTokenError,
19
+ toAuthError,
20
+ validateCloudflareAccessToken
21
+ } from "./chunk-DM2KGIQX.mjs";
22
+ export {
23
+ AccessDeniedError,
24
+ AuthRequiredError,
25
+ CloudflareAccessError,
26
+ CloudflareAccessErrorCode,
27
+ ConfigurationError,
28
+ InvalidTokenError,
29
+ __clearJwksCache,
30
+ createCloudflareAccessAuth,
31
+ getCloudflareAccessConfigFromBindings,
32
+ getCloudflareAccessConfigFromEnv,
33
+ isAccessDeniedError,
34
+ isAuthRequiredError,
35
+ isCloudflareAccessError,
36
+ isConfigurationError,
37
+ isInvalidTokenError,
38
+ toAuthError,
39
+ validateCloudflareAccessToken
40
+ };
41
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}