@orangecheck/me-client 0.5.0 → 0.6.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.
@@ -0,0 +1,51 @@
1
+ import { VerifyOcOptions, SessionRequestHeaders, SessionPayload } from '@orangecheck/auth-core';
2
+ export { SessionPayload, VerifyOcOptions, verifyOcToken } from '@orangecheck/auth-core';
3
+
4
+ declare function getOcSession(headers: SessionRequestHeaders | Headers, options?: VerifyOcOptions): Promise<SessionPayload | null>;
5
+ interface NextApiRequestLike {
6
+ headers: {
7
+ cookie?: string;
8
+ authorization?: string;
9
+ [k: string]: unknown;
10
+ };
11
+ ocSession?: SessionPayload | null;
12
+ }
13
+ interface NextApiResponseLike {
14
+ status(code: number): NextApiResponseLike;
15
+ json(body: unknown): unknown;
16
+ setHeader(name: string, value: string | number | readonly string[]): unknown;
17
+ }
18
+ type NextApiHandlerLike = (req: NextApiRequestLike, res: NextApiResponseLike) => unknown | Promise<unknown>;
19
+ interface WithOcAuthOptions extends VerifyOcOptions {
20
+ required?: boolean;
21
+ }
22
+ declare function withOcAuth<T extends NextApiHandlerLike>(handler: T, options?: WithOcAuthOptions): T;
23
+ interface ExpressRequestLike {
24
+ headers: {
25
+ cookie?: string;
26
+ authorization?: string;
27
+ [k: string]: unknown;
28
+ };
29
+ ocSession?: SessionPayload | null;
30
+ }
31
+ interface ExpressResponseLike {
32
+ status(code: number): ExpressResponseLike;
33
+ json(body: unknown): unknown;
34
+ setHeader(name: string, value: string | number | readonly string[]): unknown;
35
+ }
36
+ type ExpressNextLike = (err?: unknown) => void;
37
+ declare function ocAuthExpress(options?: WithOcAuthOptions): (req: ExpressRequestLike, res: ExpressResponseLike, next: ExpressNextLike) => Promise<void>;
38
+ interface HonoContextLike {
39
+ req: {
40
+ raw: {
41
+ headers: Headers;
42
+ };
43
+ };
44
+ set(key: string, value: unknown): void;
45
+ json(body: unknown, status?: number): unknown;
46
+ header(name: string, value: string): void;
47
+ }
48
+ type HonoNextLike = () => Promise<void>;
49
+ declare function ocAuthHono(options?: WithOcAuthOptions): (c: HonoContextLike, next: HonoNextLike) => Promise<unknown>;
50
+
51
+ export { type WithOcAuthOptions, getOcSession, ocAuthExpress, ocAuthHono, withOcAuth };
package/dist/server.js ADDED
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ var authCore = require('@orangecheck/auth-core');
4
+
5
+ // src/server.ts
6
+ async function getOcSession(headers, options = {}) {
7
+ return authCore.getOcSession(headers, options);
8
+ }
9
+ function withOcAuth(handler, options = {}) {
10
+ const wrapped = async (req, res) => {
11
+ res.setHeader("Cache-Control", "no-store, private");
12
+ res.setHeader("Vary", "Cookie, Authorization");
13
+ const session = await getOcSession(
14
+ {
15
+ cookie: typeof req.headers.cookie === "string" ? req.headers.cookie : null,
16
+ authorization: typeof req.headers.authorization === "string" ? req.headers.authorization : null
17
+ },
18
+ options
19
+ );
20
+ req.ocSession = session;
21
+ if (options.required && !session) {
22
+ return res.status(401).json({ ok: false, reason: "unauthenticated" });
23
+ }
24
+ return handler(req, res);
25
+ };
26
+ return wrapped;
27
+ }
28
+ function ocAuthExpress(options = {}) {
29
+ return async (req, res, next) => {
30
+ try {
31
+ res.setHeader("Vary", "Cookie, Authorization");
32
+ const session = await getOcSession(
33
+ {
34
+ cookie: typeof req.headers.cookie === "string" ? req.headers.cookie : null,
35
+ authorization: typeof req.headers.authorization === "string" ? req.headers.authorization : null
36
+ },
37
+ options
38
+ );
39
+ req.ocSession = session;
40
+ if (options.required && !session) {
41
+ res.status(401).json({ ok: false, reason: "unauthenticated" });
42
+ return;
43
+ }
44
+ next();
45
+ } catch (err) {
46
+ next(err);
47
+ }
48
+ };
49
+ }
50
+ function ocAuthHono(options = {}) {
51
+ return async (c, next) => {
52
+ c.header("Vary", "Cookie, Authorization");
53
+ const session = await getOcSession(c.req.raw.headers, options);
54
+ c.set("ocSession", session);
55
+ if (options.required && !session) {
56
+ return c.json({ ok: false, reason: "unauthenticated" }, 401);
57
+ }
58
+ await next();
59
+ };
60
+ }
61
+
62
+ Object.defineProperty(exports, "verifyOcToken", {
63
+ enumerable: true,
64
+ get: function () { return authCore.verifyOcToken; }
65
+ });
66
+ exports.getOcSession = getOcSession;
67
+ exports.ocAuthExpress = ocAuthExpress;
68
+ exports.ocAuthHono = ocAuthHono;
69
+ exports.withOcAuth = withOcAuth;
70
+ //# sourceMappingURL=server.js.map
71
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts"],"names":["getOcSessionCore"],"mappings":"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","file":"server.js","sourcesContent":["/**\n * @orangecheck/me-client/server\n *\n * Server-side verification helpers for OC integrators.\n *\n * import { withOcAuth, getOcSession, verifyOcToken } from '@orangecheck/me-client/server';\n *\n * Zero env vars, zero JWK handling. Internally lazy-fetches the auth\n * host's JWKS at https://ochk.io/.well-known/jwks.json and caches it\n * in-process. Integrators write code; we handle the crypto.\n *\n * Three layers, smallest to thickest:\n *\n * verifyOcToken(token) → SessionPayload | null\n * getOcSession(headers) → SessionPayload | null (cookie OR Bearer)\n * withOcAuth(handler) → Next.js Pages adapter that injects\n * req.ocSession on the request object\n * ocAuthExpress(opts?) → Express / Connect middleware\n * ocAuthHono(opts?) → Hono middleware\n *\n * All thin wrappers around `getOcSession`. Bring your own framework.\n */\n\nimport {\n getOcSession as getOcSessionCore,\n verifyOcToken,\n type SessionPayload,\n type VerifyOcOptions,\n type SessionRequestHeaders,\n} from '@orangecheck/auth-core';\n\nexport { verifyOcToken };\nexport type { SessionPayload, VerifyOcOptions };\n\n/**\n * Verify the OC session for a request. Accepts either:\n *\n * - A Web Headers object (Hono / edge / Fetch API): `c.req.raw.headers`\n * - A plain `{ cookie, authorization }` object (Express / Next.js Pages /\n * Fastify / etc.): `{ cookie: req.headers.cookie, authorization: req.headers.authorization }`\n *\n * Reads the `oc_session` cookie first; falls back to\n * `Authorization: Bearer <token>` so cross-domain integrators (no\n * .ochk.io cookie reach) verify the same way.\n *\n * Returns `null` for unauthenticated requests. Never throws.\n */\nexport async function getOcSession(\n headers: SessionRequestHeaders | Headers,\n options: VerifyOcOptions = {}\n): Promise<SessionPayload | null> {\n return getOcSessionCore(headers, options);\n}\n\n// ─── Next.js Pages Router adapter ────────────────────────────────────────\n\ninterface NextApiRequestLike {\n headers: { cookie?: string; authorization?: string; [k: string]: unknown };\n ocSession?: SessionPayload | null;\n}\ninterface NextApiResponseLike {\n status(code: number): NextApiResponseLike;\n json(body: unknown): unknown;\n setHeader(name: string, value: string | number | readonly string[]): unknown;\n}\ntype NextApiHandlerLike = (req: NextApiRequestLike, res: NextApiResponseLike) => unknown | Promise<unknown>;\n\nexport interface WithOcAuthOptions extends VerifyOcOptions {\n /** When true, unauthenticated requests get a 401 + `{ok:false}` response\n * before the wrapped handler runs. Default: false — handler runs and\n * receives `req.ocSession === null`, useful when the route serves both\n * signed-in and anonymous users. */\n required?: boolean;\n}\n\n/**\n * Wrap a Next.js Pages-Router API route handler. Adds `req.ocSession` —\n * the verified SessionPayload, or null when unauthenticated.\n *\n * // pages/api/me/profile.ts\n * import { withOcAuth } from '@orangecheck/me-client/server';\n *\n * export default withOcAuth(async (req, res) => {\n * if (!req.ocSession) return res.status(401).json({ ok: false });\n * res.status(200).json({ account: { address: req.ocSession.addr } });\n * }, { required: true });\n *\n * `Cache-Control: no-store, private` and `Vary: Cookie, Authorization`\n * are set on every authenticated response — without them a cached 401\n * leaks anonymous to authenticated callers.\n */\nexport function withOcAuth<T extends NextApiHandlerLike>(\n handler: T,\n options: WithOcAuthOptions = {}\n): T {\n const wrapped = async (req: NextApiRequestLike, res: NextApiResponseLike) => {\n res.setHeader('Cache-Control', 'no-store, private');\n res.setHeader('Vary', 'Cookie, Authorization');\n const session = await getOcSession(\n {\n cookie: typeof req.headers.cookie === 'string' ? req.headers.cookie : null,\n authorization:\n typeof req.headers.authorization === 'string'\n ? req.headers.authorization\n : null,\n },\n options\n );\n req.ocSession = session;\n if (options.required && !session) {\n return res.status(401).json({ ok: false, reason: 'unauthenticated' });\n }\n return handler(req, res);\n };\n return wrapped as unknown as T;\n}\n\n// ─── Express / Connect middleware ────────────────────────────────────────\n\ninterface ExpressRequestLike {\n headers: { cookie?: string; authorization?: string; [k: string]: unknown };\n ocSession?: SessionPayload | null;\n}\ninterface ExpressResponseLike {\n status(code: number): ExpressResponseLike;\n json(body: unknown): unknown;\n setHeader(name: string, value: string | number | readonly string[]): unknown;\n}\ntype ExpressNextLike = (err?: unknown) => void;\n\n/**\n * Express / Connect middleware. Attaches `req.ocSession` (verified\n * SessionPayload | null) and calls next(). Use it as a global middleware\n * or per-route.\n *\n * import express from 'express';\n * import { ocAuthExpress } from '@orangecheck/me-client/server';\n *\n * const app = express();\n * app.use(ocAuthExpress());\n *\n * app.get('/api/profile', (req, res) => {\n * if (!req.ocSession) return res.status(401).json({ error: 'sign in' });\n * res.json({ address: req.ocSession.addr });\n * });\n *\n * Pass `{ required: true }` to short-circuit unauthenticated requests\n * with a 401 before they reach your handler.\n */\nexport function ocAuthExpress(options: WithOcAuthOptions = {}) {\n return async (req: ExpressRequestLike, res: ExpressResponseLike, next: ExpressNextLike) => {\n try {\n res.setHeader('Vary', 'Cookie, Authorization');\n const session = await getOcSession(\n {\n cookie: typeof req.headers.cookie === 'string' ? req.headers.cookie : null,\n authorization:\n typeof req.headers.authorization === 'string'\n ? req.headers.authorization\n : null,\n },\n options\n );\n req.ocSession = session;\n if (options.required && !session) {\n res.status(401).json({ ok: false, reason: 'unauthenticated' });\n return;\n }\n next();\n } catch (err) {\n next(err);\n }\n };\n}\n\n// ─── Hono middleware ─────────────────────────────────────────────────────\n\ninterface HonoContextLike {\n req: { raw: { headers: Headers } };\n set(key: string, value: unknown): void;\n json(body: unknown, status?: number): unknown;\n header(name: string, value: string): void;\n}\ntype HonoNextLike = () => Promise<void>;\n\n/**\n * Hono middleware. Attaches the verified session at `c.get('ocSession')`.\n *\n * import { Hono } from 'hono';\n * import { ocAuthHono } from '@orangecheck/me-client/server';\n *\n * const app = new Hono();\n * app.use('*', ocAuthHono());\n *\n * app.get('/api/profile', (c) => {\n * const session = c.get('ocSession');\n * if (!session) return c.json({ error: 'sign in' }, 401);\n * return c.json({ address: session.addr });\n * });\n */\nexport function ocAuthHono(options: WithOcAuthOptions = {}) {\n return async (c: HonoContextLike, next: HonoNextLike) => {\n c.header('Vary', 'Cookie, Authorization');\n const session = await getOcSession(c.req.raw.headers, options);\n c.set('ocSession', session);\n if (options.required && !session) {\n return c.json({ ok: false, reason: 'unauthenticated' }, 401);\n }\n await next();\n };\n}\n"]}
@@ -0,0 +1,63 @@
1
+ import { getOcSession as getOcSession$1 } from '@orangecheck/auth-core';
2
+ export { verifyOcToken } from '@orangecheck/auth-core';
3
+
4
+ // src/server.ts
5
+ async function getOcSession(headers, options = {}) {
6
+ return getOcSession$1(headers, options);
7
+ }
8
+ function withOcAuth(handler, options = {}) {
9
+ const wrapped = async (req, res) => {
10
+ res.setHeader("Cache-Control", "no-store, private");
11
+ res.setHeader("Vary", "Cookie, Authorization");
12
+ const session = await getOcSession(
13
+ {
14
+ cookie: typeof req.headers.cookie === "string" ? req.headers.cookie : null,
15
+ authorization: typeof req.headers.authorization === "string" ? req.headers.authorization : null
16
+ },
17
+ options
18
+ );
19
+ req.ocSession = session;
20
+ if (options.required && !session) {
21
+ return res.status(401).json({ ok: false, reason: "unauthenticated" });
22
+ }
23
+ return handler(req, res);
24
+ };
25
+ return wrapped;
26
+ }
27
+ function ocAuthExpress(options = {}) {
28
+ return async (req, res, next) => {
29
+ try {
30
+ res.setHeader("Vary", "Cookie, Authorization");
31
+ const session = await getOcSession(
32
+ {
33
+ cookie: typeof req.headers.cookie === "string" ? req.headers.cookie : null,
34
+ authorization: typeof req.headers.authorization === "string" ? req.headers.authorization : null
35
+ },
36
+ options
37
+ );
38
+ req.ocSession = session;
39
+ if (options.required && !session) {
40
+ res.status(401).json({ ok: false, reason: "unauthenticated" });
41
+ return;
42
+ }
43
+ next();
44
+ } catch (err) {
45
+ next(err);
46
+ }
47
+ };
48
+ }
49
+ function ocAuthHono(options = {}) {
50
+ return async (c, next) => {
51
+ c.header("Vary", "Cookie, Authorization");
52
+ const session = await getOcSession(c.req.raw.headers, options);
53
+ c.set("ocSession", session);
54
+ if (options.required && !session) {
55
+ return c.json({ ok: false, reason: "unauthenticated" }, 401);
56
+ }
57
+ await next();
58
+ };
59
+ }
60
+
61
+ export { getOcSession, ocAuthExpress, ocAuthHono, withOcAuth };
62
+ //# sourceMappingURL=server.mjs.map
63
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts"],"names":["getOcSessionCore"],"mappings":";;;;AA+CA,eAAsB,YAAA,CAClB,OAAA,EACA,OAAA,GAA2B,EAAC,EACE;AAC9B,EAAA,OAAOA,cAAA,CAAiB,SAAS,OAAO,CAAA;AAC5C;AAuCO,SAAS,UAAA,CACZ,OAAA,EACA,OAAA,GAA6B,EAAC,EAC7B;AACD,EAAA,MAAM,OAAA,GAAU,OAAO,GAAA,EAAyB,GAAA,KAA6B;AACzE,IAAA,GAAA,CAAI,SAAA,CAAU,iBAAiB,mBAAmB,CAAA;AAClD,IAAA,GAAA,CAAI,SAAA,CAAU,QAAQ,uBAAuB,CAAA;AAC7C,IAAA,MAAM,UAAU,MAAM,YAAA;AAAA,MAClB;AAAA,QACI,MAAA,EAAQ,OAAO,GAAA,CAAI,OAAA,CAAQ,WAAW,QAAA,GAAW,GAAA,CAAI,QAAQ,MAAA,GAAS,IAAA;AAAA,QACtE,aAAA,EACI,OAAO,GAAA,CAAI,OAAA,CAAQ,kBAAkB,QAAA,GAC/B,GAAA,CAAI,QAAQ,aAAA,GACZ;AAAA,OACd;AAAA,MACA;AAAA,KACJ;AACA,IAAA,GAAA,CAAI,SAAA,GAAY,OAAA;AAChB,IAAA,IAAI,OAAA,CAAQ,QAAA,IAAY,CAAC,OAAA,EAAS;AAC9B,MAAA,OAAO,GAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,EAAE,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,iBAAA,EAAmB,CAAA;AAAA,IACxE;AACA,IAAA,OAAO,OAAA,CAAQ,KAAK,GAAG,CAAA;AAAA,EAC3B,CAAA;AACA,EAAA,OAAO,OAAA;AACX;AAkCO,SAAS,aAAA,CAAc,OAAA,GAA6B,EAAC,EAAG;AAC3D,EAAA,OAAO,OAAO,GAAA,EAAyB,GAAA,EAA0B,IAAA,KAA0B;AACvF,IAAA,IAAI;AACA,MAAA,GAAA,CAAI,SAAA,CAAU,QAAQ,uBAAuB,CAAA;AAC7C,MAAA,MAAM,UAAU,MAAM,YAAA;AAAA,QAClB;AAAA,UACI,MAAA,EAAQ,OAAO,GAAA,CAAI,OAAA,CAAQ,WAAW,QAAA,GAAW,GAAA,CAAI,QAAQ,MAAA,GAAS,IAAA;AAAA,UACtE,aAAA,EACI,OAAO,GAAA,CAAI,OAAA,CAAQ,kBAAkB,QAAA,GAC/B,GAAA,CAAI,QAAQ,aAAA,GACZ;AAAA,SACd;AAAA,QACA;AAAA,OACJ;AACA,MAAA,GAAA,CAAI,SAAA,GAAY,OAAA;AAChB,MAAA,IAAI,OAAA,CAAQ,QAAA,IAAY,CAAC,OAAA,EAAS;AAC9B,QAAA,GAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,EAAE,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,iBAAA,EAAmB,CAAA;AAC7D,QAAA;AAAA,MACJ;AACA,MAAA,IAAA,EAAK;AAAA,IACT,SAAS,GAAA,EAAK;AACV,MAAA,IAAA,CAAK,GAAG,CAAA;AAAA,IACZ;AAAA,EACJ,CAAA;AACJ;AA2BO,SAAS,UAAA,CAAW,OAAA,GAA6B,EAAC,EAAG;AACxD,EAAA,OAAO,OAAO,GAAoB,IAAA,KAAuB;AACrD,IAAA,CAAA,CAAE,MAAA,CAAO,QAAQ,uBAAuB,CAAA;AACxC,IAAA,MAAM,UAAU,MAAM,YAAA,CAAa,EAAE,GAAA,CAAI,GAAA,CAAI,SAAS,OAAO,CAAA;AAC7D,IAAA,CAAA,CAAE,GAAA,CAAI,aAAa,OAAO,CAAA;AAC1B,IAAA,IAAI,OAAA,CAAQ,QAAA,IAAY,CAAC,OAAA,EAAS;AAC9B,MAAA,OAAO,CAAA,CAAE,KAAK,EAAE,EAAA,EAAI,OAAO,MAAA,EAAQ,iBAAA,IAAqB,GAAG,CAAA;AAAA,IAC/D;AACA,IAAA,MAAM,IAAA,EAAK;AAAA,EACf,CAAA;AACJ","file":"server.mjs","sourcesContent":["/**\n * @orangecheck/me-client/server\n *\n * Server-side verification helpers for OC integrators.\n *\n * import { withOcAuth, getOcSession, verifyOcToken } from '@orangecheck/me-client/server';\n *\n * Zero env vars, zero JWK handling. Internally lazy-fetches the auth\n * host's JWKS at https://ochk.io/.well-known/jwks.json and caches it\n * in-process. Integrators write code; we handle the crypto.\n *\n * Three layers, smallest to thickest:\n *\n * verifyOcToken(token) → SessionPayload | null\n * getOcSession(headers) → SessionPayload | null (cookie OR Bearer)\n * withOcAuth(handler) → Next.js Pages adapter that injects\n * req.ocSession on the request object\n * ocAuthExpress(opts?) → Express / Connect middleware\n * ocAuthHono(opts?) → Hono middleware\n *\n * All thin wrappers around `getOcSession`. Bring your own framework.\n */\n\nimport {\n getOcSession as getOcSessionCore,\n verifyOcToken,\n type SessionPayload,\n type VerifyOcOptions,\n type SessionRequestHeaders,\n} from '@orangecheck/auth-core';\n\nexport { verifyOcToken };\nexport type { SessionPayload, VerifyOcOptions };\n\n/**\n * Verify the OC session for a request. Accepts either:\n *\n * - A Web Headers object (Hono / edge / Fetch API): `c.req.raw.headers`\n * - A plain `{ cookie, authorization }` object (Express / Next.js Pages /\n * Fastify / etc.): `{ cookie: req.headers.cookie, authorization: req.headers.authorization }`\n *\n * Reads the `oc_session` cookie first; falls back to\n * `Authorization: Bearer <token>` so cross-domain integrators (no\n * .ochk.io cookie reach) verify the same way.\n *\n * Returns `null` for unauthenticated requests. Never throws.\n */\nexport async function getOcSession(\n headers: SessionRequestHeaders | Headers,\n options: VerifyOcOptions = {}\n): Promise<SessionPayload | null> {\n return getOcSessionCore(headers, options);\n}\n\n// ─── Next.js Pages Router adapter ────────────────────────────────────────\n\ninterface NextApiRequestLike {\n headers: { cookie?: string; authorization?: string; [k: string]: unknown };\n ocSession?: SessionPayload | null;\n}\ninterface NextApiResponseLike {\n status(code: number): NextApiResponseLike;\n json(body: unknown): unknown;\n setHeader(name: string, value: string | number | readonly string[]): unknown;\n}\ntype NextApiHandlerLike = (req: NextApiRequestLike, res: NextApiResponseLike) => unknown | Promise<unknown>;\n\nexport interface WithOcAuthOptions extends VerifyOcOptions {\n /** When true, unauthenticated requests get a 401 + `{ok:false}` response\n * before the wrapped handler runs. Default: false — handler runs and\n * receives `req.ocSession === null`, useful when the route serves both\n * signed-in and anonymous users. */\n required?: boolean;\n}\n\n/**\n * Wrap a Next.js Pages-Router API route handler. Adds `req.ocSession` —\n * the verified SessionPayload, or null when unauthenticated.\n *\n * // pages/api/me/profile.ts\n * import { withOcAuth } from '@orangecheck/me-client/server';\n *\n * export default withOcAuth(async (req, res) => {\n * if (!req.ocSession) return res.status(401).json({ ok: false });\n * res.status(200).json({ account: { address: req.ocSession.addr } });\n * }, { required: true });\n *\n * `Cache-Control: no-store, private` and `Vary: Cookie, Authorization`\n * are set on every authenticated response — without them a cached 401\n * leaks anonymous to authenticated callers.\n */\nexport function withOcAuth<T extends NextApiHandlerLike>(\n handler: T,\n options: WithOcAuthOptions = {}\n): T {\n const wrapped = async (req: NextApiRequestLike, res: NextApiResponseLike) => {\n res.setHeader('Cache-Control', 'no-store, private');\n res.setHeader('Vary', 'Cookie, Authorization');\n const session = await getOcSession(\n {\n cookie: typeof req.headers.cookie === 'string' ? req.headers.cookie : null,\n authorization:\n typeof req.headers.authorization === 'string'\n ? req.headers.authorization\n : null,\n },\n options\n );\n req.ocSession = session;\n if (options.required && !session) {\n return res.status(401).json({ ok: false, reason: 'unauthenticated' });\n }\n return handler(req, res);\n };\n return wrapped as unknown as T;\n}\n\n// ─── Express / Connect middleware ────────────────────────────────────────\n\ninterface ExpressRequestLike {\n headers: { cookie?: string; authorization?: string; [k: string]: unknown };\n ocSession?: SessionPayload | null;\n}\ninterface ExpressResponseLike {\n status(code: number): ExpressResponseLike;\n json(body: unknown): unknown;\n setHeader(name: string, value: string | number | readonly string[]): unknown;\n}\ntype ExpressNextLike = (err?: unknown) => void;\n\n/**\n * Express / Connect middleware. Attaches `req.ocSession` (verified\n * SessionPayload | null) and calls next(). Use it as a global middleware\n * or per-route.\n *\n * import express from 'express';\n * import { ocAuthExpress } from '@orangecheck/me-client/server';\n *\n * const app = express();\n * app.use(ocAuthExpress());\n *\n * app.get('/api/profile', (req, res) => {\n * if (!req.ocSession) return res.status(401).json({ error: 'sign in' });\n * res.json({ address: req.ocSession.addr });\n * });\n *\n * Pass `{ required: true }` to short-circuit unauthenticated requests\n * with a 401 before they reach your handler.\n */\nexport function ocAuthExpress(options: WithOcAuthOptions = {}) {\n return async (req: ExpressRequestLike, res: ExpressResponseLike, next: ExpressNextLike) => {\n try {\n res.setHeader('Vary', 'Cookie, Authorization');\n const session = await getOcSession(\n {\n cookie: typeof req.headers.cookie === 'string' ? req.headers.cookie : null,\n authorization:\n typeof req.headers.authorization === 'string'\n ? req.headers.authorization\n : null,\n },\n options\n );\n req.ocSession = session;\n if (options.required && !session) {\n res.status(401).json({ ok: false, reason: 'unauthenticated' });\n return;\n }\n next();\n } catch (err) {\n next(err);\n }\n };\n}\n\n// ─── Hono middleware ─────────────────────────────────────────────────────\n\ninterface HonoContextLike {\n req: { raw: { headers: Headers } };\n set(key: string, value: unknown): void;\n json(body: unknown, status?: number): unknown;\n header(name: string, value: string): void;\n}\ntype HonoNextLike = () => Promise<void>;\n\n/**\n * Hono middleware. Attaches the verified session at `c.get('ocSession')`.\n *\n * import { Hono } from 'hono';\n * import { ocAuthHono } from '@orangecheck/me-client/server';\n *\n * const app = new Hono();\n * app.use('*', ocAuthHono());\n *\n * app.get('/api/profile', (c) => {\n * const session = c.get('ocSession');\n * if (!session) return c.json({ error: 'sign in' }, 401);\n * return c.json({ address: session.addr });\n * });\n */\nexport function ocAuthHono(options: WithOcAuthOptions = {}) {\n return async (c: HonoContextLike, next: HonoNextLike) => {\n c.header('Vary', 'Cookie, Authorization');\n const session = await getOcSession(c.req.raw.headers, options);\n c.set('ocSession', session);\n if (options.required && !session) {\n return c.json({ ok: false, reason: 'unauthenticated' }, 401);\n }\n await next();\n };\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orangecheck/me-client",
3
- "version": "0.5.0",
4
- "description": "Drop-in client for me.ochk.io. Sign-in-with-OC button, useOcSession, oc.session/payment/config/delegation/webhook/event, the canonical billable-event taxonomy as types.",
3
+ "version": "0.6.0",
4
+ "description": "Drop-in client for me.ochk.io. Three entry points: React surface (OcSignInButton, useOcSession), server-side verification (withOcAuth for Next.js, ocAuthExpress, ocAuthHono — zero env vars, zero JWK handling), and a browser-only popup orchestrator (signInWithOc). Plus session lifecycle hooks, payment authorization, and the canonical billable-event taxonomy as types.",
5
5
  "keywords": [
6
6
  "orangecheck",
7
7
  "bitcoin",
@@ -30,6 +30,16 @@
30
30
  "types": "./dist/index.d.ts",
31
31
  "import": "./dist/index.mjs",
32
32
  "require": "./dist/index.js"
33
+ },
34
+ "./server": {
35
+ "types": "./dist/server.d.ts",
36
+ "import": "./dist/server.mjs",
37
+ "require": "./dist/server.js"
38
+ },
39
+ "./popup": {
40
+ "types": "./dist/popup.d.ts",
41
+ "import": "./dist/popup.mjs",
42
+ "require": "./dist/popup.js"
33
43
  }
34
44
  },
35
45
  "files": [
@@ -46,8 +56,7 @@
46
56
  "prepublishOnly": "npm run clean && npm run build"
47
57
  },
48
58
  "dependencies": {
49
- "@noble/curves": "^1.6.0",
50
- "@noble/hashes": "^1.5.0"
59
+ "@orangecheck/auth-core": "^0.3.0"
51
60
  },
52
61
  "peerDependencies": {
53
62
  "@orangecheck/auth-client": "^0.4.0",