@superfunctions/oauth-router 0.0.1
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 +49 -0
- package/dist/browser-routes.d.ts +22 -0
- package/dist/browser-routes.d.ts.map +1 -0
- package/dist/browser-routes.js +175 -0
- package/dist/browser-routes.js.map +1 -0
- package/dist/connection-routes.d.ts +19 -0
- package/dist/connection-routes.d.ts.map +1 -0
- package/dist/connection-routes.js +152 -0
- package/dist/connection-routes.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @superfunctions/oauth-router
|
|
2
|
+
|
|
3
|
+
Reusable OAuth route factories for browser-auth and connection-management flows.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @superfunctions/oauth-router @superfunctions/oauth-flow @superfunctions/http
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Use an HTTP adapter such as `@superfunctions/http-express`, `@superfunctions/http-fastify`, or `@superfunctions/http-hono` in the consuming app.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createOAuthBrowserRoutes } from "@superfunctions/oauth-router";
|
|
17
|
+
|
|
18
|
+
const routes = createOAuthBrowserRoutes({
|
|
19
|
+
basePath: "/auth/social",
|
|
20
|
+
flowService,
|
|
21
|
+
async resolveStartInput(request) {
|
|
22
|
+
return (await request.json()) as never;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Package Boundary
|
|
28
|
+
|
|
29
|
+
`@superfunctions/oauth-router` owns route factories only:
|
|
30
|
+
|
|
31
|
+
- `createOAuthBrowserRoutes(...)`
|
|
32
|
+
- `createOAuthConnectionRoutes(...)`
|
|
33
|
+
- secure default route metadata
|
|
34
|
+
- per-route `routeMeta` overrides
|
|
35
|
+
|
|
36
|
+
It does not create framework servers, resolve sessions, or persist OAuth state by itself.
|
|
37
|
+
|
|
38
|
+
## Production Notes
|
|
39
|
+
|
|
40
|
+
- Browser routes default to `start=none`, `callback=none`, `disconnect=hybrid`.
|
|
41
|
+
- Connection routes default to `start=hybrid`, `callback=none`, `disconnect=hybrid`.
|
|
42
|
+
- Override route metadata explicitly when your app requires stronger auth or different OpenAPI annotations.
|
|
43
|
+
- Keep callback routes reachable without session enforcement unless your app handles provider callbacks through another trust boundary.
|
|
44
|
+
|
|
45
|
+
## Related Packages
|
|
46
|
+
|
|
47
|
+
- OAuth core primitives: [../oauth-core/README.md](../oauth-core/README.md)
|
|
48
|
+
- Flow orchestration: [../oauth-flow/README.md](../oauth-flow/README.md)
|
|
49
|
+
- HTTP primitives: [../oauth-http/README.md](../oauth-http/README.md)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { HttpRouteMeta, Route, RouteContext } from "@superfunctions/http";
|
|
2
|
+
import type { OAuthFlowCallbackInput, OAuthFlowCallbackResult, OAuthFlowDisconnectInput, OAuthFlowService, OAuthFlowStartInput } from "@superfunctions/oauth-flow";
|
|
3
|
+
export type OAuthBrowserCallbackMode = "redirect" | "json";
|
|
4
|
+
export type OAuthBrowserRouteMetaOverrides = {
|
|
5
|
+
start?: HttpRouteMeta;
|
|
6
|
+
callback?: HttpRouteMeta;
|
|
7
|
+
disconnect?: HttpRouteMeta;
|
|
8
|
+
};
|
|
9
|
+
export interface OAuthBrowserRouteConfig {
|
|
10
|
+
basePath: string;
|
|
11
|
+
flowService: OAuthFlowService;
|
|
12
|
+
resolveStartInput: (request: Request, context: RouteContext) => Promise<OAuthFlowStartInput> | OAuthFlowStartInput;
|
|
13
|
+
resolveDisconnectInput?: (request: Request, context: RouteContext) => Promise<Omit<OAuthFlowDisconnectInput, "providerId" | "requestId">> | Omit<OAuthFlowDisconnectInput, "providerId" | "requestId">;
|
|
14
|
+
resolveCallbackInput?: (request: Request, context: RouteContext) => Promise<Partial<Omit<OAuthFlowCallbackInput, "providerId" | "requestId">>> | Partial<Omit<OAuthFlowCallbackInput, "providerId" | "requestId">>;
|
|
15
|
+
callbackMode?: OAuthBrowserCallbackMode | ((result: OAuthFlowCallbackResult, request: Request, context: RouteContext) => Promise<OAuthBrowserCallbackMode> | OAuthBrowserCallbackMode);
|
|
16
|
+
getRedirectLocation?: (result: OAuthFlowCallbackResult, request: Request, context: RouteContext) => Promise<string> | string;
|
|
17
|
+
serializeCallbackResult?: (result: OAuthFlowCallbackResult, request: Request, context: RouteContext) => Promise<unknown> | unknown;
|
|
18
|
+
routeMeta?: OAuthBrowserRouteMetaOverrides;
|
|
19
|
+
requestIdHeader?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function createOAuthBrowserRoutes(config: OAuthBrowserRouteConfig): Route[];
|
|
22
|
+
//# sourceMappingURL=browser-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-routes.d.ts","sourceRoot":"","sources":["../src/browser-routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,aAAa,EAAoB,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAChH,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG,MAAM,CAAC;AAE3D,MAAM,MAAM,8BAA8B,GAAG;IAC3C,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAC;IACnH,sBAAsB,CAAC,EAAE,CACvB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC,IAAI,CAAC,wBAAwB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,wBAAwB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC;IACtI,oBAAoB,CAAC,EAAE,CACrB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC;IACpJ,YAAY,CAAC,EAAE,wBAAwB,GAAG,CAAC,CACzC,MAAM,EAAE,uBAAuB,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC,wBAAwB,CAAC,GAAG,wBAAwB,CAAC,CAAC;IACnE,mBAAmB,CAAC,EAAE,CACpB,MAAM,EAAE,uBAAuB,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAC9B,uBAAuB,CAAC,EAAE,CACxB,MAAM,EAAE,uBAAuB,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAChC,SAAS,CAAC,EAAE,8BAA8B,CAAC;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,uBAAuB,GAAG,KAAK,EAAE,CAsEjF"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { BadRequestError } from "@superfunctions/http";
|
|
2
|
+
export function createOAuthBrowserRoutes(config) {
|
|
3
|
+
const requestIdHeader = (config.requestIdHeader ?? "x-request-id").toLowerCase();
|
|
4
|
+
return [
|
|
5
|
+
{
|
|
6
|
+
method: "POST",
|
|
7
|
+
path: joinPath(config.basePath, "start"),
|
|
8
|
+
meta: resolveRouteMeta({ auth: { mode: "none" } }, config.routeMeta?.start),
|
|
9
|
+
handler: async (request, context) => {
|
|
10
|
+
const requestId = request.headers.get(requestIdHeader) ?? undefined;
|
|
11
|
+
const input = await config.resolveStartInput(request, context);
|
|
12
|
+
const result = await config.flowService.start({
|
|
13
|
+
...input,
|
|
14
|
+
requestId: requestId ?? input.requestId
|
|
15
|
+
});
|
|
16
|
+
return Response.json(result);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
method: "GET",
|
|
21
|
+
path: joinPath(config.basePath, "callback/:provider"),
|
|
22
|
+
meta: resolveRouteMeta({ auth: { mode: "none" } }, config.routeMeta?.callback),
|
|
23
|
+
handler: async (request, context) => {
|
|
24
|
+
const requestId = request.headers.get(requestIdHeader) ?? undefined;
|
|
25
|
+
const resolvedInput = (await config.resolveCallbackInput?.(request, context)) ?? {};
|
|
26
|
+
const url = new URL(request.url);
|
|
27
|
+
const callbackResult = await config.flowService.handleCallback({
|
|
28
|
+
providerId: context.params.provider,
|
|
29
|
+
code: asRequiredString(resolvedInput.code ?? url.searchParams.get("code"), "code"),
|
|
30
|
+
state: asRequiredString(resolvedInput.state ?? url.searchParams.get("state"), "state"),
|
|
31
|
+
redirectUri: asRequiredString(resolvedInput.redirectUri ??
|
|
32
|
+
url.searchParams.get("redirectUri") ??
|
|
33
|
+
inferCallbackRedirectUri(url), "redirectUri"),
|
|
34
|
+
requestId
|
|
35
|
+
});
|
|
36
|
+
const mode = await resolveCallbackMode(config.callbackMode, callbackResult, request, context);
|
|
37
|
+
if (mode === "redirect") {
|
|
38
|
+
const location = await resolveRedirectLocation(config, callbackResult, request, context);
|
|
39
|
+
return Response.redirect(location, 302);
|
|
40
|
+
}
|
|
41
|
+
const payload = config.serializeCallbackResult
|
|
42
|
+
? await config.serializeCallbackResult(callbackResult, request, context)
|
|
43
|
+
: callbackResult;
|
|
44
|
+
return Response.json(payload);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
method: "POST",
|
|
49
|
+
path: joinPath(config.basePath, "disconnect/:provider"),
|
|
50
|
+
meta: resolveRouteMeta({ auth: { mode: "hybrid" } }, config.routeMeta?.disconnect),
|
|
51
|
+
handler: async (request, context) => {
|
|
52
|
+
const requestId = request.headers.get(requestIdHeader) ?? undefined;
|
|
53
|
+
const input = (await config.resolveDisconnectInput?.(request, context)) ??
|
|
54
|
+
(await parseDisconnectBody(request));
|
|
55
|
+
const result = await config.flowService.disconnect({
|
|
56
|
+
...input,
|
|
57
|
+
providerId: context.params.provider,
|
|
58
|
+
requestId
|
|
59
|
+
});
|
|
60
|
+
return Response.json(result);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
function resolveRouteMeta(defaultMeta, overrideMeta) {
|
|
66
|
+
if (!overrideMeta) {
|
|
67
|
+
return defaultMeta;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
...defaultMeta,
|
|
71
|
+
...overrideMeta,
|
|
72
|
+
auth: mergeAuthMeta(defaultMeta.auth, overrideMeta.auth),
|
|
73
|
+
openapi: mergeOpenApiMeta(defaultMeta.openapi, overrideMeta.openapi)
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function mergeAuthMeta(defaultMeta, overrideMeta) {
|
|
77
|
+
if (!defaultMeta) {
|
|
78
|
+
return overrideMeta ? { ...overrideMeta } : undefined;
|
|
79
|
+
}
|
|
80
|
+
if (!overrideMeta) {
|
|
81
|
+
return { ...defaultMeta };
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
...defaultMeta,
|
|
85
|
+
...overrideMeta
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function mergeOpenApiMeta(defaultMeta, overrideMeta) {
|
|
89
|
+
if (!defaultMeta) {
|
|
90
|
+
return overrideMeta ? { ...overrideMeta } : undefined;
|
|
91
|
+
}
|
|
92
|
+
if (!overrideMeta) {
|
|
93
|
+
return { ...defaultMeta };
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
...defaultMeta,
|
|
97
|
+
...overrideMeta
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function joinPath(basePath, suffix) {
|
|
101
|
+
const normalizedBase = basePath.startsWith("/") ? basePath : `/${basePath}`;
|
|
102
|
+
return `${normalizedBase.replace(/\/$/, "")}/${suffix.replace(/^\//, "")}`;
|
|
103
|
+
}
|
|
104
|
+
function asRequiredString(value, field) {
|
|
105
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
106
|
+
throw new BadRequestError(`${field} is required`, "OAUTH_ROUTE_INVALID_INPUT");
|
|
107
|
+
}
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
async function resolveCallbackMode(mode, result, request, context) {
|
|
111
|
+
if (!mode) {
|
|
112
|
+
return "json";
|
|
113
|
+
}
|
|
114
|
+
if (typeof mode === "function") {
|
|
115
|
+
return mode(result, request, context);
|
|
116
|
+
}
|
|
117
|
+
return mode;
|
|
118
|
+
}
|
|
119
|
+
async function resolveRedirectLocation(config, result, request, context) {
|
|
120
|
+
if (config.getRedirectLocation) {
|
|
121
|
+
return config.getRedirectLocation(result, request, context);
|
|
122
|
+
}
|
|
123
|
+
if (result.subject.kind === "browser-auth" && result.subject.returnTo) {
|
|
124
|
+
return result.subject.returnTo;
|
|
125
|
+
}
|
|
126
|
+
return new URL("/", request.url).toString();
|
|
127
|
+
}
|
|
128
|
+
async function parseDisconnectBody(request) {
|
|
129
|
+
const body = asJsonObject(await parseJsonBody(request), "disconnect body");
|
|
130
|
+
return {
|
|
131
|
+
connectionId: asRequiredString(body.connectionId, "connectionId"),
|
|
132
|
+
revokeRemote: asOptionalBoolean(body.revokeRemote, "revokeRemote"),
|
|
133
|
+
tokenTypeHint: asTokenTypeHint(body.tokenTypeHint)
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
async function parseJsonBody(request) {
|
|
137
|
+
try {
|
|
138
|
+
return await request.json();
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
throw new BadRequestError("disconnect body must be valid JSON", "OAUTH_ROUTE_INVALID_INPUT");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function inferCallbackRedirectUri(url) {
|
|
145
|
+
const redirectUrl = new URL(url.toString());
|
|
146
|
+
for (const transientParam of ["code", "state", "redirectUri", "error", "error_description", "error_uri"]) {
|
|
147
|
+
redirectUrl.searchParams.delete(transientParam);
|
|
148
|
+
}
|
|
149
|
+
return redirectUrl.toString();
|
|
150
|
+
}
|
|
151
|
+
function asJsonObject(value, field) {
|
|
152
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
153
|
+
throw new BadRequestError(`${field} must be a JSON object`, "OAUTH_ROUTE_INVALID_INPUT");
|
|
154
|
+
}
|
|
155
|
+
return value;
|
|
156
|
+
}
|
|
157
|
+
function asOptionalBoolean(value, field) {
|
|
158
|
+
if (value === undefined) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
if (typeof value !== "boolean") {
|
|
162
|
+
throw new BadRequestError(`${field} must be a boolean`, "OAUTH_ROUTE_INVALID_INPUT");
|
|
163
|
+
}
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
function asTokenTypeHint(value) {
|
|
167
|
+
if (value === undefined) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
if (value === "access_token" || value === "refresh_token") {
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
throw new BadRequestError("tokenTypeHint must be access_token or refresh_token", "OAUTH_ROUTE_INVALID_INPUT");
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=browser-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-routes.js","sourceRoot":"","sources":["../src/browser-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { HttpRouteMeta, Route, RouteContext } from "@superfunctions/http";
|
|
2
|
+
import type { OAuthFlowCallbackInput, OAuthFlowCallbackResult, OAuthFlowDisconnectInput, OAuthFlowService, OAuthFlowStartInput } from "@superfunctions/oauth-flow";
|
|
3
|
+
export type OAuthConnectionRouteMetaOverrides = {
|
|
4
|
+
start?: HttpRouteMeta;
|
|
5
|
+
callback?: HttpRouteMeta;
|
|
6
|
+
disconnect?: HttpRouteMeta;
|
|
7
|
+
};
|
|
8
|
+
export interface OAuthConnectionRouteConfig {
|
|
9
|
+
basePath: string;
|
|
10
|
+
flowService: OAuthFlowService;
|
|
11
|
+
resolveStartInput: (request: Request, context: RouteContext) => Promise<OAuthFlowStartInput> | OAuthFlowStartInput;
|
|
12
|
+
resolveDisconnectInput?: (request: Request, context: RouteContext) => Promise<Omit<OAuthFlowDisconnectInput, "providerId" | "requestId">> | Omit<OAuthFlowDisconnectInput, "providerId" | "requestId">;
|
|
13
|
+
resolveCallbackInput?: (request: Request, context: RouteContext) => Promise<Partial<Omit<OAuthFlowCallbackInput, "providerId" | "requestId">>> | Partial<Omit<OAuthFlowCallbackInput, "providerId" | "requestId">>;
|
|
14
|
+
serializeCallbackResult?: (result: OAuthFlowCallbackResult, request: Request, context: RouteContext) => Promise<unknown> | unknown;
|
|
15
|
+
routeMeta?: OAuthConnectionRouteMetaOverrides;
|
|
16
|
+
requestIdHeader?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function createOAuthConnectionRoutes(config: OAuthConnectionRouteConfig): Route[];
|
|
19
|
+
//# sourceMappingURL=connection-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-routes.d.ts","sourceRoot":"","sources":["../src/connection-routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,aAAa,EAAoB,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAChH,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,iCAAiC,GAAG;IAC9C,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAC;IACnH,sBAAsB,CAAC,EAAE,CACvB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC,IAAI,CAAC,wBAAwB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,wBAAwB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC;IACtI,oBAAoB,CAAC,EAAE,CACrB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC;IACpJ,uBAAuB,CAAC,EAAE,CACxB,MAAM,EAAE,uBAAuB,EAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAChC,SAAS,CAAC,EAAE,iCAAiC,CAAC;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,0BAA0B,GAAG,KAAK,EAAE,CAgEvF"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { BadRequestError } from "@superfunctions/http";
|
|
2
|
+
export function createOAuthConnectionRoutes(config) {
|
|
3
|
+
const requestIdHeader = (config.requestIdHeader ?? "x-request-id").toLowerCase();
|
|
4
|
+
return [
|
|
5
|
+
{
|
|
6
|
+
method: "POST",
|
|
7
|
+
path: joinPath(config.basePath, "start"),
|
|
8
|
+
meta: resolveRouteMeta({ auth: { mode: "hybrid" } }, config.routeMeta?.start),
|
|
9
|
+
handler: async (request, context) => {
|
|
10
|
+
const requestId = request.headers.get(requestIdHeader) ?? undefined;
|
|
11
|
+
const input = await config.resolveStartInput(request, context);
|
|
12
|
+
const result = await config.flowService.start({
|
|
13
|
+
...input,
|
|
14
|
+
requestId: requestId ?? input.requestId
|
|
15
|
+
});
|
|
16
|
+
return Response.json(result);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
method: "GET",
|
|
21
|
+
path: joinPath(config.basePath, "callback/:provider"),
|
|
22
|
+
meta: resolveRouteMeta({ auth: { mode: "none" } }, config.routeMeta?.callback),
|
|
23
|
+
handler: async (request, context) => {
|
|
24
|
+
const requestId = request.headers.get(requestIdHeader) ?? undefined;
|
|
25
|
+
const resolvedInput = (await config.resolveCallbackInput?.(request, context)) ?? {};
|
|
26
|
+
const url = new URL(request.url);
|
|
27
|
+
const callbackResult = await config.flowService.handleCallback({
|
|
28
|
+
providerId: context.params.provider,
|
|
29
|
+
code: asRequiredString(resolvedInput.code ?? url.searchParams.get("code"), "code"),
|
|
30
|
+
state: asRequiredString(resolvedInput.state ?? url.searchParams.get("state"), "state"),
|
|
31
|
+
redirectUri: asRequiredString(resolvedInput.redirectUri ??
|
|
32
|
+
url.searchParams.get("redirectUri") ??
|
|
33
|
+
inferCallbackRedirectUri(url), "redirectUri"),
|
|
34
|
+
requestId
|
|
35
|
+
});
|
|
36
|
+
const payload = config.serializeCallbackResult
|
|
37
|
+
? await config.serializeCallbackResult(callbackResult, request, context)
|
|
38
|
+
: callbackResult;
|
|
39
|
+
return Response.json(payload);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
method: "POST",
|
|
44
|
+
path: joinPath(config.basePath, "disconnect/:provider"),
|
|
45
|
+
meta: resolveRouteMeta({ auth: { mode: "hybrid" } }, config.routeMeta?.disconnect),
|
|
46
|
+
handler: async (request, context) => {
|
|
47
|
+
const requestId = request.headers.get(requestIdHeader) ?? undefined;
|
|
48
|
+
const input = (await config.resolveDisconnectInput?.(request, context)) ??
|
|
49
|
+
(await parseDisconnectBody(request));
|
|
50
|
+
const result = await config.flowService.disconnect({
|
|
51
|
+
...input,
|
|
52
|
+
providerId: context.params.provider,
|
|
53
|
+
requestId
|
|
54
|
+
});
|
|
55
|
+
return Response.json(result);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
function resolveRouteMeta(defaultMeta, overrideMeta) {
|
|
61
|
+
if (!overrideMeta) {
|
|
62
|
+
return defaultMeta;
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
...defaultMeta,
|
|
66
|
+
...overrideMeta,
|
|
67
|
+
auth: mergeAuthMeta(defaultMeta.auth, overrideMeta.auth),
|
|
68
|
+
openapi: mergeOpenApiMeta(defaultMeta.openapi, overrideMeta.openapi)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function mergeAuthMeta(defaultMeta, overrideMeta) {
|
|
72
|
+
if (!defaultMeta) {
|
|
73
|
+
return overrideMeta ? { ...overrideMeta } : undefined;
|
|
74
|
+
}
|
|
75
|
+
if (!overrideMeta) {
|
|
76
|
+
return { ...defaultMeta };
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
...defaultMeta,
|
|
80
|
+
...overrideMeta
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function mergeOpenApiMeta(defaultMeta, overrideMeta) {
|
|
84
|
+
if (!defaultMeta) {
|
|
85
|
+
return overrideMeta ? { ...overrideMeta } : undefined;
|
|
86
|
+
}
|
|
87
|
+
if (!overrideMeta) {
|
|
88
|
+
return { ...defaultMeta };
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
...defaultMeta,
|
|
92
|
+
...overrideMeta
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function joinPath(basePath, suffix) {
|
|
96
|
+
const normalizedBase = basePath.startsWith("/") ? basePath : `/${basePath}`;
|
|
97
|
+
return `${normalizedBase.replace(/\/$/, "")}/${suffix.replace(/^\//, "")}`;
|
|
98
|
+
}
|
|
99
|
+
function asRequiredString(value, field) {
|
|
100
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
101
|
+
throw new BadRequestError(`${field} is required`, "OAUTH_ROUTE_INVALID_INPUT");
|
|
102
|
+
}
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
async function parseDisconnectBody(request) {
|
|
106
|
+
const body = asJsonObject(await parseJsonBody(request), "disconnect body");
|
|
107
|
+
return {
|
|
108
|
+
connectionId: asRequiredString(body.connectionId, "connectionId"),
|
|
109
|
+
revokeRemote: asOptionalBoolean(body.revokeRemote, "revokeRemote"),
|
|
110
|
+
tokenTypeHint: asTokenTypeHint(body.tokenTypeHint)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
async function parseJsonBody(request) {
|
|
114
|
+
try {
|
|
115
|
+
return await request.json();
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
throw new BadRequestError("disconnect body must be valid JSON", "OAUTH_ROUTE_INVALID_INPUT");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function inferCallbackRedirectUri(url) {
|
|
122
|
+
const redirectUrl = new URL(url.toString());
|
|
123
|
+
for (const transientParam of ["code", "state", "redirectUri", "error", "error_description", "error_uri"]) {
|
|
124
|
+
redirectUrl.searchParams.delete(transientParam);
|
|
125
|
+
}
|
|
126
|
+
return redirectUrl.toString();
|
|
127
|
+
}
|
|
128
|
+
function asJsonObject(value, field) {
|
|
129
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
130
|
+
throw new BadRequestError(`${field} must be a JSON object`, "OAUTH_ROUTE_INVALID_INPUT");
|
|
131
|
+
}
|
|
132
|
+
return value;
|
|
133
|
+
}
|
|
134
|
+
function asOptionalBoolean(value, field) {
|
|
135
|
+
if (value === undefined) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
if (typeof value !== "boolean") {
|
|
139
|
+
throw new BadRequestError(`${field} must be a boolean`, "OAUTH_ROUTE_INVALID_INPUT");
|
|
140
|
+
}
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
function asTokenTypeHint(value) {
|
|
144
|
+
if (value === undefined) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
if (value === "access_token" || value === "refresh_token") {
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
throw new BadRequestError("tokenTypeHint must be access_token or refresh_token", "OAUTH_ROUTE_INVALID_INPUT");
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=connection-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-routes.js","sourceRoot":"","sources":["../src/connection-routes.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@superfunctions/oauth-router",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Reusable OAuth route factories for Superfunctions",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"test": "vitest --config ./vitest.config.ts --run",
|
|
20
|
+
"test:watch": "vitest --config ./vitest.config.ts --watch",
|
|
21
|
+
"lint": "echo 'lint not configured'",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"clean": "rm -rf dist"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"oauth",
|
|
27
|
+
"router",
|
|
28
|
+
"superfunctions"
|
|
29
|
+
],
|
|
30
|
+
"author": "21n",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/21nCo/super-functions.git",
|
|
35
|
+
"directory": "packages/oauth-router"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@superfunctions/http": "0.1.3",
|
|
42
|
+
"@superfunctions/oauth-flow": "0.0.1"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^22.0.0",
|
|
46
|
+
"typescript": "^5.6.0",
|
|
47
|
+
"vitest": "^3.2.4"
|
|
48
|
+
}
|
|
49
|
+
}
|