@better-auth/core 1.5.5 → 1.5.7-beta.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/dist/api/index.d.mts +41 -14
- package/dist/api/index.mjs +1 -2
- package/dist/api/index.mjs.map +1 -1
- package/dist/async_hooks/index.mjs +1 -1
- package/dist/async_hooks/pure.index.mjs +1 -1
- package/dist/async_hooks/pure.index.mjs.map +1 -1
- package/dist/context/endpoint-context.d.mts +1 -2
- package/dist/context/endpoint-context.mjs +1 -2
- package/dist/context/endpoint-context.mjs.map +1 -1
- package/dist/context/global.mjs +2 -2
- package/dist/context/global.mjs.map +1 -1
- package/dist/context/index.mjs +1 -2
- package/dist/context/request-state.mjs +1 -2
- package/dist/context/request-state.mjs.map +1 -1
- package/dist/context/transaction.mjs +1 -2
- package/dist/context/transaction.mjs.map +1 -1
- package/dist/db/adapter/factory.d.mts +0 -2
- package/dist/db/adapter/factory.mjs +54 -22
- package/dist/db/adapter/factory.mjs.map +1 -1
- package/dist/db/adapter/get-default-field-name.mjs +1 -2
- package/dist/db/adapter/get-default-field-name.mjs.map +1 -1
- package/dist/db/adapter/get-default-model-name.mjs +1 -2
- package/dist/db/adapter/get-default-model-name.mjs.map +1 -1
- package/dist/db/adapter/get-field-attributes.d.mts +0 -3
- package/dist/db/adapter/get-field-attributes.mjs +1 -2
- package/dist/db/adapter/get-field-attributes.mjs.map +1 -1
- package/dist/db/adapter/get-field-name.mjs +1 -2
- package/dist/db/adapter/get-field-name.mjs.map +1 -1
- package/dist/db/adapter/get-id-field.d.mts +0 -3
- package/dist/db/adapter/get-id-field.mjs +3 -4
- package/dist/db/adapter/get-id-field.mjs.map +1 -1
- package/dist/db/adapter/get-model-name.mjs +1 -2
- package/dist/db/adapter/get-model-name.mjs.map +1 -1
- package/dist/db/adapter/index.d.mts +0 -2
- package/dist/db/adapter/index.mjs +1 -2
- package/dist/db/adapter/index.mjs.map +1 -1
- package/dist/db/adapter/types.d.mts +0 -2
- package/dist/db/adapter/utils.mjs +1 -1
- package/dist/db/adapter/utils.mjs.map +1 -1
- package/dist/db/get-tables.d.mts +0 -2
- package/dist/db/get-tables.mjs +1 -1
- package/dist/db/index.mjs +1 -2
- package/dist/db/schema/account.d.mts +0 -1
- package/dist/db/schema/account.mjs +1 -2
- package/dist/db/schema/account.mjs.map +1 -1
- package/dist/db/schema/rate-limit.d.mts +0 -1
- package/dist/db/schema/rate-limit.mjs +1 -2
- package/dist/db/schema/rate-limit.mjs.map +1 -1
- package/dist/db/schema/session.d.mts +0 -1
- package/dist/db/schema/session.mjs +1 -2
- package/dist/db/schema/session.mjs.map +1 -1
- package/dist/db/schema/shared.mjs +1 -2
- package/dist/db/schema/shared.mjs.map +1 -1
- package/dist/db/schema/user.d.mts +0 -1
- package/dist/db/schema/user.mjs +1 -2
- package/dist/db/schema/user.mjs.map +1 -1
- package/dist/db/schema/verification.d.mts +0 -1
- package/dist/db/schema/verification.mjs +1 -2
- package/dist/db/schema/verification.mjs.map +1 -1
- package/dist/db/type.d.mts +0 -1
- package/dist/env/color-depth.mjs +1 -2
- package/dist/env/color-depth.mjs.map +1 -1
- package/dist/env/env-impl.mjs +1 -1
- package/dist/env/env-impl.mjs.map +1 -1
- package/dist/env/index.mjs +1 -2
- package/dist/env/logger.mjs +1 -2
- package/dist/env/logger.mjs.map +1 -1
- package/dist/error/codes.mjs +1 -2
- package/dist/error/codes.mjs.map +1 -1
- package/dist/error/index.mjs +1 -2
- package/dist/error/index.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/instrumentation/attributes.d.mts +12 -0
- package/dist/instrumentation/attributes.mjs +12 -0
- package/dist/instrumentation/attributes.mjs.map +1 -0
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.mjs +3 -0
- package/dist/instrumentation/tracer.d.mts +14 -0
- package/dist/instrumentation/tracer.mjs +36 -0
- package/dist/instrumentation/tracer.mjs.map +1 -0
- package/dist/oauth2/client-credentials-token.d.mts +0 -1
- package/dist/oauth2/client-credentials-token.mjs +1 -2
- package/dist/oauth2/client-credentials-token.mjs.map +1 -1
- package/dist/oauth2/create-authorization-url.d.mts +0 -3
- package/dist/oauth2/create-authorization-url.mjs +1 -2
- package/dist/oauth2/create-authorization-url.mjs.map +1 -1
- package/dist/oauth2/index.mjs +1 -2
- package/dist/oauth2/oauth-provider.d.mts +0 -2
- package/dist/oauth2/refresh-access-token.d.mts +0 -1
- package/dist/oauth2/refresh-access-token.mjs +1 -2
- package/dist/oauth2/refresh-access-token.mjs.map +1 -1
- package/dist/oauth2/utils.mjs +1 -2
- package/dist/oauth2/utils.mjs.map +1 -1
- package/dist/oauth2/validate-authorization-code.d.mts +0 -2
- package/dist/oauth2/validate-authorization-code.mjs +1 -2
- package/dist/oauth2/validate-authorization-code.mjs.map +1 -1
- package/dist/oauth2/verify.mjs +1 -2
- package/dist/oauth2/verify.mjs.map +1 -1
- package/dist/social-providers/apple.d.mts +0 -2
- package/dist/social-providers/apple.mjs +2 -3
- package/dist/social-providers/apple.mjs.map +1 -1
- package/dist/social-providers/atlassian.d.mts +0 -2
- package/dist/social-providers/atlassian.mjs +4 -4
- package/dist/social-providers/atlassian.mjs.map +1 -1
- package/dist/social-providers/cognito.d.mts +0 -2
- package/dist/social-providers/cognito.mjs +1 -2
- package/dist/social-providers/cognito.mjs.map +1 -1
- package/dist/social-providers/discord.d.mts +0 -2
- package/dist/social-providers/discord.mjs +4 -4
- package/dist/social-providers/discord.mjs.map +1 -1
- package/dist/social-providers/dropbox.d.mts +0 -2
- package/dist/social-providers/dropbox.mjs +1 -2
- package/dist/social-providers/dropbox.mjs.map +1 -1
- package/dist/social-providers/facebook.d.mts +0 -2
- package/dist/social-providers/facebook.mjs +1 -2
- package/dist/social-providers/facebook.mjs.map +1 -1
- package/dist/social-providers/figma.d.mts +0 -2
- package/dist/social-providers/figma.mjs +4 -4
- package/dist/social-providers/figma.mjs.map +1 -1
- package/dist/social-providers/github.d.mts +0 -2
- package/dist/social-providers/github.mjs +2 -3
- package/dist/social-providers/github.mjs.map +1 -1
- package/dist/social-providers/gitlab.d.mts +0 -2
- package/dist/social-providers/gitlab.mjs +1 -2
- package/dist/social-providers/gitlab.mjs.map +1 -1
- package/dist/social-providers/google.d.mts +0 -2
- package/dist/social-providers/google.mjs +1 -2
- package/dist/social-providers/google.mjs.map +1 -1
- package/dist/social-providers/huggingface.d.mts +0 -2
- package/dist/social-providers/huggingface.mjs +4 -4
- package/dist/social-providers/huggingface.mjs.map +1 -1
- package/dist/social-providers/index.d.mts +61 -3
- package/dist/social-providers/index.mjs +5 -4
- package/dist/social-providers/index.mjs.map +1 -1
- package/dist/social-providers/kakao.d.mts +0 -2
- package/dist/social-providers/kakao.mjs +4 -4
- package/dist/social-providers/kakao.mjs.map +1 -1
- package/dist/social-providers/kick.d.mts +0 -2
- package/dist/social-providers/kick.mjs +1 -2
- package/dist/social-providers/kick.mjs.map +1 -1
- package/dist/social-providers/line.d.mts +0 -2
- package/dist/social-providers/line.mjs +1 -2
- package/dist/social-providers/line.mjs.map +1 -1
- package/dist/social-providers/linear.d.mts +0 -2
- package/dist/social-providers/linear.mjs +1 -2
- package/dist/social-providers/linear.mjs.map +1 -1
- package/dist/social-providers/linkedin.d.mts +0 -2
- package/dist/social-providers/linkedin.mjs +1 -2
- package/dist/social-providers/linkedin.mjs.map +1 -1
- package/dist/social-providers/microsoft-entra-id.d.mts +0 -2
- package/dist/social-providers/microsoft-entra-id.mjs +1 -2
- package/dist/social-providers/microsoft-entra-id.mjs.map +1 -1
- package/dist/social-providers/naver.d.mts +0 -2
- package/dist/social-providers/naver.mjs +4 -4
- package/dist/social-providers/naver.mjs.map +1 -1
- package/dist/social-providers/notion.d.mts +0 -2
- package/dist/social-providers/notion.mjs +1 -2
- package/dist/social-providers/notion.mjs.map +1 -1
- package/dist/social-providers/paybin.d.mts +0 -2
- package/dist/social-providers/paybin.mjs +1 -2
- package/dist/social-providers/paybin.mjs.map +1 -1
- package/dist/social-providers/paypal.d.mts +0 -2
- package/dist/social-providers/paypal.mjs +1 -2
- package/dist/social-providers/paypal.mjs.map +1 -1
- package/dist/social-providers/polar.d.mts +0 -2
- package/dist/social-providers/polar.mjs +4 -4
- package/dist/social-providers/polar.mjs.map +1 -1
- package/dist/social-providers/railway.d.mts +0 -2
- package/dist/social-providers/railway.mjs +1 -2
- package/dist/social-providers/railway.mjs.map +1 -1
- package/dist/social-providers/reddit.d.mts +0 -2
- package/dist/social-providers/reddit.mjs +1 -2
- package/dist/social-providers/reddit.mjs.map +1 -1
- package/dist/social-providers/roblox.d.mts +0 -2
- package/dist/social-providers/roblox.mjs +4 -4
- package/dist/social-providers/roblox.mjs.map +1 -1
- package/dist/social-providers/salesforce.d.mts +0 -2
- package/dist/social-providers/salesforce.mjs +1 -2
- package/dist/social-providers/salesforce.mjs.map +1 -1
- package/dist/social-providers/slack.d.mts +0 -2
- package/dist/social-providers/slack.mjs +4 -4
- package/dist/social-providers/slack.mjs.map +1 -1
- package/dist/social-providers/spotify.d.mts +0 -2
- package/dist/social-providers/spotify.mjs +4 -4
- package/dist/social-providers/spotify.mjs.map +1 -1
- package/dist/social-providers/tiktok.d.mts +0 -2
- package/dist/social-providers/tiktok.mjs +4 -4
- package/dist/social-providers/tiktok.mjs.map +1 -1
- package/dist/social-providers/twitch.d.mts +0 -2
- package/dist/social-providers/twitch.mjs +4 -4
- package/dist/social-providers/twitch.mjs.map +1 -1
- package/dist/social-providers/twitter.d.mts +0 -2
- package/dist/social-providers/twitter.mjs +4 -4
- package/dist/social-providers/twitter.mjs.map +1 -1
- package/dist/social-providers/vercel.d.mts +0 -2
- package/dist/social-providers/vercel.mjs +1 -2
- package/dist/social-providers/vercel.mjs.map +1 -1
- package/dist/social-providers/vk.d.mts +0 -2
- package/dist/social-providers/vk.mjs +4 -4
- package/dist/social-providers/vk.mjs.map +1 -1
- package/dist/social-providers/wechat.d.mts +114 -0
- package/dist/social-providers/wechat.mjs +83 -0
- package/dist/social-providers/wechat.mjs.map +1 -0
- package/dist/social-providers/zoom.d.mts +0 -2
- package/dist/social-providers/zoom.mjs +1 -2
- package/dist/social-providers/zoom.mjs.map +1 -1
- package/dist/types/context.d.mts +1 -5
- package/dist/types/init-options.d.mts +0 -1
- package/dist/types/plugin.d.mts +4 -2
- package/dist/utils/db.d.mts +0 -2
- package/dist/utils/db.mjs +1 -1
- package/dist/utils/deprecate.mjs +1 -1
- package/dist/utils/error-codes.mjs +1 -1
- package/dist/utils/fetch-metadata.mjs +1 -1
- package/dist/utils/id.mjs +1 -2
- package/dist/utils/id.mjs.map +1 -1
- package/dist/utils/ip.mjs +1 -2
- package/dist/utils/ip.mjs.map +1 -1
- package/dist/utils/json.mjs +1 -2
- package/dist/utils/json.mjs.map +1 -1
- package/dist/utils/string.mjs +1 -1
- package/dist/utils/url.mjs +1 -1
- package/package.json +18 -5
- package/src/api/index.ts +151 -41
- package/src/context/endpoint-context.ts +2 -1
- package/src/db/adapter/factory.ts +119 -47
- package/src/db/adapter/get-id-field.test.ts +222 -0
- package/src/db/adapter/get-id-field.ts +15 -4
- package/src/instrumentation/attributes.ts +22 -0
- package/src/instrumentation/index.ts +2 -0
- package/src/instrumentation/instrumentation.test.ts +139 -0
- package/src/instrumentation/tracer.ts +62 -0
- package/src/social-providers/apple.ts +1 -1
- package/src/social-providers/atlassian.ts +3 -2
- package/src/social-providers/discord.ts +3 -2
- package/src/social-providers/figma.ts +3 -2
- package/src/social-providers/github.ts +1 -1
- package/src/social-providers/huggingface.ts +3 -2
- package/src/social-providers/index.ts +3 -0
- package/src/social-providers/kakao.ts +3 -2
- package/src/social-providers/naver.ts +3 -2
- package/src/social-providers/polar.ts +3 -2
- package/src/social-providers/roblox.ts +3 -2
- package/src/social-providers/slack.ts +3 -2
- package/src/social-providers/spotify.ts +3 -2
- package/src/social-providers/tiktok.ts +3 -2
- package/src/social-providers/twitch.ts +3 -2
- package/src/social-providers/twitter.ts +3 -2
- package/src/social-providers/vk.ts +3 -2
- package/src/social-providers/wechat.ts +213 -0
- package/src/types/context.ts +1 -3
- package/src/types/plugin.ts +14 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attributes.mjs","names":[],"sources":["../../src/instrumentation/attributes.ts"],"sourcesContent":["import {\n\tATTR_DB_COLLECTION_NAME,\n\tATTR_DB_OPERATION_NAME,\n\tATTR_HTTP_RESPONSE_STATUS_CODE,\n\tATTR_HTTP_ROUTE,\n} from \"@opentelemetry/semantic-conventions\";\n\nexport {\n\tATTR_DB_COLLECTION_NAME,\n\tATTR_DB_OPERATION_NAME,\n\tATTR_HTTP_RESPONSE_STATUS_CODE,\n\tATTR_HTTP_ROUTE,\n};\n\n/** Operation identifier (e.g. getSession, signUpWithEmailAndPassword). Uses endpoint operationId when set, otherwise the endpoint key. */\nexport const ATTR_OPERATION_ID = \"better_auth.operation_id\" as const;\n\n/** Hook type (e.g. before, after, create.before). */\nexport const ATTR_HOOK_TYPE = \"better_auth.hook.type\" as const;\n\n/** Execution context (e.g. user, plugin:id). */\nexport const ATTR_CONTEXT = \"better_auth.context\" as const;\n"],"mappings":";;;AAeA,MAAa,oBAAoB;;AAGjC,MAAa,iBAAiB;;AAG9B,MAAa,eAAe"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { ATTR_CONTEXT, ATTR_DB_COLLECTION_NAME, ATTR_DB_OPERATION_NAME, ATTR_HOOK_TYPE, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_HTTP_ROUTE, ATTR_OPERATION_ID } from "./attributes.mjs";
|
|
2
|
+
import { withSpan } from "./tracer.mjs";
|
|
3
|
+
export { ATTR_CONTEXT, ATTR_DB_COLLECTION_NAME, ATTR_DB_OPERATION_NAME, ATTR_HOOK_TYPE, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_HTTP_ROUTE, ATTR_OPERATION_ID, withSpan };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { ATTR_CONTEXT, ATTR_DB_COLLECTION_NAME, ATTR_DB_OPERATION_NAME, ATTR_HOOK_TYPE, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_HTTP_ROUTE, ATTR_OPERATION_ID } from "./attributes.mjs";
|
|
2
|
+
import { withSpan } from "./tracer.mjs";
|
|
3
|
+
export { ATTR_CONTEXT, ATTR_DB_COLLECTION_NAME, ATTR_DB_OPERATION_NAME, ATTR_HOOK_TYPE, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_HTTP_ROUTE, ATTR_OPERATION_ID, withSpan };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/instrumentation/tracer.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Creates a child span whose lifetime is bound to the execution of the given function
|
|
4
|
+
*
|
|
5
|
+
* @param name - The name of the span.
|
|
6
|
+
* @param attributes - The attributes of the span.
|
|
7
|
+
* @param fn - The function to execute within the span.
|
|
8
|
+
* @returns The result of the function.
|
|
9
|
+
*/
|
|
10
|
+
declare function withSpan<T>(name: string, attributes: Record<string, string | number | boolean>, fn: () => T): T;
|
|
11
|
+
declare function withSpan<T>(name: string, attributes: Record<string, string | number | boolean>, fn: () => Promise<T>): Promise<T>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { withSpan };
|
|
14
|
+
//# sourceMappingURL=tracer.d.mts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
2
|
+
//#region src/instrumentation/tracer.ts
|
|
3
|
+
const tracer = trace.getTracer("better-auth", "1.5.7-beta.1");
|
|
4
|
+
function withSpan(name, attributes, fn) {
|
|
5
|
+
return tracer.startActiveSpan(name, { attributes }, (span) => {
|
|
6
|
+
try {
|
|
7
|
+
const result = fn();
|
|
8
|
+
if (result instanceof Promise) return result.then((value) => {
|
|
9
|
+
span.end();
|
|
10
|
+
return value;
|
|
11
|
+
}).catch((err) => {
|
|
12
|
+
span.recordException(err);
|
|
13
|
+
span.setStatus({
|
|
14
|
+
code: SpanStatusCode.ERROR,
|
|
15
|
+
message: String(err.message ?? err)
|
|
16
|
+
});
|
|
17
|
+
span.end();
|
|
18
|
+
throw err;
|
|
19
|
+
});
|
|
20
|
+
span.end();
|
|
21
|
+
return result;
|
|
22
|
+
} catch (err) {
|
|
23
|
+
span.recordException(err);
|
|
24
|
+
span.setStatus({
|
|
25
|
+
code: SpanStatusCode.ERROR,
|
|
26
|
+
message: String(err?.message ?? err)
|
|
27
|
+
});
|
|
28
|
+
span.end();
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { withSpan };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=tracer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracer.mjs","names":[],"sources":["../../src/instrumentation/tracer.ts"],"sourcesContent":["import { SpanStatusCode, trace } from \"@opentelemetry/api\";\n\nconst INSTRUMENTATION_SCOPE = \"better-auth\";\nconst INSTRUMENTATION_VERSION = import.meta.env?.BETTER_AUTH_VERSION ?? \"1.0.0\";\n\nconst tracer = trace.getTracer(INSTRUMENTATION_SCOPE, INSTRUMENTATION_VERSION);\n\n/**\n * Creates a child span whose lifetime is bound to the execution of the given function\n *\n * @param name - The name of the span.\n * @param attributes - The attributes of the span.\n * @param fn - The function to execute within the span.\n * @returns The result of the function.\n */\nexport function withSpan<T>(\n\tname: string,\n\tattributes: Record<string, string | number | boolean>,\n\tfn: () => T,\n): T;\nexport function withSpan<T>(\n\tname: string,\n\tattributes: Record<string, string | number | boolean>,\n\tfn: () => Promise<T>,\n): Promise<T>;\nexport function withSpan<T>(\n\tname: string,\n\tattributes: Record<string, string | number | boolean>,\n\tfn: () => T | Promise<T>,\n): T | Promise<T> {\n\treturn tracer.startActiveSpan(name, { attributes }, (span) => {\n\t\ttry {\n\t\t\tconst result = fn();\n\t\t\tif (result instanceof Promise) {\n\t\t\t\treturn result\n\t\t\t\t\t.then((value) => {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tspan.recordException(err);\n\t\t\t\t\t\tspan.setStatus({\n\t\t\t\t\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\t\t\t\t\tmessage: String(err.message ?? err),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t\tthrow err;\n\t\t\t\t\t}) as Promise<T>;\n\t\t\t}\n\t\t\tspan.end();\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tspan.recordException(err as Error);\n\t\t\tspan.setStatus({\n\t\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\t\tmessage: String((err as Error)?.message ?? err),\n\t\t\t});\n\t\t\tspan.end();\n\t\t\tthrow err;\n\t\t}\n\t});\n}\n"],"mappings":";;AAKA,MAAM,SAAS,MAAM,UAHS,eAAA,eAGgD;AAoB9E,SAAgB,SACf,MACA,YACA,IACiB;AACjB,QAAO,OAAO,gBAAgB,MAAM,EAAE,YAAY,GAAG,SAAS;AAC7D,MAAI;GACH,MAAM,SAAS,IAAI;AACnB,OAAI,kBAAkB,QACrB,QAAO,OACL,MAAM,UAAU;AAChB,SAAK,KAAK;AACV,WAAO;KACN,CACD,OAAO,QAAQ;AACf,SAAK,gBAAgB,IAAI;AACzB,SAAK,UAAU;KACd,MAAM,eAAe;KACrB,SAAS,OAAO,IAAI,WAAW,IAAI;KACnC,CAAC;AACF,SAAK,KAAK;AACV,UAAM;KACL;AAEJ,QAAK,KAAK;AACV,UAAO;WACC,KAAK;AACb,QAAK,gBAAgB,IAAa;AAClC,QAAK,UAAU;IACd,MAAM,eAAe;IACrB,SAAS,OAAQ,KAAe,WAAW,IAAI;IAC/C,CAAC;AACF,QAAK,KAAK;AACV,SAAM;;GAEN"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { base64Url } from "@better-auth/utils/base64";
|
|
2
2
|
import { betterFetch } from "@better-fetch/fetch";
|
|
3
|
-
|
|
4
3
|
//#region src/oauth2/client-credentials-token.ts
|
|
5
4
|
async function clientCredentialsTokenRequest({ options, scope, authentication, resource }) {
|
|
6
5
|
options = typeof options === "function" ? await options() : options;
|
|
@@ -61,7 +60,7 @@ async function clientCredentialsToken({ options, tokenEndpoint, scope, authentic
|
|
|
61
60
|
}
|
|
62
61
|
return tokens;
|
|
63
62
|
}
|
|
64
|
-
|
|
65
63
|
//#endregion
|
|
66
64
|
export { clientCredentialsToken, clientCredentialsTokenRequest, createClientCredentialsTokenRequest };
|
|
65
|
+
|
|
67
66
|
//# sourceMappingURL=client-credentials-token.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-credentials-token.mjs","names":[],"sources":["../../src/oauth2/client-credentials-token.ts"],"sourcesContent":["import { base64Url } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport type { AwaitableFunction } from \"../types\";\nimport type { OAuth2Tokens, ProviderOptions } from \"./oauth-provider\";\n\nexport async function clientCredentialsTokenRequest({\n\toptions,\n\tscope,\n\tauthentication,\n\tresource,\n}: {\n\toptions: AwaitableFunction<ProviderOptions & { clientSecret: string }>;\n\tscope?: string | undefined;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\toptions = typeof options === \"function\" ? await options() : options;\n\treturn createClientCredentialsTokenRequest({\n\t\toptions,\n\t\tscope,\n\t\tauthentication,\n\t\tresource,\n\t});\n}\n\n/**\n * @deprecated use async'd clientCredentialsTokenRequest instead\n */\nexport function createClientCredentialsTokenRequest({\n\toptions,\n\tscope,\n\tauthentication,\n\tresource,\n}: {\n\toptions: ProviderOptions & { clientSecret: string };\n\tscope?: string | undefined;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\tconst body = new URLSearchParams();\n\tconst headers: Record<string, any> = {\n\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\taccept: \"application/json\",\n\t};\n\n\tbody.set(\"grant_type\", \"client_credentials\");\n\tscope && body.set(\"scope\", scope);\n\tif (resource) {\n\t\tif (typeof resource === \"string\") {\n\t\t\tbody.append(\"resource\", resource);\n\t\t} else {\n\t\t\tfor (const _resource of resource) {\n\t\t\t\tbody.append(\"resource\", _resource);\n\t\t\t}\n\t\t}\n\t}\n\tif (authentication === \"basic\") {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tconst encodedCredentials = base64Url.encode(\n\t\t\t`${primaryClientId}:${options.clientSecret}`,\n\t\t);\n\t\theaders[\"authorization\"] = `Basic ${encodedCredentials}`;\n\t} else {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tbody.set(\"client_id\", primaryClientId);\n\t\tbody.set(\"client_secret\", options.clientSecret);\n\t}\n\n\treturn {\n\t\tbody,\n\t\theaders,\n\t};\n}\n\nexport async function clientCredentialsToken({\n\toptions,\n\ttokenEndpoint,\n\tscope,\n\tauthentication,\n\tresource,\n}: {\n\toptions: AwaitableFunction<ProviderOptions & { clientSecret: string }>;\n\ttokenEndpoint: string;\n\tscope: string;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\tresource?: (string | string[]) | undefined;\n}): Promise<OAuth2Tokens> {\n\tconst { body, headers } = await clientCredentialsTokenRequest({\n\t\toptions,\n\t\tscope,\n\t\tauthentication,\n\t\tresource,\n\t});\n\n\tconst { data, error } = await betterFetch<{\n\t\taccess_token: string;\n\t\texpires_in?: number | undefined;\n\t\ttoken_type?: string | undefined;\n\t\tscope?: string | undefined;\n\t}>(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\tbody,\n\t\theaders,\n\t});\n\tif (error) {\n\t\tthrow error;\n\t}\n\tconst tokens: OAuth2Tokens = {\n\t\taccessToken: data.access_token,\n\t\ttokenType: data.token_type,\n\t\tscopes: data.scope?.split(\" \"),\n\t};\n\n\tif (data.expires_in) {\n\t\tconst now = new Date();\n\t\ttokens.accessTokenExpiresAt = new Date(\n\t\t\tnow.getTime() + data.expires_in * 1000,\n\t\t);\n\t}\n\n\treturn tokens;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"client-credentials-token.mjs","names":[],"sources":["../../src/oauth2/client-credentials-token.ts"],"sourcesContent":["import { base64Url } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport type { AwaitableFunction } from \"../types\";\nimport type { OAuth2Tokens, ProviderOptions } from \"./oauth-provider\";\n\nexport async function clientCredentialsTokenRequest({\n\toptions,\n\tscope,\n\tauthentication,\n\tresource,\n}: {\n\toptions: AwaitableFunction<ProviderOptions & { clientSecret: string }>;\n\tscope?: string | undefined;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\toptions = typeof options === \"function\" ? await options() : options;\n\treturn createClientCredentialsTokenRequest({\n\t\toptions,\n\t\tscope,\n\t\tauthentication,\n\t\tresource,\n\t});\n}\n\n/**\n * @deprecated use async'd clientCredentialsTokenRequest instead\n */\nexport function createClientCredentialsTokenRequest({\n\toptions,\n\tscope,\n\tauthentication,\n\tresource,\n}: {\n\toptions: ProviderOptions & { clientSecret: string };\n\tscope?: string | undefined;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\tconst body = new URLSearchParams();\n\tconst headers: Record<string, any> = {\n\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\taccept: \"application/json\",\n\t};\n\n\tbody.set(\"grant_type\", \"client_credentials\");\n\tscope && body.set(\"scope\", scope);\n\tif (resource) {\n\t\tif (typeof resource === \"string\") {\n\t\t\tbody.append(\"resource\", resource);\n\t\t} else {\n\t\t\tfor (const _resource of resource) {\n\t\t\t\tbody.append(\"resource\", _resource);\n\t\t\t}\n\t\t}\n\t}\n\tif (authentication === \"basic\") {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tconst encodedCredentials = base64Url.encode(\n\t\t\t`${primaryClientId}:${options.clientSecret}`,\n\t\t);\n\t\theaders[\"authorization\"] = `Basic ${encodedCredentials}`;\n\t} else {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tbody.set(\"client_id\", primaryClientId);\n\t\tbody.set(\"client_secret\", options.clientSecret);\n\t}\n\n\treturn {\n\t\tbody,\n\t\theaders,\n\t};\n}\n\nexport async function clientCredentialsToken({\n\toptions,\n\ttokenEndpoint,\n\tscope,\n\tauthentication,\n\tresource,\n}: {\n\toptions: AwaitableFunction<ProviderOptions & { clientSecret: string }>;\n\ttokenEndpoint: string;\n\tscope: string;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\tresource?: (string | string[]) | undefined;\n}): Promise<OAuth2Tokens> {\n\tconst { body, headers } = await clientCredentialsTokenRequest({\n\t\toptions,\n\t\tscope,\n\t\tauthentication,\n\t\tresource,\n\t});\n\n\tconst { data, error } = await betterFetch<{\n\t\taccess_token: string;\n\t\texpires_in?: number | undefined;\n\t\ttoken_type?: string | undefined;\n\t\tscope?: string | undefined;\n\t}>(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\tbody,\n\t\theaders,\n\t});\n\tif (error) {\n\t\tthrow error;\n\t}\n\tconst tokens: OAuth2Tokens = {\n\t\taccessToken: data.access_token,\n\t\ttokenType: data.token_type,\n\t\tscopes: data.scope?.split(\" \"),\n\t};\n\n\tif (data.expires_in) {\n\t\tconst now = new Date();\n\t\ttokens.accessTokenExpiresAt = new Date(\n\t\t\tnow.getTime() + data.expires_in * 1000,\n\t\t);\n\t}\n\n\treturn tokens;\n}\n"],"mappings":";;;AAKA,eAAsB,8BAA8B,EACnD,SACA,OACA,gBACA,YAME;AACF,WAAU,OAAO,YAAY,aAAa,MAAM,SAAS,GAAG;AAC5D,QAAO,oCAAoC;EAC1C;EACA;EACA;EACA;EACA,CAAC;;;;;AAMH,SAAgB,oCAAoC,EACnD,SACA,OACA,gBACA,YAME;CACF,MAAM,OAAO,IAAI,iBAAiB;CAClC,MAAM,UAA+B;EACpC,gBAAgB;EAChB,QAAQ;EACR;AAED,MAAK,IAAI,cAAc,qBAAqB;AAC5C,UAAS,KAAK,IAAI,SAAS,MAAM;AACjC,KAAI,SACH,KAAI,OAAO,aAAa,SACvB,MAAK,OAAO,YAAY,SAAS;KAEjC,MAAK,MAAM,aAAa,SACvB,MAAK,OAAO,YAAY,UAAU;AAIrC,KAAI,mBAAmB,SAAS;EAC/B,MAAM,kBAAkB,MAAM,QAAQ,QAAQ,SAAS,GACpD,QAAQ,SAAS,KACjB,QAAQ;AAIX,UAAQ,mBAAmB,SAHA,UAAU,OACpC,GAAG,gBAAgB,GAAG,QAAQ,eAC9B;QAEK;EACN,MAAM,kBAAkB,MAAM,QAAQ,QAAQ,SAAS,GACpD,QAAQ,SAAS,KACjB,QAAQ;AACX,OAAK,IAAI,aAAa,gBAAgB;AACtC,OAAK,IAAI,iBAAiB,QAAQ,aAAa;;AAGhD,QAAO;EACN;EACA;EACA;;AAGF,eAAsB,uBAAuB,EAC5C,SACA,eACA,OACA,gBACA,YAOyB;CACzB,MAAM,EAAE,MAAM,YAAY,MAAM,8BAA8B;EAC7D;EACA;EACA;EACA;EACA,CAAC;CAEF,MAAM,EAAE,MAAM,UAAU,MAAM,YAK3B,eAAe;EACjB,QAAQ;EACR;EACA;EACA,CAAC;AACF,KAAI,MACH,OAAM;CAEP,MAAM,SAAuB;EAC5B,aAAa,KAAK;EAClB,WAAW,KAAK;EAChB,QAAQ,KAAK,OAAO,MAAM,IAAI;EAC9B;AAED,KAAI,KAAK,YAAY;EACpB,MAAM,sBAAM,IAAI,MAAM;AACtB,SAAO,uBAAuB,IAAI,KACjC,IAAI,SAAS,GAAG,KAAK,aAAa,IAClC;;AAGF,QAAO"}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { AwaitableFunction } from "../types/helper.mjs";
|
|
2
|
-
import "../types/index.mjs";
|
|
3
2
|
import { ProviderOptions } from "./oauth-provider.mjs";
|
|
4
|
-
import "./index.mjs";
|
|
5
|
-
|
|
6
3
|
//#region src/oauth2/create-authorization-url.d.ts
|
|
7
4
|
declare function createAuthorizationURL({
|
|
8
5
|
id,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { generateCodeChallenge } from "./utils.mjs";
|
|
2
|
-
|
|
3
2
|
//#region src/oauth2/create-authorization-url.ts
|
|
4
3
|
async function createAuthorizationURL({ id, options, authorizationEndpoint, state, codeVerifier, scopes, claims, redirectURI, duration, prompt, accessType, responseType, display, loginHint, hd, responseMode, additionalParams, scopeJoiner }) {
|
|
5
4
|
options = typeof options === "function" ? await options() : options;
|
|
@@ -38,7 +37,7 @@ async function createAuthorizationURL({ id, options, authorizationEndpoint, stat
|
|
|
38
37
|
});
|
|
39
38
|
return url;
|
|
40
39
|
}
|
|
41
|
-
|
|
42
40
|
//#endregion
|
|
43
41
|
export { createAuthorizationURL };
|
|
42
|
+
|
|
44
43
|
//# sourceMappingURL=create-authorization-url.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-authorization-url.mjs","names":[],"sources":["../../src/oauth2/create-authorization-url.ts"],"sourcesContent":["import type { AwaitableFunction } from \"../types\";\nimport type { ProviderOptions } from \"./index\";\nimport { generateCodeChallenge } from \"./utils\";\n\nexport async function createAuthorizationURL({\n\tid,\n\toptions,\n\tauthorizationEndpoint,\n\tstate,\n\tcodeVerifier,\n\tscopes,\n\tclaims,\n\tredirectURI,\n\tduration,\n\tprompt,\n\taccessType,\n\tresponseType,\n\tdisplay,\n\tloginHint,\n\thd,\n\tresponseMode,\n\tadditionalParams,\n\tscopeJoiner,\n}: {\n\tid: string;\n\toptions: AwaitableFunction<ProviderOptions>;\n\tredirectURI: string;\n\tauthorizationEndpoint: string;\n\tstate: string;\n\tcodeVerifier?: string | undefined;\n\tscopes?: string[] | undefined;\n\tclaims?: string[] | undefined;\n\tduration?: string | undefined;\n\tprompt?: string | undefined;\n\taccessType?: string | undefined;\n\tresponseType?: string | undefined;\n\tdisplay?: string | undefined;\n\tloginHint?: string | undefined;\n\thd?: string | undefined;\n\tresponseMode?: string | undefined;\n\tadditionalParams?: Record<string, string> | undefined;\n\tscopeJoiner?: string | undefined;\n}) {\n\toptions = typeof options === \"function\" ? await options() : options;\n\tconst url = new URL(options.authorizationEndpoint || authorizationEndpoint);\n\turl.searchParams.set(\"response_type\", responseType || \"code\");\n\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t? options.clientId[0]\n\t\t: options.clientId;\n\turl.searchParams.set(\"client_id\", primaryClientId);\n\turl.searchParams.set(\"state\", state);\n\tif (scopes) {\n\t\turl.searchParams.set(\"scope\", scopes.join(scopeJoiner || \" \"));\n\t}\n\turl.searchParams.set(\"redirect_uri\", options.redirectURI || redirectURI);\n\tduration && url.searchParams.set(\"duration\", duration);\n\tdisplay && url.searchParams.set(\"display\", display);\n\tloginHint && url.searchParams.set(\"login_hint\", loginHint);\n\tprompt && url.searchParams.set(\"prompt\", prompt);\n\thd && url.searchParams.set(\"hd\", hd);\n\taccessType && url.searchParams.set(\"access_type\", accessType);\n\tresponseMode && url.searchParams.set(\"response_mode\", responseMode);\n\tif (codeVerifier) {\n\t\tconst codeChallenge = await generateCodeChallenge(codeVerifier);\n\t\turl.searchParams.set(\"code_challenge_method\", \"S256\");\n\t\turl.searchParams.set(\"code_challenge\", codeChallenge);\n\t}\n\tif (claims) {\n\t\tconst claimsObj = claims.reduce(\n\t\t\t(acc, claim) => {\n\t\t\t\tacc[claim] = null;\n\t\t\t\treturn acc;\n\t\t\t},\n\t\t\t{} as Record<string, null>,\n\t\t);\n\t\turl.searchParams.set(\n\t\t\t\"claims\",\n\t\t\tJSON.stringify({\n\t\t\t\tid_token: { email: null, email_verified: null, ...claimsObj },\n\t\t\t}),\n\t\t);\n\t}\n\tif (additionalParams) {\n\t\tObject.entries(additionalParams).forEach(([key, value]) => {\n\t\t\turl.searchParams.set(key, value);\n\t\t});\n\t}\n\treturn url;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-authorization-url.mjs","names":[],"sources":["../../src/oauth2/create-authorization-url.ts"],"sourcesContent":["import type { AwaitableFunction } from \"../types\";\nimport type { ProviderOptions } from \"./index\";\nimport { generateCodeChallenge } from \"./utils\";\n\nexport async function createAuthorizationURL({\n\tid,\n\toptions,\n\tauthorizationEndpoint,\n\tstate,\n\tcodeVerifier,\n\tscopes,\n\tclaims,\n\tredirectURI,\n\tduration,\n\tprompt,\n\taccessType,\n\tresponseType,\n\tdisplay,\n\tloginHint,\n\thd,\n\tresponseMode,\n\tadditionalParams,\n\tscopeJoiner,\n}: {\n\tid: string;\n\toptions: AwaitableFunction<ProviderOptions>;\n\tredirectURI: string;\n\tauthorizationEndpoint: string;\n\tstate: string;\n\tcodeVerifier?: string | undefined;\n\tscopes?: string[] | undefined;\n\tclaims?: string[] | undefined;\n\tduration?: string | undefined;\n\tprompt?: string | undefined;\n\taccessType?: string | undefined;\n\tresponseType?: string | undefined;\n\tdisplay?: string | undefined;\n\tloginHint?: string | undefined;\n\thd?: string | undefined;\n\tresponseMode?: string | undefined;\n\tadditionalParams?: Record<string, string> | undefined;\n\tscopeJoiner?: string | undefined;\n}) {\n\toptions = typeof options === \"function\" ? await options() : options;\n\tconst url = new URL(options.authorizationEndpoint || authorizationEndpoint);\n\turl.searchParams.set(\"response_type\", responseType || \"code\");\n\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t? options.clientId[0]\n\t\t: options.clientId;\n\turl.searchParams.set(\"client_id\", primaryClientId);\n\turl.searchParams.set(\"state\", state);\n\tif (scopes) {\n\t\turl.searchParams.set(\"scope\", scopes.join(scopeJoiner || \" \"));\n\t}\n\turl.searchParams.set(\"redirect_uri\", options.redirectURI || redirectURI);\n\tduration && url.searchParams.set(\"duration\", duration);\n\tdisplay && url.searchParams.set(\"display\", display);\n\tloginHint && url.searchParams.set(\"login_hint\", loginHint);\n\tprompt && url.searchParams.set(\"prompt\", prompt);\n\thd && url.searchParams.set(\"hd\", hd);\n\taccessType && url.searchParams.set(\"access_type\", accessType);\n\tresponseMode && url.searchParams.set(\"response_mode\", responseMode);\n\tif (codeVerifier) {\n\t\tconst codeChallenge = await generateCodeChallenge(codeVerifier);\n\t\turl.searchParams.set(\"code_challenge_method\", \"S256\");\n\t\turl.searchParams.set(\"code_challenge\", codeChallenge);\n\t}\n\tif (claims) {\n\t\tconst claimsObj = claims.reduce(\n\t\t\t(acc, claim) => {\n\t\t\t\tacc[claim] = null;\n\t\t\t\treturn acc;\n\t\t\t},\n\t\t\t{} as Record<string, null>,\n\t\t);\n\t\turl.searchParams.set(\n\t\t\t\"claims\",\n\t\t\tJSON.stringify({\n\t\t\t\tid_token: { email: null, email_verified: null, ...claimsObj },\n\t\t\t}),\n\t\t);\n\t}\n\tif (additionalParams) {\n\t\tObject.entries(additionalParams).forEach(([key, value]) => {\n\t\t\turl.searchParams.set(key, value);\n\t\t});\n\t}\n\treturn url;\n}\n"],"mappings":";;AAIA,eAAsB,uBAAuB,EAC5C,IACA,SACA,uBACA,OACA,cACA,QACA,QACA,aACA,UACA,QACA,YACA,cACA,SACA,WACA,IACA,cACA,kBACA,eAoBE;AACF,WAAU,OAAO,YAAY,aAAa,MAAM,SAAS,GAAG;CAC5D,MAAM,MAAM,IAAI,IAAI,QAAQ,yBAAyB,sBAAsB;AAC3E,KAAI,aAAa,IAAI,iBAAiB,gBAAgB,OAAO;CAC7D,MAAM,kBAAkB,MAAM,QAAQ,QAAQ,SAAS,GACpD,QAAQ,SAAS,KACjB,QAAQ;AACX,KAAI,aAAa,IAAI,aAAa,gBAAgB;AAClD,KAAI,aAAa,IAAI,SAAS,MAAM;AACpC,KAAI,OACH,KAAI,aAAa,IAAI,SAAS,OAAO,KAAK,eAAe,IAAI,CAAC;AAE/D,KAAI,aAAa,IAAI,gBAAgB,QAAQ,eAAe,YAAY;AACxE,aAAY,IAAI,aAAa,IAAI,YAAY,SAAS;AACtD,YAAW,IAAI,aAAa,IAAI,WAAW,QAAQ;AACnD,cAAa,IAAI,aAAa,IAAI,cAAc,UAAU;AAC1D,WAAU,IAAI,aAAa,IAAI,UAAU,OAAO;AAChD,OAAM,IAAI,aAAa,IAAI,MAAM,GAAG;AACpC,eAAc,IAAI,aAAa,IAAI,eAAe,WAAW;AAC7D,iBAAgB,IAAI,aAAa,IAAI,iBAAiB,aAAa;AACnE,KAAI,cAAc;EACjB,MAAM,gBAAgB,MAAM,sBAAsB,aAAa;AAC/D,MAAI,aAAa,IAAI,yBAAyB,OAAO;AACrD,MAAI,aAAa,IAAI,kBAAkB,cAAc;;AAEtD,KAAI,QAAQ;EACX,MAAM,YAAY,OAAO,QACvB,KAAK,UAAU;AACf,OAAI,SAAS;AACb,UAAO;KAER,EAAE,CACF;AACD,MAAI,aAAa,IAChB,UACA,KAAK,UAAU,EACd,UAAU;GAAE,OAAO;GAAM,gBAAgB;GAAM,GAAG;GAAW,EAC7D,CAAC,CACF;;AAEF,KAAI,iBACH,QAAO,QAAQ,iBAAiB,CAAC,SAAS,CAAC,KAAK,WAAW;AAC1D,MAAI,aAAa,IAAI,KAAK,MAAM;GAC/B;AAEH,QAAO"}
|
package/dist/oauth2/index.mjs
CHANGED
|
@@ -4,5 +4,4 @@ import { createAuthorizationURL } from "./create-authorization-url.mjs";
|
|
|
4
4
|
import { createRefreshAccessTokenRequest, refreshAccessToken, refreshAccessTokenRequest } from "./refresh-access-token.mjs";
|
|
5
5
|
import { authorizationCodeRequest, createAuthorizationCodeRequest, validateAuthorizationCode, validateToken } from "./validate-authorization-code.mjs";
|
|
6
6
|
import { getJwks, verifyAccessToken, verifyJwsAccessToken } from "./verify.mjs";
|
|
7
|
-
|
|
8
|
-
export { authorizationCodeRequest, clientCredentialsToken, clientCredentialsTokenRequest, createAuthorizationCodeRequest, createAuthorizationURL, createClientCredentialsTokenRequest, createRefreshAccessTokenRequest, generateCodeChallenge, getJwks, getOAuth2Tokens, refreshAccessToken, refreshAccessTokenRequest, validateAuthorizationCode, validateToken, verifyAccessToken, verifyJwsAccessToken };
|
|
7
|
+
export { authorizationCodeRequest, clientCredentialsToken, clientCredentialsTokenRequest, createAuthorizationCodeRequest, createAuthorizationURL, createClientCredentialsTokenRequest, createRefreshAccessTokenRequest, generateCodeChallenge, getJwks, getOAuth2Tokens, refreshAccessToken, refreshAccessTokenRequest, validateAuthorizationCode, validateToken, verifyAccessToken, verifyJwsAccessToken };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { base64 } from "@better-auth/utils/base64";
|
|
2
2
|
import { betterFetch } from "@better-fetch/fetch";
|
|
3
|
-
|
|
4
3
|
//#region src/oauth2/refresh-access-token.ts
|
|
5
4
|
async function refreshAccessTokenRequest({ refreshToken, options, authentication, extraParams, resource }) {
|
|
6
5
|
options = typeof options === "function" ? await options() : options;
|
|
@@ -70,7 +69,7 @@ async function refreshAccessToken({ refreshToken, options, tokenEndpoint, authen
|
|
|
70
69
|
}
|
|
71
70
|
return tokens;
|
|
72
71
|
}
|
|
73
|
-
|
|
74
72
|
//#endregion
|
|
75
73
|
export { createRefreshAccessTokenRequest, refreshAccessToken, refreshAccessTokenRequest };
|
|
74
|
+
|
|
76
75
|
//# sourceMappingURL=refresh-access-token.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-access-token.mjs","names":[],"sources":["../../src/oauth2/refresh-access-token.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport type { AwaitableFunction } from \"../types\";\nimport type { OAuth2Tokens, ProviderOptions } from \"./oauth-provider\";\n\nexport async function refreshAccessTokenRequest({\n\trefreshToken,\n\toptions,\n\tauthentication,\n\textraParams,\n\tresource,\n}: {\n\trefreshToken: string;\n\toptions: AwaitableFunction<Partial<ProviderOptions>>;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\textraParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\toptions = typeof options === \"function\" ? await options() : options;\n\treturn createRefreshAccessTokenRequest({\n\t\trefreshToken,\n\t\toptions,\n\t\tauthentication,\n\t\textraParams,\n\t\tresource,\n\t});\n}\n\n/**\n * @deprecated use async'd refreshAccessTokenRequest instead\n */\nexport function createRefreshAccessTokenRequest({\n\trefreshToken,\n\toptions,\n\tauthentication,\n\textraParams,\n\tresource,\n}: {\n\trefreshToken: string;\n\toptions: ProviderOptions;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\textraParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\tconst body = new URLSearchParams();\n\tconst headers: Record<string, any> = {\n\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\taccept: \"application/json\",\n\t};\n\n\tbody.set(\"grant_type\", \"refresh_token\");\n\tbody.set(\"refresh_token\", refreshToken);\n\t// Use standard Base64 encoding for HTTP Basic Auth (OAuth2 spec, RFC 7617)\n\t// Fixes compatibility with providers like Notion, Twitter, etc.\n\tif (authentication === \"basic\") {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tif (primaryClientId) {\n\t\t\theaders[\"authorization\"] =\n\t\t\t\t\"Basic \" +\n\t\t\t\tbase64.encode(`${primaryClientId}:${options.clientSecret ?? \"\"}`);\n\t\t} else {\n\t\t\theaders[\"authorization\"] =\n\t\t\t\t\"Basic \" + base64.encode(`:${options.clientSecret ?? \"\"}`);\n\t\t}\n\t} else {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tbody.set(\"client_id\", primaryClientId);\n\t\tif (options.clientSecret) {\n\t\t\tbody.set(\"client_secret\", options.clientSecret);\n\t\t}\n\t}\n\n\tif (resource) {\n\t\tif (typeof resource === \"string\") {\n\t\t\tbody.append(\"resource\", resource);\n\t\t} else {\n\t\t\tfor (const _resource of resource) {\n\t\t\t\tbody.append(\"resource\", _resource);\n\t\t\t}\n\t\t}\n\t}\n\tif (extraParams) {\n\t\tfor (const [key, value] of Object.entries(extraParams)) {\n\t\t\tbody.set(key, value);\n\t\t}\n\t}\n\n\treturn {\n\t\tbody,\n\t\theaders,\n\t};\n}\n\nexport async function refreshAccessToken({\n\trefreshToken,\n\toptions,\n\ttokenEndpoint,\n\tauthentication,\n\textraParams,\n}: {\n\trefreshToken: string;\n\toptions: Partial<ProviderOptions>;\n\ttokenEndpoint: string;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\textraParams?: Record<string, string> | undefined;\n}): Promise<OAuth2Tokens> {\n\tconst { body, headers } = await createRefreshAccessTokenRequest({\n\t\trefreshToken,\n\t\toptions,\n\t\tauthentication,\n\t\textraParams,\n\t});\n\n\tconst { data, error } = await betterFetch<{\n\t\taccess_token: string;\n\t\trefresh_token?: string | undefined;\n\t\texpires_in?: number | undefined;\n\t\trefresh_token_expires_in?: number | undefined;\n\t\ttoken_type?: string | undefined;\n\t\tscope?: string | undefined;\n\t\tid_token?: string | undefined;\n\t}>(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\tbody,\n\t\theaders,\n\t});\n\tif (error) {\n\t\tthrow error;\n\t}\n\tconst tokens: OAuth2Tokens = {\n\t\taccessToken: data.access_token,\n\t\trefreshToken: data.refresh_token,\n\t\ttokenType: data.token_type,\n\t\tscopes: data.scope?.split(\" \"),\n\t\tidToken: data.id_token,\n\t};\n\n\tif (data.expires_in) {\n\t\tconst now = new Date();\n\t\ttokens.accessTokenExpiresAt = new Date(\n\t\t\tnow.getTime() + data.expires_in * 1000,\n\t\t);\n\t}\n\n\tif (data.refresh_token_expires_in) {\n\t\tconst now = new Date();\n\t\ttokens.refreshTokenExpiresAt = new Date(\n\t\t\tnow.getTime() + data.refresh_token_expires_in * 1000,\n\t\t);\n\t}\n\n\treturn tokens;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"refresh-access-token.mjs","names":[],"sources":["../../src/oauth2/refresh-access-token.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport type { AwaitableFunction } from \"../types\";\nimport type { OAuth2Tokens, ProviderOptions } from \"./oauth-provider\";\n\nexport async function refreshAccessTokenRequest({\n\trefreshToken,\n\toptions,\n\tauthentication,\n\textraParams,\n\tresource,\n}: {\n\trefreshToken: string;\n\toptions: AwaitableFunction<Partial<ProviderOptions>>;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\textraParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\toptions = typeof options === \"function\" ? await options() : options;\n\treturn createRefreshAccessTokenRequest({\n\t\trefreshToken,\n\t\toptions,\n\t\tauthentication,\n\t\textraParams,\n\t\tresource,\n\t});\n}\n\n/**\n * @deprecated use async'd refreshAccessTokenRequest instead\n */\nexport function createRefreshAccessTokenRequest({\n\trefreshToken,\n\toptions,\n\tauthentication,\n\textraParams,\n\tresource,\n}: {\n\trefreshToken: string;\n\toptions: ProviderOptions;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\textraParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\tconst body = new URLSearchParams();\n\tconst headers: Record<string, any> = {\n\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\taccept: \"application/json\",\n\t};\n\n\tbody.set(\"grant_type\", \"refresh_token\");\n\tbody.set(\"refresh_token\", refreshToken);\n\t// Use standard Base64 encoding for HTTP Basic Auth (OAuth2 spec, RFC 7617)\n\t// Fixes compatibility with providers like Notion, Twitter, etc.\n\tif (authentication === \"basic\") {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tif (primaryClientId) {\n\t\t\theaders[\"authorization\"] =\n\t\t\t\t\"Basic \" +\n\t\t\t\tbase64.encode(`${primaryClientId}:${options.clientSecret ?? \"\"}`);\n\t\t} else {\n\t\t\theaders[\"authorization\"] =\n\t\t\t\t\"Basic \" + base64.encode(`:${options.clientSecret ?? \"\"}`);\n\t\t}\n\t} else {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tbody.set(\"client_id\", primaryClientId);\n\t\tif (options.clientSecret) {\n\t\t\tbody.set(\"client_secret\", options.clientSecret);\n\t\t}\n\t}\n\n\tif (resource) {\n\t\tif (typeof resource === \"string\") {\n\t\t\tbody.append(\"resource\", resource);\n\t\t} else {\n\t\t\tfor (const _resource of resource) {\n\t\t\t\tbody.append(\"resource\", _resource);\n\t\t\t}\n\t\t}\n\t}\n\tif (extraParams) {\n\t\tfor (const [key, value] of Object.entries(extraParams)) {\n\t\t\tbody.set(key, value);\n\t\t}\n\t}\n\n\treturn {\n\t\tbody,\n\t\theaders,\n\t};\n}\n\nexport async function refreshAccessToken({\n\trefreshToken,\n\toptions,\n\ttokenEndpoint,\n\tauthentication,\n\textraParams,\n}: {\n\trefreshToken: string;\n\toptions: Partial<ProviderOptions>;\n\ttokenEndpoint: string;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\textraParams?: Record<string, string> | undefined;\n}): Promise<OAuth2Tokens> {\n\tconst { body, headers } = await createRefreshAccessTokenRequest({\n\t\trefreshToken,\n\t\toptions,\n\t\tauthentication,\n\t\textraParams,\n\t});\n\n\tconst { data, error } = await betterFetch<{\n\t\taccess_token: string;\n\t\trefresh_token?: string | undefined;\n\t\texpires_in?: number | undefined;\n\t\trefresh_token_expires_in?: number | undefined;\n\t\ttoken_type?: string | undefined;\n\t\tscope?: string | undefined;\n\t\tid_token?: string | undefined;\n\t}>(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\tbody,\n\t\theaders,\n\t});\n\tif (error) {\n\t\tthrow error;\n\t}\n\tconst tokens: OAuth2Tokens = {\n\t\taccessToken: data.access_token,\n\t\trefreshToken: data.refresh_token,\n\t\ttokenType: data.token_type,\n\t\tscopes: data.scope?.split(\" \"),\n\t\tidToken: data.id_token,\n\t};\n\n\tif (data.expires_in) {\n\t\tconst now = new Date();\n\t\ttokens.accessTokenExpiresAt = new Date(\n\t\t\tnow.getTime() + data.expires_in * 1000,\n\t\t);\n\t}\n\n\tif (data.refresh_token_expires_in) {\n\t\tconst now = new Date();\n\t\ttokens.refreshTokenExpiresAt = new Date(\n\t\t\tnow.getTime() + data.refresh_token_expires_in * 1000,\n\t\t);\n\t}\n\n\treturn tokens;\n}\n"],"mappings":";;;AAKA,eAAsB,0BAA0B,EAC/C,cACA,SACA,gBACA,aACA,YAOE;AACF,WAAU,OAAO,YAAY,aAAa,MAAM,SAAS,GAAG;AAC5D,QAAO,gCAAgC;EACtC;EACA;EACA;EACA;EACA;EACA,CAAC;;;;;AAMH,SAAgB,gCAAgC,EAC/C,cACA,SACA,gBACA,aACA,YAOE;CACF,MAAM,OAAO,IAAI,iBAAiB;CAClC,MAAM,UAA+B;EACpC,gBAAgB;EAChB,QAAQ;EACR;AAED,MAAK,IAAI,cAAc,gBAAgB;AACvC,MAAK,IAAI,iBAAiB,aAAa;AAGvC,KAAI,mBAAmB,SAAS;EAC/B,MAAM,kBAAkB,MAAM,QAAQ,QAAQ,SAAS,GACpD,QAAQ,SAAS,KACjB,QAAQ;AACX,MAAI,gBACH,SAAQ,mBACP,WACA,OAAO,OAAO,GAAG,gBAAgB,GAAG,QAAQ,gBAAgB,KAAK;MAElE,SAAQ,mBACP,WAAW,OAAO,OAAO,IAAI,QAAQ,gBAAgB,KAAK;QAEtD;EACN,MAAM,kBAAkB,MAAM,QAAQ,QAAQ,SAAS,GACpD,QAAQ,SAAS,KACjB,QAAQ;AACX,OAAK,IAAI,aAAa,gBAAgB;AACtC,MAAI,QAAQ,aACX,MAAK,IAAI,iBAAiB,QAAQ,aAAa;;AAIjD,KAAI,SACH,KAAI,OAAO,aAAa,SACvB,MAAK,OAAO,YAAY,SAAS;KAEjC,MAAK,MAAM,aAAa,SACvB,MAAK,OAAO,YAAY,UAAU;AAIrC,KAAI,YACH,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,CACrD,MAAK,IAAI,KAAK,MAAM;AAItB,QAAO;EACN;EACA;EACA;;AAGF,eAAsB,mBAAmB,EACxC,cACA,SACA,eACA,gBACA,eAOyB;CACzB,MAAM,EAAE,MAAM,YAAY,MAAM,gCAAgC;EAC/D;EACA;EACA;EACA;EACA,CAAC;CAEF,MAAM,EAAE,MAAM,UAAU,MAAM,YAQ3B,eAAe;EACjB,QAAQ;EACR;EACA;EACA,CAAC;AACF,KAAI,MACH,OAAM;CAEP,MAAM,SAAuB;EAC5B,aAAa,KAAK;EAClB,cAAc,KAAK;EACnB,WAAW,KAAK;EAChB,QAAQ,KAAK,OAAO,MAAM,IAAI;EAC9B,SAAS,KAAK;EACd;AAED,KAAI,KAAK,YAAY;EACpB,MAAM,sBAAM,IAAI,MAAM;AACtB,SAAO,uBAAuB,IAAI,KACjC,IAAI,SAAS,GAAG,KAAK,aAAa,IAClC;;AAGF,KAAI,KAAK,0BAA0B;EAClC,MAAM,sBAAM,IAAI,MAAM;AACtB,SAAO,wBAAwB,IAAI,KAClC,IAAI,SAAS,GAAG,KAAK,2BAA2B,IAChD;;AAGF,QAAO"}
|
package/dist/oauth2/utils.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { base64Url } from "@better-auth/utils/base64";
|
|
2
|
-
|
|
3
2
|
//#region src/oauth2/utils.ts
|
|
4
3
|
function getOAuth2Tokens(data) {
|
|
5
4
|
const getDate = (seconds) => {
|
|
@@ -22,7 +21,7 @@ async function generateCodeChallenge(codeVerifier) {
|
|
|
22
21
|
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
23
22
|
return base64Url.encode(new Uint8Array(hash), { padding: false });
|
|
24
23
|
}
|
|
25
|
-
|
|
26
24
|
//#endregion
|
|
27
25
|
export { generateCodeChallenge, getOAuth2Tokens };
|
|
26
|
+
|
|
28
27
|
//# sourceMappingURL=utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","names":[],"sources":["../../src/oauth2/utils.ts"],"sourcesContent":["import { base64Url } from \"@better-auth/utils/base64\";\nimport type { OAuth2Tokens } from \"./oauth-provider\";\n\nexport function getOAuth2Tokens(data: Record<string, any>): OAuth2Tokens {\n\tconst getDate = (seconds: number) => {\n\t\tconst now = new Date();\n\t\treturn new Date(now.getTime() + seconds * 1000);\n\t};\n\n\treturn {\n\t\ttokenType: data.token_type,\n\t\taccessToken: data.access_token,\n\t\trefreshToken: data.refresh_token,\n\t\taccessTokenExpiresAt: data.expires_in\n\t\t\t? getDate(data.expires_in)\n\t\t\t: undefined,\n\t\trefreshTokenExpiresAt: data.refresh_token_expires_in\n\t\t\t? getDate(data.refresh_token_expires_in)\n\t\t\t: undefined,\n\t\tscopes: data?.scope\n\t\t\t? typeof data.scope === \"string\"\n\t\t\t\t? data.scope.split(\" \")\n\t\t\t\t: data.scope\n\t\t\t: [],\n\t\tidToken: data.id_token,\n\t\t// Preserve the raw token response for provider-specific fields\n\t\traw: data,\n\t};\n}\n\nexport async function generateCodeChallenge(codeVerifier: string) {\n\tconst encoder = new TextEncoder();\n\tconst data = encoder.encode(codeVerifier);\n\tconst hash = await crypto.subtle.digest(\"SHA-256\", data);\n\treturn base64Url.encode(new Uint8Array(hash), {\n\t\tpadding: false,\n\t});\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.mjs","names":[],"sources":["../../src/oauth2/utils.ts"],"sourcesContent":["import { base64Url } from \"@better-auth/utils/base64\";\nimport type { OAuth2Tokens } from \"./oauth-provider\";\n\nexport function getOAuth2Tokens(data: Record<string, any>): OAuth2Tokens {\n\tconst getDate = (seconds: number) => {\n\t\tconst now = new Date();\n\t\treturn new Date(now.getTime() + seconds * 1000);\n\t};\n\n\treturn {\n\t\ttokenType: data.token_type,\n\t\taccessToken: data.access_token,\n\t\trefreshToken: data.refresh_token,\n\t\taccessTokenExpiresAt: data.expires_in\n\t\t\t? getDate(data.expires_in)\n\t\t\t: undefined,\n\t\trefreshTokenExpiresAt: data.refresh_token_expires_in\n\t\t\t? getDate(data.refresh_token_expires_in)\n\t\t\t: undefined,\n\t\tscopes: data?.scope\n\t\t\t? typeof data.scope === \"string\"\n\t\t\t\t? data.scope.split(\" \")\n\t\t\t\t: data.scope\n\t\t\t: [],\n\t\tidToken: data.id_token,\n\t\t// Preserve the raw token response for provider-specific fields\n\t\traw: data,\n\t};\n}\n\nexport async function generateCodeChallenge(codeVerifier: string) {\n\tconst encoder = new TextEncoder();\n\tconst data = encoder.encode(codeVerifier);\n\tconst hash = await crypto.subtle.digest(\"SHA-256\", data);\n\treturn base64Url.encode(new Uint8Array(hash), {\n\t\tpadding: false,\n\t});\n}\n"],"mappings":";;AAGA,SAAgB,gBAAgB,MAAyC;CACxE,MAAM,WAAW,YAAoB;EACpC,MAAM,sBAAM,IAAI,MAAM;AACtB,SAAO,IAAI,KAAK,IAAI,SAAS,GAAG,UAAU,IAAK;;AAGhD,QAAO;EACN,WAAW,KAAK;EAChB,aAAa,KAAK;EAClB,cAAc,KAAK;EACnB,sBAAsB,KAAK,aACxB,QAAQ,KAAK,WAAW,GACxB,KAAA;EACH,uBAAuB,KAAK,2BACzB,QAAQ,KAAK,yBAAyB,GACtC,KAAA;EACH,QAAQ,MAAM,QACX,OAAO,KAAK,UAAU,WACrB,KAAK,MAAM,MAAM,IAAI,GACrB,KAAK,QACN,EAAE;EACL,SAAS,KAAK;EAEd,KAAK;EACL;;AAGF,eAAsB,sBAAsB,cAAsB;CAEjE,MAAM,OADU,IAAI,aAAa,CACZ,OAAO,aAAa;CACzC,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,WAAW,KAAK;AACxD,QAAO,UAAU,OAAO,IAAI,WAAW,KAAK,EAAE,EAC7C,SAAS,OACT,CAAC"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { AwaitableFunction } from "../types/helper.mjs";
|
|
2
|
-
import "../types/index.mjs";
|
|
3
2
|
import { OAuth2Tokens, ProviderOptions } from "./oauth-provider.mjs";
|
|
4
|
-
import "./index.mjs";
|
|
5
3
|
import * as jose from "jose";
|
|
6
4
|
|
|
7
5
|
//#region src/oauth2/validate-authorization-code.d.ts
|
|
@@ -3,7 +3,6 @@ import "./index.mjs";
|
|
|
3
3
|
import { base64 } from "@better-auth/utils/base64";
|
|
4
4
|
import { betterFetch } from "@better-fetch/fetch";
|
|
5
5
|
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
6
|
-
|
|
7
6
|
//#region src/oauth2/validate-authorization-code.ts
|
|
8
7
|
async function authorizationCodeRequest({ code, codeVerifier, redirectURI, options, authentication, deviceId, headers, additionalParams = {}, resource }) {
|
|
9
8
|
options = typeof options === "function" ? await options() : options;
|
|
@@ -77,7 +76,7 @@ async function validateToken(token, jwksEndpoint, options) {
|
|
|
77
76
|
issuer: options?.issuer
|
|
78
77
|
});
|
|
79
78
|
}
|
|
80
|
-
|
|
81
79
|
//#endregion
|
|
82
80
|
export { authorizationCodeRequest, createAuthorizationCodeRequest, validateAuthorizationCode, validateToken };
|
|
81
|
+
|
|
83
82
|
//# sourceMappingURL=validate-authorization-code.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-authorization-code.mjs","names":[],"sources":["../../src/oauth2/validate-authorization-code.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { createRemoteJWKSet, jwtVerify } from \"jose\";\nimport type { AwaitableFunction } from \"../types\";\nimport type { ProviderOptions } from \"./index\";\nimport { getOAuth2Tokens } from \"./index\";\n\nexport async function authorizationCodeRequest({\n\tcode,\n\tcodeVerifier,\n\tredirectURI,\n\toptions,\n\tauthentication,\n\tdeviceId,\n\theaders,\n\tadditionalParams = {},\n\tresource,\n}: {\n\tcode: string;\n\tredirectURI: string;\n\toptions: AwaitableFunction<Partial<ProviderOptions>>;\n\tcodeVerifier?: string | undefined;\n\tdeviceId?: string | undefined;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\theaders?: Record<string, string> | undefined;\n\tadditionalParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\toptions = typeof options === \"function\" ? await options() : options;\n\treturn createAuthorizationCodeRequest({\n\t\tcode,\n\t\tcodeVerifier,\n\t\tredirectURI,\n\t\toptions,\n\t\tauthentication,\n\t\tdeviceId,\n\t\theaders,\n\t\tadditionalParams,\n\t\tresource,\n\t});\n}\n\n/**\n * @deprecated use async'd authorizationCodeRequest instead\n */\nexport function createAuthorizationCodeRequest({\n\tcode,\n\tcodeVerifier,\n\tredirectURI,\n\toptions,\n\tauthentication,\n\tdeviceId,\n\theaders,\n\tadditionalParams = {},\n\tresource,\n}: {\n\tcode: string;\n\tredirectURI: string;\n\toptions: Partial<ProviderOptions>;\n\tcodeVerifier?: string | undefined;\n\tdeviceId?: string | undefined;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\theaders?: Record<string, string> | undefined;\n\tadditionalParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\tconst body = new URLSearchParams();\n\tconst requestHeaders: Record<string, any> = {\n\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\taccept: \"application/json\",\n\t\t...headers,\n\t};\n\n\tbody.set(\"grant_type\", \"authorization_code\");\n\tbody.set(\"code\", code);\n\tcodeVerifier && body.set(\"code_verifier\", codeVerifier);\n\toptions.clientKey && body.set(\"client_key\", options.clientKey);\n\tdeviceId && body.set(\"device_id\", deviceId);\n\tbody.set(\"redirect_uri\", options.redirectURI || redirectURI);\n\tif (resource) {\n\t\tif (typeof resource === \"string\") {\n\t\t\tbody.append(\"resource\", resource);\n\t\t} else {\n\t\t\tfor (const _resource of resource) {\n\t\t\t\tbody.append(\"resource\", _resource);\n\t\t\t}\n\t\t}\n\t}\n\t// Use standard Base64 encoding for HTTP Basic Auth (OAuth2 spec, RFC 7617)\n\t// Fixes compatibility with providers like Notion, Twitter, etc.\n\tif (authentication === \"basic\") {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tconst encodedCredentials = base64.encode(\n\t\t\t`${primaryClientId}:${options.clientSecret ?? \"\"}`,\n\t\t);\n\t\trequestHeaders[\"authorization\"] = `Basic ${encodedCredentials}`;\n\t} else {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tbody.set(\"client_id\", primaryClientId);\n\t\tif (options.clientSecret) {\n\t\t\tbody.set(\"client_secret\", options.clientSecret);\n\t\t}\n\t}\n\n\tfor (const [key, value] of Object.entries(additionalParams)) {\n\t\tif (!body.has(key)) body.append(key, value);\n\t}\n\n\treturn {\n\t\tbody,\n\t\theaders: requestHeaders,\n\t};\n}\n\nexport async function validateAuthorizationCode({\n\tcode,\n\tcodeVerifier,\n\tredirectURI,\n\toptions,\n\ttokenEndpoint,\n\tauthentication,\n\tdeviceId,\n\theaders,\n\tadditionalParams = {},\n\tresource,\n}: {\n\tcode: string;\n\tredirectURI: string;\n\toptions: AwaitableFunction<Partial<ProviderOptions>>;\n\tcodeVerifier?: string | undefined;\n\tdeviceId?: string | undefined;\n\ttokenEndpoint: string;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\theaders?: Record<string, string> | undefined;\n\tadditionalParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\tconst { body, headers: requestHeaders } = await authorizationCodeRequest({\n\t\tcode,\n\t\tcodeVerifier,\n\t\tredirectURI,\n\t\toptions,\n\t\tauthentication,\n\t\tdeviceId,\n\t\theaders,\n\t\tadditionalParams,\n\t\tresource,\n\t});\n\n\tconst { data, error } = await betterFetch<object>(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\tbody: body,\n\t\theaders: requestHeaders,\n\t});\n\tif (error) {\n\t\tthrow error;\n\t}\n\tconst tokens = getOAuth2Tokens(data);\n\treturn tokens;\n}\n\nexport async function validateToken(\n\ttoken: string,\n\tjwksEndpoint: string,\n\toptions?: {\n\t\taudience?: string | string[];\n\t\tissuer?: string | string[];\n\t},\n) {\n\tconst jwks = createRemoteJWKSet(new URL(jwksEndpoint));\n\tconst verified = await jwtVerify(token, jwks, {\n\t\taudience: options?.audience,\n\t\tissuer: options?.issuer,\n\t});\n\treturn verified;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate-authorization-code.mjs","names":[],"sources":["../../src/oauth2/validate-authorization-code.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { createRemoteJWKSet, jwtVerify } from \"jose\";\nimport type { AwaitableFunction } from \"../types\";\nimport type { ProviderOptions } from \"./index\";\nimport { getOAuth2Tokens } from \"./index\";\n\nexport async function authorizationCodeRequest({\n\tcode,\n\tcodeVerifier,\n\tredirectURI,\n\toptions,\n\tauthentication,\n\tdeviceId,\n\theaders,\n\tadditionalParams = {},\n\tresource,\n}: {\n\tcode: string;\n\tredirectURI: string;\n\toptions: AwaitableFunction<Partial<ProviderOptions>>;\n\tcodeVerifier?: string | undefined;\n\tdeviceId?: string | undefined;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\theaders?: Record<string, string> | undefined;\n\tadditionalParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\toptions = typeof options === \"function\" ? await options() : options;\n\treturn createAuthorizationCodeRequest({\n\t\tcode,\n\t\tcodeVerifier,\n\t\tredirectURI,\n\t\toptions,\n\t\tauthentication,\n\t\tdeviceId,\n\t\theaders,\n\t\tadditionalParams,\n\t\tresource,\n\t});\n}\n\n/**\n * @deprecated use async'd authorizationCodeRequest instead\n */\nexport function createAuthorizationCodeRequest({\n\tcode,\n\tcodeVerifier,\n\tredirectURI,\n\toptions,\n\tauthentication,\n\tdeviceId,\n\theaders,\n\tadditionalParams = {},\n\tresource,\n}: {\n\tcode: string;\n\tredirectURI: string;\n\toptions: Partial<ProviderOptions>;\n\tcodeVerifier?: string | undefined;\n\tdeviceId?: string | undefined;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\theaders?: Record<string, string> | undefined;\n\tadditionalParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\tconst body = new URLSearchParams();\n\tconst requestHeaders: Record<string, any> = {\n\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\taccept: \"application/json\",\n\t\t...headers,\n\t};\n\n\tbody.set(\"grant_type\", \"authorization_code\");\n\tbody.set(\"code\", code);\n\tcodeVerifier && body.set(\"code_verifier\", codeVerifier);\n\toptions.clientKey && body.set(\"client_key\", options.clientKey);\n\tdeviceId && body.set(\"device_id\", deviceId);\n\tbody.set(\"redirect_uri\", options.redirectURI || redirectURI);\n\tif (resource) {\n\t\tif (typeof resource === \"string\") {\n\t\t\tbody.append(\"resource\", resource);\n\t\t} else {\n\t\t\tfor (const _resource of resource) {\n\t\t\t\tbody.append(\"resource\", _resource);\n\t\t\t}\n\t\t}\n\t}\n\t// Use standard Base64 encoding for HTTP Basic Auth (OAuth2 spec, RFC 7617)\n\t// Fixes compatibility with providers like Notion, Twitter, etc.\n\tif (authentication === \"basic\") {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tconst encodedCredentials = base64.encode(\n\t\t\t`${primaryClientId}:${options.clientSecret ?? \"\"}`,\n\t\t);\n\t\trequestHeaders[\"authorization\"] = `Basic ${encodedCredentials}`;\n\t} else {\n\t\tconst primaryClientId = Array.isArray(options.clientId)\n\t\t\t? options.clientId[0]\n\t\t\t: options.clientId;\n\t\tbody.set(\"client_id\", primaryClientId);\n\t\tif (options.clientSecret) {\n\t\t\tbody.set(\"client_secret\", options.clientSecret);\n\t\t}\n\t}\n\n\tfor (const [key, value] of Object.entries(additionalParams)) {\n\t\tif (!body.has(key)) body.append(key, value);\n\t}\n\n\treturn {\n\t\tbody,\n\t\theaders: requestHeaders,\n\t};\n}\n\nexport async function validateAuthorizationCode({\n\tcode,\n\tcodeVerifier,\n\tredirectURI,\n\toptions,\n\ttokenEndpoint,\n\tauthentication,\n\tdeviceId,\n\theaders,\n\tadditionalParams = {},\n\tresource,\n}: {\n\tcode: string;\n\tredirectURI: string;\n\toptions: AwaitableFunction<Partial<ProviderOptions>>;\n\tcodeVerifier?: string | undefined;\n\tdeviceId?: string | undefined;\n\ttokenEndpoint: string;\n\tauthentication?: (\"basic\" | \"post\") | undefined;\n\theaders?: Record<string, string> | undefined;\n\tadditionalParams?: Record<string, string> | undefined;\n\tresource?: (string | string[]) | undefined;\n}) {\n\tconst { body, headers: requestHeaders } = await authorizationCodeRequest({\n\t\tcode,\n\t\tcodeVerifier,\n\t\tredirectURI,\n\t\toptions,\n\t\tauthentication,\n\t\tdeviceId,\n\t\theaders,\n\t\tadditionalParams,\n\t\tresource,\n\t});\n\n\tconst { data, error } = await betterFetch<object>(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\tbody: body,\n\t\theaders: requestHeaders,\n\t});\n\tif (error) {\n\t\tthrow error;\n\t}\n\tconst tokens = getOAuth2Tokens(data);\n\treturn tokens;\n}\n\nexport async function validateToken(\n\ttoken: string,\n\tjwksEndpoint: string,\n\toptions?: {\n\t\taudience?: string | string[];\n\t\tissuer?: string | string[];\n\t},\n) {\n\tconst jwks = createRemoteJWKSet(new URL(jwksEndpoint));\n\tconst verified = await jwtVerify(token, jwks, {\n\t\taudience: options?.audience,\n\t\tissuer: options?.issuer,\n\t});\n\treturn verified;\n}\n"],"mappings":";;;;;;AAOA,eAAsB,yBAAyB,EAC9C,MACA,cACA,aACA,SACA,gBACA,UACA,SACA,mBAAmB,EAAE,EACrB,YAWE;AACF,WAAU,OAAO,YAAY,aAAa,MAAM,SAAS,GAAG;AAC5D,QAAO,+BAA+B;EACrC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC;;;;;AAMH,SAAgB,+BAA+B,EAC9C,MACA,cACA,aACA,SACA,gBACA,UACA,SACA,mBAAmB,EAAE,EACrB,YAWE;CACF,MAAM,OAAO,IAAI,iBAAiB;CAClC,MAAM,iBAAsC;EAC3C,gBAAgB;EAChB,QAAQ;EACR,GAAG;EACH;AAED,MAAK,IAAI,cAAc,qBAAqB;AAC5C,MAAK,IAAI,QAAQ,KAAK;AACtB,iBAAgB,KAAK,IAAI,iBAAiB,aAAa;AACvD,SAAQ,aAAa,KAAK,IAAI,cAAc,QAAQ,UAAU;AAC9D,aAAY,KAAK,IAAI,aAAa,SAAS;AAC3C,MAAK,IAAI,gBAAgB,QAAQ,eAAe,YAAY;AAC5D,KAAI,SACH,KAAI,OAAO,aAAa,SACvB,MAAK,OAAO,YAAY,SAAS;KAEjC,MAAK,MAAM,aAAa,SACvB,MAAK,OAAO,YAAY,UAAU;AAMrC,KAAI,mBAAmB,SAAS;EAC/B,MAAM,kBAAkB,MAAM,QAAQ,QAAQ,SAAS,GACpD,QAAQ,SAAS,KACjB,QAAQ;AAIX,iBAAe,mBAAmB,SAHP,OAAO,OACjC,GAAG,gBAAgB,GAAG,QAAQ,gBAAgB,KAC9C;QAEK;EACN,MAAM,kBAAkB,MAAM,QAAQ,QAAQ,SAAS,GACpD,QAAQ,SAAS,KACjB,QAAQ;AACX,OAAK,IAAI,aAAa,gBAAgB;AACtC,MAAI,QAAQ,aACX,MAAK,IAAI,iBAAiB,QAAQ,aAAa;;AAIjD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,iBAAiB,CAC1D,KAAI,CAAC,KAAK,IAAI,IAAI,CAAE,MAAK,OAAO,KAAK,MAAM;AAG5C,QAAO;EACN;EACA,SAAS;EACT;;AAGF,eAAsB,0BAA0B,EAC/C,MACA,cACA,aACA,SACA,eACA,gBACA,UACA,SACA,mBAAmB,EAAE,EACrB,YAYE;CACF,MAAM,EAAE,MAAM,SAAS,mBAAmB,MAAM,yBAAyB;EACxE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC;CAEF,MAAM,EAAE,MAAM,UAAU,MAAM,YAAoB,eAAe;EAChE,QAAQ;EACF;EACN,SAAS;EACT,CAAC;AACF,KAAI,MACH,OAAM;AAGP,QADe,gBAAgB,KAAK;;AAIrC,eAAsB,cACrB,OACA,cACA,SAIC;AAMD,QAJiB,MAAM,UAAU,OADpB,mBAAmB,IAAI,IAAI,aAAa,CAAC,EACR;EAC7C,UAAU,SAAS;EACnB,QAAQ,SAAS;EACjB,CAAC"}
|
package/dist/oauth2/verify.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import "../env/index.mjs";
|
|
|
3
3
|
import { APIError } from "better-call";
|
|
4
4
|
import { betterFetch } from "@better-fetch/fetch";
|
|
5
5
|
import { UnsecuredJWT, createLocalJWKSet, decodeProtectedHeader, jwtVerify } from "jose";
|
|
6
|
-
|
|
7
6
|
//#region src/oauth2/verify.ts
|
|
8
7
|
/** Last fetched jwks used locally in getJwks @internal */
|
|
9
8
|
let jwks;
|
|
@@ -90,7 +89,7 @@ async function verifyAccessToken(token, opts) {
|
|
|
90
89
|
}
|
|
91
90
|
return payload;
|
|
92
91
|
}
|
|
93
|
-
|
|
94
92
|
//#endregion
|
|
95
93
|
export { getJwks, verifyAccessToken, verifyJwsAccessToken };
|
|
94
|
+
|
|
96
95
|
//# sourceMappingURL=verify.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.mjs","names":[],"sources":["../../src/oauth2/verify.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport type {\n\tJSONWebKeySet,\n\tJWTPayload,\n\tJWTVerifyOptions,\n\tProtectedHeaderParameters,\n} from \"jose\";\nimport {\n\tcreateLocalJWKSet,\n\tdecodeProtectedHeader,\n\tjwtVerify,\n\tUnsecuredJWT,\n} from \"jose\";\nimport { logger } from \"../env\";\n\n/** Last fetched jwks used locally in getJwks @internal */\nlet jwks: JSONWebKeySet | undefined;\n\nexport interface VerifyAccessTokenRemote {\n\t/** Full url of the introspect endpoint. Should end with `/oauth2/introspect` */\n\tintrospectUrl: string;\n\t/** Client Secret */\n\tclientId: string;\n\t/** Client Secret */\n\tclientSecret: string;\n\t/**\n\t * Forces remote verification of a token.\n\t * This ensures attached session (if applicable)\n\t * is also still active.\n\t */\n\tforce?: boolean;\n}\n\n/**\n * Performs local verification of an access token for your APIs.\n *\n * Can also be configured for remote verification.\n */\nexport async function verifyJwsAccessToken(\n\ttoken: string,\n\topts: {\n\t\t/** Jwks url or promise of a Jwks */\n\t\tjwksFetch: string | (() => Promise<JSONWebKeySet | undefined>);\n\t\t/** Verify options */\n\t\tverifyOptions: JWTVerifyOptions &\n\t\t\tRequired<Pick<JWTVerifyOptions, \"audience\" | \"issuer\">>;\n\t},\n) {\n\ttry {\n\t\tconst jwks = await getJwks(token, opts);\n\t\tconst jwt = await jwtVerify<JWTPayload>(\n\t\t\ttoken,\n\t\t\tcreateLocalJWKSet(jwks),\n\t\t\topts.verifyOptions,\n\t\t);\n\t\t// Return the JWT payload in introspection format\n\t\t// https://datatracker.ietf.org/doc/html/rfc7662#section-2.2\n\t\tif (jwt.payload.azp) {\n\t\t\tjwt.payload.client_id = jwt.payload.azp;\n\t\t}\n\t\treturn jwt.payload;\n\t} catch (error) {\n\t\tif (error instanceof Error) throw error;\n\t\tthrow new Error(error as unknown as string);\n\t}\n}\n\nexport async function getJwks(\n\ttoken: string,\n\topts: {\n\t\t/** Jwks url or promise of a Jwks */\n\t\tjwksFetch: string | (() => Promise<JSONWebKeySet | undefined>);\n\t},\n) {\n\t// Attempt to decode the token and find a matching kid in jwks\n\tlet jwtHeaders: ProtectedHeaderParameters | undefined;\n\ttry {\n\t\tjwtHeaders = decodeProtectedHeader(token);\n\t} catch (error) {\n\t\tif (error instanceof Error) throw error;\n\t\tthrow new Error(error as unknown as string);\n\t}\n\n\tif (!jwtHeaders.kid) throw new Error(\"Missing jwt kid\");\n\n\t// Fetch jwks if not set or has a different kid than the one stored\n\tif (!jwks || !jwks.keys.find((jwk) => jwk.kid === jwtHeaders.kid)) {\n\t\tjwks =\n\t\t\ttypeof opts.jwksFetch === \"string\"\n\t\t\t\t? await betterFetch<JSONWebKeySet>(opts.jwksFetch, {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t},\n\t\t\t\t\t}).then(async (res) => {\n\t\t\t\t\t\tif (res.error)\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Jwks failed: ${res.error.message ?? res.error.statusText}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn res.data;\n\t\t\t\t\t})\n\t\t\t\t: await opts.jwksFetch();\n\t\tif (!jwks) throw new Error(\"No jwks found\");\n\t}\n\n\treturn jwks;\n}\n\n/**\n * Performs local verification of an access token for your API.\n *\n * Can also be configured for remote verification.\n */\nexport async function verifyAccessToken(\n\ttoken: string,\n\topts: {\n\t\t/** Verify options */\n\t\tverifyOptions: JWTVerifyOptions &\n\t\t\tRequired<Pick<JWTVerifyOptions, \"audience\" | \"issuer\">>;\n\t\t/** Scopes to additionally verify. Token must include all but not exact. */\n\t\tscopes?: string[];\n\t\t/** Required to verify access token locally */\n\t\tjwksUrl?: string;\n\t\t/** If provided, can verify a token remotely */\n\t\tremoteVerify?: VerifyAccessTokenRemote;\n\t},\n) {\n\tlet payload: JWTPayload | undefined;\n\t// Locally verify\n\tif (opts.jwksUrl && !opts?.remoteVerify?.force) {\n\t\ttry {\n\t\t\tpayload = await verifyJwsAccessToken(token, {\n\t\t\t\tjwksFetch: opts.jwksUrl,\n\t\t\t\tverifyOptions: opts.verifyOptions,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tif (error.name === \"TypeError\" || error.name === \"JWSInvalid\") {\n\t\t\t\t\t// likely an opaque token (continue)\n\t\t\t\t} else if (error.name === \"JWTExpired\") {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: \"token expired\",\n\t\t\t\t\t});\n\t\t\t\t} else if (error.name === \"JWTInvalid\") {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: \"token invalid\",\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(error as unknown as string);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remote verify\n\tif (opts?.remoteVerify) {\n\t\tconst { data: introspect, error: introspectError } = await betterFetch<\n\t\t\tJWTPayload & {\n\t\t\t\tactive: boolean;\n\t\t\t}\n\t\t>(opts.remoteVerify.introspectUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tclient_id: opts.remoteVerify.clientId,\n\t\t\t\tclient_secret: opts.remoteVerify.clientSecret,\n\t\t\t\ttoken,\n\t\t\t\ttoken_type_hint: \"access_token\",\n\t\t\t}).toString(),\n\t\t});\n\t\tif (introspectError)\n\t\t\tlogger.error(\n\t\t\t\t`Introspection failed: ${introspectError.message ?? introspectError.statusText}`,\n\t\t\t);\n\t\tif (!introspect)\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\tmessage: \"introspection failed\",\n\t\t\t});\n\t\tif (!introspect.active)\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"token inactive\",\n\t\t\t});\n\t\t// Verifies payload using verify options (token valid through introspect)\n\t\ttry {\n\t\t\tconst unsecuredJwt = new UnsecuredJWT(introspect).encode();\n\t\t\tconst { audience: _audience, ...verifyOptions } = opts.verifyOptions;\n\t\t\tconst verify = introspect.aud\n\t\t\t\t? UnsecuredJWT.decode(unsecuredJwt, opts.verifyOptions)\n\t\t\t\t: UnsecuredJWT.decode(unsecuredJwt, verifyOptions);\n\t\t\tpayload = verify.payload;\n\t\t} catch (error) {\n\t\t\tthrow new Error(error as unknown as string);\n\t\t}\n\t}\n\n\tif (!payload)\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\tmessage: `no token payload`,\n\t\t});\n\n\t// Check scopes if provided\n\tif (opts.scopes) {\n\t\tconst validScopes = new Set(\n\t\t\t(payload.scope as string | undefined)?.split(\" \"),\n\t\t);\n\t\tfor (const sc of opts.scopes) {\n\t\t\tif (!validScopes.has(sc)) {\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: `invalid scope ${sc}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn payload;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify.mjs","names":[],"sources":["../../src/oauth2/verify.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport type {\n\tJSONWebKeySet,\n\tJWTPayload,\n\tJWTVerifyOptions,\n\tProtectedHeaderParameters,\n} from \"jose\";\nimport {\n\tcreateLocalJWKSet,\n\tdecodeProtectedHeader,\n\tjwtVerify,\n\tUnsecuredJWT,\n} from \"jose\";\nimport { logger } from \"../env\";\n\n/** Last fetched jwks used locally in getJwks @internal */\nlet jwks: JSONWebKeySet | undefined;\n\nexport interface VerifyAccessTokenRemote {\n\t/** Full url of the introspect endpoint. Should end with `/oauth2/introspect` */\n\tintrospectUrl: string;\n\t/** Client Secret */\n\tclientId: string;\n\t/** Client Secret */\n\tclientSecret: string;\n\t/**\n\t * Forces remote verification of a token.\n\t * This ensures attached session (if applicable)\n\t * is also still active.\n\t */\n\tforce?: boolean;\n}\n\n/**\n * Performs local verification of an access token for your APIs.\n *\n * Can also be configured for remote verification.\n */\nexport async function verifyJwsAccessToken(\n\ttoken: string,\n\topts: {\n\t\t/** Jwks url or promise of a Jwks */\n\t\tjwksFetch: string | (() => Promise<JSONWebKeySet | undefined>);\n\t\t/** Verify options */\n\t\tverifyOptions: JWTVerifyOptions &\n\t\t\tRequired<Pick<JWTVerifyOptions, \"audience\" | \"issuer\">>;\n\t},\n) {\n\ttry {\n\t\tconst jwks = await getJwks(token, opts);\n\t\tconst jwt = await jwtVerify<JWTPayload>(\n\t\t\ttoken,\n\t\t\tcreateLocalJWKSet(jwks),\n\t\t\topts.verifyOptions,\n\t\t);\n\t\t// Return the JWT payload in introspection format\n\t\t// https://datatracker.ietf.org/doc/html/rfc7662#section-2.2\n\t\tif (jwt.payload.azp) {\n\t\t\tjwt.payload.client_id = jwt.payload.azp;\n\t\t}\n\t\treturn jwt.payload;\n\t} catch (error) {\n\t\tif (error instanceof Error) throw error;\n\t\tthrow new Error(error as unknown as string);\n\t}\n}\n\nexport async function getJwks(\n\ttoken: string,\n\topts: {\n\t\t/** Jwks url or promise of a Jwks */\n\t\tjwksFetch: string | (() => Promise<JSONWebKeySet | undefined>);\n\t},\n) {\n\t// Attempt to decode the token and find a matching kid in jwks\n\tlet jwtHeaders: ProtectedHeaderParameters | undefined;\n\ttry {\n\t\tjwtHeaders = decodeProtectedHeader(token);\n\t} catch (error) {\n\t\tif (error instanceof Error) throw error;\n\t\tthrow new Error(error as unknown as string);\n\t}\n\n\tif (!jwtHeaders.kid) throw new Error(\"Missing jwt kid\");\n\n\t// Fetch jwks if not set or has a different kid than the one stored\n\tif (!jwks || !jwks.keys.find((jwk) => jwk.kid === jwtHeaders.kid)) {\n\t\tjwks =\n\t\t\ttypeof opts.jwksFetch === \"string\"\n\t\t\t\t? await betterFetch<JSONWebKeySet>(opts.jwksFetch, {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t},\n\t\t\t\t\t}).then(async (res) => {\n\t\t\t\t\t\tif (res.error)\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Jwks failed: ${res.error.message ?? res.error.statusText}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn res.data;\n\t\t\t\t\t})\n\t\t\t\t: await opts.jwksFetch();\n\t\tif (!jwks) throw new Error(\"No jwks found\");\n\t}\n\n\treturn jwks;\n}\n\n/**\n * Performs local verification of an access token for your API.\n *\n * Can also be configured for remote verification.\n */\nexport async function verifyAccessToken(\n\ttoken: string,\n\topts: {\n\t\t/** Verify options */\n\t\tverifyOptions: JWTVerifyOptions &\n\t\t\tRequired<Pick<JWTVerifyOptions, \"audience\" | \"issuer\">>;\n\t\t/** Scopes to additionally verify. Token must include all but not exact. */\n\t\tscopes?: string[];\n\t\t/** Required to verify access token locally */\n\t\tjwksUrl?: string;\n\t\t/** If provided, can verify a token remotely */\n\t\tremoteVerify?: VerifyAccessTokenRemote;\n\t},\n) {\n\tlet payload: JWTPayload | undefined;\n\t// Locally verify\n\tif (opts.jwksUrl && !opts?.remoteVerify?.force) {\n\t\ttry {\n\t\t\tpayload = await verifyJwsAccessToken(token, {\n\t\t\t\tjwksFetch: opts.jwksUrl,\n\t\t\t\tverifyOptions: opts.verifyOptions,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tif (error.name === \"TypeError\" || error.name === \"JWSInvalid\") {\n\t\t\t\t\t// likely an opaque token (continue)\n\t\t\t\t} else if (error.name === \"JWTExpired\") {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: \"token expired\",\n\t\t\t\t\t});\n\t\t\t\t} else if (error.name === \"JWTInvalid\") {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: \"token invalid\",\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(error as unknown as string);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remote verify\n\tif (opts?.remoteVerify) {\n\t\tconst { data: introspect, error: introspectError } = await betterFetch<\n\t\t\tJWTPayload & {\n\t\t\t\tactive: boolean;\n\t\t\t}\n\t\t>(opts.remoteVerify.introspectUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tclient_id: opts.remoteVerify.clientId,\n\t\t\t\tclient_secret: opts.remoteVerify.clientSecret,\n\t\t\t\ttoken,\n\t\t\t\ttoken_type_hint: \"access_token\",\n\t\t\t}).toString(),\n\t\t});\n\t\tif (introspectError)\n\t\t\tlogger.error(\n\t\t\t\t`Introspection failed: ${introspectError.message ?? introspectError.statusText}`,\n\t\t\t);\n\t\tif (!introspect)\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\tmessage: \"introspection failed\",\n\t\t\t});\n\t\tif (!introspect.active)\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"token inactive\",\n\t\t\t});\n\t\t// Verifies payload using verify options (token valid through introspect)\n\t\ttry {\n\t\t\tconst unsecuredJwt = new UnsecuredJWT(introspect).encode();\n\t\t\tconst { audience: _audience, ...verifyOptions } = opts.verifyOptions;\n\t\t\tconst verify = introspect.aud\n\t\t\t\t? UnsecuredJWT.decode(unsecuredJwt, opts.verifyOptions)\n\t\t\t\t: UnsecuredJWT.decode(unsecuredJwt, verifyOptions);\n\t\t\tpayload = verify.payload;\n\t\t} catch (error) {\n\t\t\tthrow new Error(error as unknown as string);\n\t\t}\n\t}\n\n\tif (!payload)\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\tmessage: `no token payload`,\n\t\t});\n\n\t// Check scopes if provided\n\tif (opts.scopes) {\n\t\tconst validScopes = new Set(\n\t\t\t(payload.scope as string | undefined)?.split(\" \"),\n\t\t);\n\t\tfor (const sc of opts.scopes) {\n\t\t\tif (!validScopes.has(sc)) {\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: `invalid scope ${sc}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn payload;\n}\n"],"mappings":";;;;;;;AAiBA,IAAI;;;;;;AAsBJ,eAAsB,qBACrB,OACA,MAOC;AACD,KAAI;EAEH,MAAM,MAAM,MAAM,UACjB,OACA,kBAHY,MAAM,QAAQ,OAAO,KAAK,CAGf,EACvB,KAAK,cACL;AAGD,MAAI,IAAI,QAAQ,IACf,KAAI,QAAQ,YAAY,IAAI,QAAQ;AAErC,SAAO,IAAI;UACH,OAAO;AACf,MAAI,iBAAiB,MAAO,OAAM;AAClC,QAAM,IAAI,MAAM,MAA2B;;;AAI7C,eAAsB,QACrB,OACA,MAIC;CAED,IAAI;AACJ,KAAI;AACH,eAAa,sBAAsB,MAAM;UACjC,OAAO;AACf,MAAI,iBAAiB,MAAO,OAAM;AAClC,QAAM,IAAI,MAAM,MAA2B;;AAG5C,KAAI,CAAC,WAAW,IAAK,OAAM,IAAI,MAAM,kBAAkB;AAGvD,KAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,MAAM,QAAQ,IAAI,QAAQ,WAAW,IAAI,EAAE;AAClE,SACC,OAAO,KAAK,cAAc,WACvB,MAAM,YAA2B,KAAK,WAAW,EACjD,SAAS,EACR,QAAQ,oBACR,EACD,CAAC,CAAC,KAAK,OAAO,QAAQ;AACtB,OAAI,IAAI,MACP,OAAM,IAAI,MACT,gBAAgB,IAAI,MAAM,WAAW,IAAI,MAAM,aAC/C;AACF,UAAO,IAAI;IACV,GACD,MAAM,KAAK,WAAW;AAC1B,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,gBAAgB;;AAG5C,QAAO;;;;;;;AAQR,eAAsB,kBACrB,OACA,MAWC;CACD,IAAI;AAEJ,KAAI,KAAK,WAAW,CAAC,MAAM,cAAc,MACxC,KAAI;AACH,YAAU,MAAM,qBAAqB,OAAO;GAC3C,WAAW,KAAK;GAChB,eAAe,KAAK;GACpB,CAAC;UACM,OAAO;AACf,MAAI,iBAAiB,MACpB,KAAI,MAAM,SAAS,eAAe,MAAM,SAAS,cAAc,YAEpD,MAAM,SAAS,aACzB,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,iBACT,CAAC;WACQ,MAAM,SAAS,aACzB,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,iBACT,CAAC;MAEF,OAAM;MAGP,OAAM,IAAI,MAAM,MAA2B;;AAM9C,KAAI,MAAM,cAAc;EACvB,MAAM,EAAE,MAAM,YAAY,OAAO,oBAAoB,MAAM,YAIzD,KAAK,aAAa,eAAe;GAClC,QAAQ;GACR,SAAS;IACR,QAAQ;IACR,gBAAgB;IAChB;GACD,MAAM,IAAI,gBAAgB;IACzB,WAAW,KAAK,aAAa;IAC7B,eAAe,KAAK,aAAa;IACjC;IACA,iBAAiB;IACjB,CAAC,CAAC,UAAU;GACb,CAAC;AACF,MAAI,gBACH,QAAO,MACN,yBAAyB,gBAAgB,WAAW,gBAAgB,aACpE;AACF,MAAI,CAAC,WACJ,OAAM,IAAI,SAAS,yBAAyB,EAC3C,SAAS,wBACT,CAAC;AACH,MAAI,CAAC,WAAW,OACf,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,kBACT,CAAC;AAEH,MAAI;GACH,MAAM,eAAe,IAAI,aAAa,WAAW,CAAC,QAAQ;GAC1D,MAAM,EAAE,UAAU,WAAW,GAAG,kBAAkB,KAAK;AAIvD,cAHe,WAAW,MACvB,aAAa,OAAO,cAAc,KAAK,cAAc,GACrD,aAAa,OAAO,cAAc,cAAc,EAClC;WACT,OAAO;AACf,SAAM,IAAI,MAAM,MAA2B;;;AAI7C,KAAI,CAAC,QACJ,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,oBACT,CAAC;AAGH,KAAI,KAAK,QAAQ;EAChB,MAAM,cAAc,IAAI,IACtB,QAAQ,OAA8B,MAAM,IAAI,CACjD;AACD,OAAK,MAAM,MAAM,KAAK,OACrB,KAAI,CAAC,YAAY,IAAI,GAAG,CACvB,OAAM,IAAI,SAAS,aAAa,EAC/B,SAAS,iBAAiB,MAC1B,CAAC;;AAKL,QAAO"}
|
|
@@ -5,7 +5,6 @@ import { validateAuthorizationCode } from "../oauth2/validate-authorization-code
|
|
|
5
5
|
import "../oauth2/index.mjs";
|
|
6
6
|
import { betterFetch } from "@better-fetch/fetch";
|
|
7
7
|
import { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from "jose";
|
|
8
|
-
|
|
9
8
|
//#region src/social-providers/apple.ts
|
|
10
9
|
const apple = (options) => {
|
|
11
10
|
const tokenEndpoint = "https://appleid.apple.com/auth/token";
|
|
@@ -61,7 +60,7 @@ const apple = (options) => {
|
|
|
61
60
|
return refreshAccessToken({
|
|
62
61
|
refreshToken,
|
|
63
62
|
options,
|
|
64
|
-
tokenEndpoint
|
|
63
|
+
tokenEndpoint
|
|
65
64
|
});
|
|
66
65
|
},
|
|
67
66
|
async getUserInfo(token) {
|
|
@@ -99,7 +98,7 @@ const getApplePublicKey = async (kid) => {
|
|
|
99
98
|
if (!jwk) throw new Error(`JWK with kid ${kid} not found`);
|
|
100
99
|
return await importJWK(jwk, jwk.alg);
|
|
101
100
|
};
|
|
102
|
-
|
|
103
101
|
//#endregion
|
|
104
102
|
export { apple, getApplePublicKey };
|
|
103
|
+
|
|
105
104
|
//# sourceMappingURL=apple.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apple.mjs","names":[],"sources":["../../src/social-providers/apple.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\n\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport { APIError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\nexport interface AppleProfile {\n\t/**\n\t * The subject registered claim identifies the principal that’s the subject\n\t * of the identity token. Because this token is for your app, the value is\n\t * the unique identifier for the user.\n\t */\n\tsub: string;\n\t/**\n\t * A String value representing the user's email address.\n\t * The email address is either the user's real email address or the proxy\n\t * address, depending on their status private email relay service.\n\t */\n\temail: string;\n\t/**\n\t * A string or Boolean value that indicates whether the service verifies\n\t * the email. The value can either be a string (\"true\" or \"false\") or a\n\t * Boolean (true or false). The system may not verify email addresses for\n\t * Sign in with Apple at Work & School users, and this claim is \"false\" or\n\t * false for those users.\n\t */\n\temail_verified: true | \"true\";\n\t/**\n\t * A string or Boolean value that indicates whether the email that the user\n\t * shares is the proxy address. The value can either be a string (\"true\" or\n\t * \"false\") or a Boolean (true or false).\n\t */\n\tis_private_email: boolean;\n\t/**\n\t * An Integer value that indicates whether the user appears to be a real\n\t * person. Use the value of this claim to mitigate fraud. The possible\n\t * values are: 0 (or Unsupported), 1 (or Unknown), 2 (or LikelyReal). For\n\t * more information, see ASUserDetectionStatus. This claim is present only\n\t * in iOS 14 and later, macOS 11 and later, watchOS 7 and later, tvOS 14\n\t * and later. The claim isn’t present or supported for web-based apps.\n\t */\n\treal_user_status: number;\n\t/**\n\t * The user’s full name in the format provided during the authorization\n\t * process.\n\t */\n\tname: string;\n\t/**\n\t * The URL to the user's profile picture.\n\t */\n\tpicture: string;\n\tuser?: AppleNonConformUser | undefined;\n}\n\n/**\n * This is the shape of the `user` query parameter that Apple sends the first\n * time the user consents to the app.\n * @see https://developer.apple.com/documentation/signinwithapplerestapi/request-an-authorization-to-the-sign-in-with-apple-server./\n */\nexport interface AppleNonConformUser {\n\tname: {\n\t\tfirstName: string;\n\t\tlastName: string;\n\t};\n\temail: string;\n}\n\nexport interface AppleOptions extends ProviderOptions<AppleProfile> {\n\tclientId: string;\n\tappBundleIdentifier?: string | undefined;\n\taudience?: (string | string[]) | undefined;\n}\n\nexport const apple = (options: AppleOptions) => {\n\tconst tokenEndpoint = \"https://appleid.apple.com/auth/token\";\n\treturn {\n\t\tid: \"apple\",\n\t\tname: \"Apple\",\n\t\tasync createAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scope = options.disableDefaultScope ? [] : [\"email\", \"name\"];\n\t\t\tif (options.scope) _scope.push(...options.scope);\n\t\t\tif (scopes) _scope.push(...scopes);\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"apple\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://appleid.apple.com/auth/authorize\",\n\t\t\t\tscopes: _scope,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tresponseMode: \"form_post\",\n\t\t\t\tresponseType: \"code id_token\",\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst decodedHeader = decodeProtectedHeader(token);\n\t\t\t\tconst { kid, alg: jwtAlg } = decodedHeader;\n\t\t\t\tif (!kid || !jwtAlg) return false;\n\t\t\t\tconst publicKey = await getApplePublicKey(kid);\n\t\t\t\tconst { payload: jwtClaims } = await jwtVerify(token, publicKey, {\n\t\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\t\tissuer: \"https://appleid.apple.com\",\n\t\t\t\t\taudience:\n\t\t\t\t\t\toptions.audience && options.audience.length\n\t\t\t\t\t\t\t? options.audience\n\t\t\t\t\t\t\t: options.appBundleIdentifier\n\t\t\t\t\t\t\t\t? options.appBundleIdentifier\n\t\t\t\t\t\t\t\t: options.clientId,\n\t\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t\t});\n\t\t\t\t[\"email_verified\", \"is_private_email\"].forEach((field) => {\n\t\t\t\t\tif (jwtClaims[field] !== undefined) {\n\t\t\t\t\t\tjwtClaims[field] = Boolean(jwtClaims[field]);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (nonce && jwtClaims.nonce !== nonce) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn !!jwtClaims;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\ttokenEndpoint
|
|
1
|
+
{"version":3,"file":"apple.mjs","names":[],"sources":["../../src/social-providers/apple.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\n\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport { APIError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\nexport interface AppleProfile {\n\t/**\n\t * The subject registered claim identifies the principal that’s the subject\n\t * of the identity token. Because this token is for your app, the value is\n\t * the unique identifier for the user.\n\t */\n\tsub: string;\n\t/**\n\t * A String value representing the user's email address.\n\t * The email address is either the user's real email address or the proxy\n\t * address, depending on their status private email relay service.\n\t */\n\temail: string;\n\t/**\n\t * A string or Boolean value that indicates whether the service verifies\n\t * the email. The value can either be a string (\"true\" or \"false\") or a\n\t * Boolean (true or false). The system may not verify email addresses for\n\t * Sign in with Apple at Work & School users, and this claim is \"false\" or\n\t * false for those users.\n\t */\n\temail_verified: true | \"true\";\n\t/**\n\t * A string or Boolean value that indicates whether the email that the user\n\t * shares is the proxy address. The value can either be a string (\"true\" or\n\t * \"false\") or a Boolean (true or false).\n\t */\n\tis_private_email: boolean;\n\t/**\n\t * An Integer value that indicates whether the user appears to be a real\n\t * person. Use the value of this claim to mitigate fraud. The possible\n\t * values are: 0 (or Unsupported), 1 (or Unknown), 2 (or LikelyReal). For\n\t * more information, see ASUserDetectionStatus. This claim is present only\n\t * in iOS 14 and later, macOS 11 and later, watchOS 7 and later, tvOS 14\n\t * and later. The claim isn’t present or supported for web-based apps.\n\t */\n\treal_user_status: number;\n\t/**\n\t * The user’s full name in the format provided during the authorization\n\t * process.\n\t */\n\tname: string;\n\t/**\n\t * The URL to the user's profile picture.\n\t */\n\tpicture: string;\n\tuser?: AppleNonConformUser | undefined;\n}\n\n/**\n * This is the shape of the `user` query parameter that Apple sends the first\n * time the user consents to the app.\n * @see https://developer.apple.com/documentation/signinwithapplerestapi/request-an-authorization-to-the-sign-in-with-apple-server./\n */\nexport interface AppleNonConformUser {\n\tname: {\n\t\tfirstName: string;\n\t\tlastName: string;\n\t};\n\temail: string;\n}\n\nexport interface AppleOptions extends ProviderOptions<AppleProfile> {\n\tclientId: string;\n\tappBundleIdentifier?: string | undefined;\n\taudience?: (string | string[]) | undefined;\n}\n\nexport const apple = (options: AppleOptions) => {\n\tconst tokenEndpoint = \"https://appleid.apple.com/auth/token\";\n\treturn {\n\t\tid: \"apple\",\n\t\tname: \"Apple\",\n\t\tasync createAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scope = options.disableDefaultScope ? [] : [\"email\", \"name\"];\n\t\t\tif (options.scope) _scope.push(...options.scope);\n\t\t\tif (scopes) _scope.push(...scopes);\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"apple\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://appleid.apple.com/auth/authorize\",\n\t\t\t\tscopes: _scope,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tresponseMode: \"form_post\",\n\t\t\t\tresponseType: \"code id_token\",\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst decodedHeader = decodeProtectedHeader(token);\n\t\t\t\tconst { kid, alg: jwtAlg } = decodedHeader;\n\t\t\t\tif (!kid || !jwtAlg) return false;\n\t\t\t\tconst publicKey = await getApplePublicKey(kid);\n\t\t\t\tconst { payload: jwtClaims } = await jwtVerify(token, publicKey, {\n\t\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\t\tissuer: \"https://appleid.apple.com\",\n\t\t\t\t\taudience:\n\t\t\t\t\t\toptions.audience && options.audience.length\n\t\t\t\t\t\t\t? options.audience\n\t\t\t\t\t\t\t: options.appBundleIdentifier\n\t\t\t\t\t\t\t\t? options.appBundleIdentifier\n\t\t\t\t\t\t\t\t: options.clientId,\n\t\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t\t});\n\t\t\t\t[\"email_verified\", \"is_private_email\"].forEach((field) => {\n\t\t\t\t\tif (jwtClaims[field] !== undefined) {\n\t\t\t\t\t\tjwtClaims[field] = Boolean(jwtClaims[field]);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (nonce && jwtClaims.nonce !== nonce) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn !!jwtClaims;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst profile = decodeJwt<AppleProfile>(token.idToken);\n\t\t\tif (!profile) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// TODO: \"\" masking will be removed when the name field is made optional\n\t\t\tlet name: string;\n\t\t\tif (token.user?.name) {\n\t\t\t\tconst firstName = token.user.name.firstName || \"\";\n\t\t\t\tconst lastName = token.user.name.lastName || \"\";\n\t\t\t\tconst fullName = `${firstName} ${lastName}`.trim();\n\t\t\t\tname = fullName;\n\t\t\t} else {\n\t\t\t\tname = profile.name || \"\";\n\t\t\t}\n\n\t\t\tconst emailVerified =\n\t\t\t\ttypeof profile.email_verified === \"boolean\"\n\t\t\t\t\t? profile.email_verified\n\t\t\t\t\t: profile.email_verified === \"true\";\n\t\t\tconst enrichedProfile = {\n\t\t\t\t...profile,\n\t\t\t\tname,\n\t\t\t};\n\t\t\tconst userMap = await options.mapProfileToUser?.(enrichedProfile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: enrichedProfile.name,\n\t\t\t\t\temailVerified: emailVerified,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: enrichedProfile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<AppleProfile>;\n};\n\nexport const getApplePublicKey = async (kid: string) => {\n\tconst APPLE_BASE_URL = \"https://appleid.apple.com\";\n\tconst JWKS_APPLE_URI = \"/auth/keys\";\n\tconst { data } = await betterFetch<{\n\t\tkeys: Array<{\n\t\t\tkid: string;\n\t\t\talg: string;\n\t\t\tkty: string;\n\t\t\tuse: string;\n\t\t\tn: string;\n\t\t\te: string;\n\t\t}>;\n\t}>(`${APPLE_BASE_URL}${JWKS_APPLE_URI}`);\n\tif (!data?.keys) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Keys not found\",\n\t\t});\n\t}\n\tconst jwk = data.keys.find((key) => key.kid === kid);\n\tif (!jwk) {\n\t\tthrow new Error(`JWK with kid ${kid} not found`);\n\t}\n\treturn await importJWK(jwk, jwk.alg);\n};\n"],"mappings":";;;;;;;;AA6EA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GAC5D,MAAM,SAAS,QAAQ,sBAAsB,EAAE,GAAG,CAAC,SAAS,OAAO;AACnE,OAAI,QAAQ,MAAO,QAAO,KAAK,GAAG,QAAQ,MAAM;AAChD,OAAI,OAAQ,QAAO,KAAK,GAAG,OAAO;AAWlC,UAVY,MAAM,uBAAuB;IACxC,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA,cAAc;IACd,cAAc;IACd,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,MAAM,cAAc,OAAO,OAAO;AACjC,OAAI,QAAQ,qBACX,QAAO;AAER,OAAI,QAAQ,cACX,QAAO,QAAQ,cAAc,OAAO,MAAM;AAE3C,OAAI;IAEH,MAAM,EAAE,KAAK,KAAK,WADI,sBAAsB,MAAM;AAElD,QAAI,CAAC,OAAO,CAAC,OAAQ,QAAO;IAE5B,MAAM,EAAE,SAAS,cAAc,MAAM,UAAU,OAD7B,MAAM,kBAAkB,IAAI,EACmB;KAChE,YAAY,CAAC,OAAO;KACpB,QAAQ;KACR,UACC,QAAQ,YAAY,QAAQ,SAAS,SAClC,QAAQ,WACR,QAAQ,sBACP,QAAQ,sBACR,QAAQ;KACb,aAAa;KACb,CAAC;AACF,KAAC,kBAAkB,mBAAmB,CAAC,SAAS,UAAU;AACzD,SAAI,UAAU,WAAW,KAAA,EACxB,WAAU,SAAS,QAAQ,UAAU,OAAO;MAE5C;AACF,QAAI,SAAS,UAAU,UAAU,MAChC,QAAO;AAER,WAAO,CAAC,CAAC;WACF;AACP,WAAO;;;EAGT,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA;IACA;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAElC,OAAI,CAAC,MAAM,QACV,QAAO;GAER,MAAM,UAAU,UAAwB,MAAM,QAAQ;AACtD,OAAI,CAAC,QACJ,QAAO;GAIR,IAAI;AACJ,OAAI,MAAM,MAAM,KAIf,QADiB,GAFC,MAAM,KAAK,KAAK,aAAa,GAEjB,GADb,MAAM,KAAK,KAAK,YAAY,KACD,MAAM;OAGlD,QAAO,QAAQ,QAAQ;GAGxB,MAAM,gBACL,OAAO,QAAQ,mBAAmB,YAC/B,QAAQ,iBACR,QAAQ,mBAAmB;GAC/B,MAAM,kBAAkB;IACvB,GAAG;IACH;IACA;GACD,MAAM,UAAU,MAAM,QAAQ,mBAAmB,gBAAgB;AACjE,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,gBAAgB;KACP;KACf,OAAO,QAAQ;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA;;AAGF,MAAa,oBAAoB,OAAO,QAAgB;CAGvD,MAAM,EAAE,SAAS,MAAM,YASpB,sCAAqC;AACxC,KAAI,CAAC,MAAM,KACV,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,kBACT,CAAC;CAEH,MAAM,MAAM,KAAK,KAAK,MAAM,QAAQ,IAAI,QAAQ,IAAI;AACpD,KAAI,CAAC,IACJ,OAAM,IAAI,MAAM,gBAAgB,IAAI,YAAY;AAEjD,QAAO,MAAM,UAAU,KAAK,IAAI,IAAI"}
|
|
@@ -6,9 +6,9 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
|
6
6
|
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
7
7
|
import "../oauth2/index.mjs";
|
|
8
8
|
import { betterFetch } from "@better-fetch/fetch";
|
|
9
|
-
|
|
10
9
|
//#region src/social-providers/atlassian.ts
|
|
11
10
|
const atlassian = (options) => {
|
|
11
|
+
const tokenEndpoint = "https://auth.atlassian.com/oauth/token";
|
|
12
12
|
return {
|
|
13
13
|
id: "atlassian",
|
|
14
14
|
name: "Atlassian",
|
|
@@ -39,7 +39,7 @@ const atlassian = (options) => {
|
|
|
39
39
|
codeVerifier,
|
|
40
40
|
redirectURI,
|
|
41
41
|
options,
|
|
42
|
-
tokenEndpoint
|
|
42
|
+
tokenEndpoint
|
|
43
43
|
});
|
|
44
44
|
},
|
|
45
45
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -49,7 +49,7 @@ const atlassian = (options) => {
|
|
|
49
49
|
clientId: options.clientId,
|
|
50
50
|
clientSecret: options.clientSecret
|
|
51
51
|
},
|
|
52
|
-
tokenEndpoint
|
|
52
|
+
tokenEndpoint
|
|
53
53
|
});
|
|
54
54
|
},
|
|
55
55
|
async getUserInfo(token) {
|
|
@@ -78,7 +78,7 @@ const atlassian = (options) => {
|
|
|
78
78
|
options
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
|
-
|
|
82
81
|
//#endregion
|
|
83
82
|
export { atlassian };
|
|
83
|
+
|
|
84
84
|
//# sourceMappingURL=atlassian.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atlassian.mjs","names":[],"sources":["../../src/social-providers/atlassian.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface AtlassianProfile {\n\taccount_type?: string | undefined;\n\taccount_id: string;\n\temail?: string | undefined;\n\tname: string;\n\tpicture?: string | undefined;\n\tnickname?: string | undefined;\n\tlocale?: string | undefined;\n\textended_profile?:\n\t\t| {\n\t\t\t\tjob_title?: string;\n\t\t\t\torganization?: string;\n\t\t\t\tdepartment?: string;\n\t\t\t\tlocation?: string;\n\t\t }\n\t\t| undefined;\n}\nexport interface AtlassianOptions extends ProviderOptions<AtlassianProfile> {\n\tclientId: string;\n}\n\nexport const atlassian = (options: AtlassianOptions) => {\n\treturn {\n\t\tid: \"atlassian\",\n\t\tname: \"Atlassian\",\n\n\t\tasync createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\"Client Id and Secret are required for Atlassian\");\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Atlassian\");\n\t\t\t}\n\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"read:jira-user\", \"offline_access\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"atlassian\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://auth.atlassian.com/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tadditionalParams: {\n\t\t\t\t\taudience: \"api.atlassian.com\",\n\t\t\t\t},\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t},\n\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint
|
|
1
|
+
{"version":3,"file":"atlassian.mjs","names":[],"sources":["../../src/social-providers/atlassian.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface AtlassianProfile {\n\taccount_type?: string | undefined;\n\taccount_id: string;\n\temail?: string | undefined;\n\tname: string;\n\tpicture?: string | undefined;\n\tnickname?: string | undefined;\n\tlocale?: string | undefined;\n\textended_profile?:\n\t\t| {\n\t\t\t\tjob_title?: string;\n\t\t\t\torganization?: string;\n\t\t\t\tdepartment?: string;\n\t\t\t\tlocation?: string;\n\t\t }\n\t\t| undefined;\n}\nexport interface AtlassianOptions extends ProviderOptions<AtlassianProfile> {\n\tclientId: string;\n}\n\nexport const atlassian = (options: AtlassianOptions) => {\n\tconst tokenEndpoint = \"https://auth.atlassian.com/oauth/token\";\n\treturn {\n\t\tid: \"atlassian\",\n\t\tname: \"Atlassian\",\n\n\t\tasync createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\"Client Id and Secret are required for Atlassian\");\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Atlassian\");\n\t\t\t}\n\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"read:jira-user\", \"offline_access\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"atlassian\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://auth.atlassian.com/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tadditionalParams: {\n\t\t\t\t\taudience: \"api.atlassian.com\",\n\t\t\t\t},\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t},\n\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\tif (!token.accessToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { data: profile } = await betterFetch<{\n\t\t\t\t\taccount_id: string;\n\t\t\t\t\tname: string;\n\t\t\t\t\temail?: string | undefined;\n\t\t\t\t\tpicture?: string | undefined;\n\t\t\t\t}>(\"https://api.atlassian.com/me\", {\n\t\t\t\t\theaders: { Authorization: `Bearer ${token.accessToken}` },\n\t\t\t\t});\n\n\t\t\t\tif (!profile) return null;\n\n\t\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\n\t\t\t\treturn {\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: profile.account_id,\n\t\t\t\t\t\tname: profile.name,\n\t\t\t\t\t\temail: profile.email,\n\t\t\t\t\t\timage: profile.picture,\n\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t\t...userMap,\n\t\t\t\t\t},\n\t\t\t\t\tdata: profile,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to fetch user info from Figma:\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\n\t\toptions,\n\t} satisfies OAuthProvider<AtlassianProfile>;\n};\n"],"mappings":";;;;;;;;;AA+BA,MAAa,aAAa,YAA8B;CACvD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EAEN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;AAC1E,OAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,cAAc;AAC/C,WAAO,MAAM,kDAAkD;AAC/D,UAAM,IAAI,gBAAgB,gCAAgC;;AAE3D,OAAI,CAAC,aACJ,OAAM,IAAI,gBAAgB,yCAAyC;GAGpE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF,CAAC,kBAAkB,iBAAiB;AACvC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAEnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,kBAAkB,EACjB,UAAU,qBACV;IACD,QAAQ,QAAQ;IAChB,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAGH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAGL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAGlC,OAAI,CAAC,MAAM,YACV,QAAO;AAGR,OAAI;IACH,MAAM,EAAE,MAAM,YAAY,MAAM,YAK7B,gCAAgC,EAClC,SAAS,EAAE,eAAe,UAAU,MAAM,eAAe,EACzD,CAAC;AAEF,QAAI,CAAC,QAAS,QAAO;IAErB,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAEzD,WAAO;KACN,MAAM;MACL,IAAI,QAAQ;MACZ,MAAM,QAAQ;MACd,OAAO,QAAQ;MACf,OAAO,QAAQ;MACf,eAAe;MACf,GAAG;MACH;KACD,MAAM;KACN;YACO,OAAO;AACf,WAAO,MAAM,yCAAyC,MAAM;AAC5D,WAAO;;;EAIT;EACA"}
|
|
@@ -7,7 +7,6 @@ import { validateAuthorizationCode } from "../oauth2/validate-authorization-code
|
|
|
7
7
|
import "../oauth2/index.mjs";
|
|
8
8
|
import { betterFetch } from "@better-fetch/fetch";
|
|
9
9
|
import { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from "jose";
|
|
10
|
-
|
|
11
10
|
//#region src/social-providers/cognito.ts
|
|
12
11
|
const cognito = (options) => {
|
|
13
12
|
if (!options.domain || !options.region || !options.userPoolId) {
|
|
@@ -160,7 +159,7 @@ const getCognitoPublicKey = async (kid, region, userPoolId) => {
|
|
|
160
159
|
throw error;
|
|
161
160
|
}
|
|
162
161
|
};
|
|
163
|
-
|
|
164
162
|
//#endregion
|
|
165
163
|
export { cognito, getCognitoPublicKey };
|
|
164
|
+
|
|
166
165
|
//# sourceMappingURL=cognito.mjs.map
|