@omg-dev/auth 0.4.24

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,43 @@
1
+ import { createRemoteJWKSet, jwtVerify } from "jose";
2
+ //#region src/index.ts
3
+ const DEFAULT_JWKS_URL = "https://auth.omg.dev/.well-known/jwks.json";
4
+ const DEFAULT_ISSUER = "https://auth.omg.dev";
5
+ /**
6
+ * Creates an auth middleware for the given mode.
7
+ * - "vibes": verifies JWT Bearer token via JWKS endpoint
8
+ * - "local": returns null (unauthenticated / no auth required)
9
+ */
10
+ function createAuthMiddleware(mode, options) {
11
+ if (mode === "local") return async () => null;
12
+ const jwksUrl = options?.jwksUrl ?? DEFAULT_JWKS_URL;
13
+ const issuer = options?.issuer ?? DEFAULT_ISSUER;
14
+ const audience = options?.audience;
15
+ const algorithms = options?.algorithms ?? ["ES256"];
16
+ const JWKS = createRemoteJWKSet(new URL(jwksUrl));
17
+ return async (req) => {
18
+ const authHeader = req.headers.get("authorization") ?? "";
19
+ if (!authHeader.startsWith("Bearer ")) return null;
20
+ const token = authHeader.slice(7).trim();
21
+ if (!token) return null;
22
+ try {
23
+ const { payload } = await jwtVerify(token, JWKS, {
24
+ algorithms,
25
+ issuer,
26
+ ...audience ? { audience } : {}
27
+ });
28
+ const userId = payload.sub;
29
+ if (!userId) return null;
30
+ if (userId.startsWith("svc:")) return null;
31
+ return {
32
+ userId,
33
+ userEmail: payload.email,
34
+ userName: payload.name,
35
+ appId: payload.appId
36
+ };
37
+ } catch {
38
+ return null;
39
+ }
40
+ };
41
+ }
42
+ //#endregion
43
+ export { createAuthMiddleware };
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@omg-dev/auth",
3
+ "version": "0.4.24",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./src/index.ts",
8
+ "default": "./dist/index.mjs"
9
+ }
10
+ },
11
+ "dependencies": {
12
+ "jose": "^5.0.0"
13
+ },
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/BennyKok/vibes.git"
18
+ },
19
+ "homepage": "https://docs.omg.dev",
20
+ "files": [
21
+ "dist",
22
+ "src"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public",
26
+ "registry": "https://registry.npmjs.org/"
27
+ }
28
+ }
package/src/index.ts ADDED
@@ -0,0 +1,77 @@
1
+ // @omg-dev/auth — Server-side JWT verification middleware
2
+ //
3
+ // Verifies JWT tokens issued by auth.omg.dev using JWKS.
4
+
5
+ import { createRemoteJWKSet, jwtVerify, type JWTPayload } from "jose"
6
+
7
+ export type AuthMode = "vibes" | "local"
8
+
9
+ export interface AuthResult {
10
+ userId: string
11
+ userEmail?: string
12
+ userName?: string
13
+ appId?: string
14
+ }
15
+
16
+ interface VibesJWTPayload extends JWTPayload {
17
+ email?: string
18
+ name?: string
19
+ appId?: string
20
+ }
21
+
22
+ const DEFAULT_JWKS_URL = "https://auth.omg.dev/.well-known/jwks.json"
23
+ const DEFAULT_ISSUER = "https://auth.omg.dev"
24
+
25
+ /**
26
+ * Creates an auth middleware for the given mode.
27
+ * - "vibes": verifies JWT Bearer token via JWKS endpoint
28
+ * - "local": returns null (unauthenticated / no auth required)
29
+ */
30
+ export function createAuthMiddleware(
31
+ mode: AuthMode,
32
+ options?: { jwksUrl?: string; issuer?: string; audience?: string | string[]; algorithms?: string[] }
33
+ ): (req: Request) => Promise<AuthResult | null> {
34
+ if (mode === "local") {
35
+ return async () => null
36
+ }
37
+
38
+ const jwksUrl = options?.jwksUrl ?? DEFAULT_JWKS_URL
39
+ const issuer = options?.issuer ?? DEFAULT_ISSUER
40
+ const audience = options?.audience
41
+ // Default to ES256 (auth.omg.dev's /token-minted JWTs). The OAuth provider
42
+ // at /api/auth/jwks signs access tokens with EdDSA, so callers verifying
43
+ // those must pass algorithms: ["EdDSA"] + the matching jwksUrl.
44
+ const algorithms = options?.algorithms ?? ["ES256"]
45
+ const JWKS = createRemoteJWKSet(new URL(jwksUrl))
46
+
47
+ return async (req: Request): Promise<AuthResult | null> => {
48
+ const authHeader = req.headers.get("authorization") ?? ""
49
+ if (!authHeader.startsWith("Bearer ")) return null
50
+
51
+ const token = authHeader.slice(7).trim()
52
+ if (!token) return null
53
+
54
+ try {
55
+ const { payload } = await jwtVerify(token, JWKS, {
56
+ algorithms,
57
+ issuer,
58
+ ...(audience ? { audience } : {}),
59
+ }) as { payload: VibesJWTPayload }
60
+
61
+ const userId = payload.sub
62
+ if (!userId) return null
63
+ // Service-principal tokens (sub="svc:*") are minted for infra-to-infra
64
+ // calls; user-facing apps must never accept them as a logged-in user.
65
+ if (userId.startsWith("svc:")) return null
66
+
67
+ return {
68
+ userId,
69
+ userEmail: payload.email,
70
+ userName: payload.name,
71
+ appId: payload.appId,
72
+ }
73
+ } catch {
74
+ return null
75
+ }
76
+ }
77
+ }