@depup/better-auth__core 1.6.23-depup.2
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/LICENSE.md +20 -0
- package/README.md +32 -0
- package/changes.json +14 -0
- package/dist/api/index.d.mts +281 -0
- package/dist/api/index.mjs +92 -0
- package/dist/async_hooks/index.d.mts +6 -0
- package/dist/async_hooks/index.mjs +20 -0
- package/dist/async_hooks/pure.index.d.mts +6 -0
- package/dist/async_hooks/pure.index.mjs +33 -0
- package/dist/context/endpoint-context.d.mts +18 -0
- package/dist/context/endpoint-context.mjs +29 -0
- package/dist/context/global.d.mts +6 -0
- package/dist/context/global.mjs +36 -0
- package/dist/context/index.d.mts +5 -0
- package/dist/context/index.mjs +5 -0
- package/dist/context/request-state.d.mts +27 -0
- package/dist/context/request-state.mjs +47 -0
- package/dist/context/transaction.d.mts +27 -0
- package/dist/context/transaction.mjs +96 -0
- package/dist/db/adapter/factory.d.mts +17 -0
- package/dist/db/adapter/factory.mjs +905 -0
- package/dist/db/adapter/get-default-field-name.d.mts +18 -0
- package/dist/db/adapter/get-default-field-name.mjs +36 -0
- package/dist/db/adapter/get-default-model-name.d.mts +12 -0
- package/dist/db/adapter/get-default-model-name.mjs +30 -0
- package/dist/db/adapter/get-field-attributes.d.mts +26 -0
- package/dist/db/adapter/get-field-attributes.mjs +37 -0
- package/dist/db/adapter/get-field-name.d.mts +18 -0
- package/dist/db/adapter/get-field-name.mjs +31 -0
- package/dist/db/adapter/get-id-field.d.mts +36 -0
- package/dist/db/adapter/get-id-field.mjs +64 -0
- package/dist/db/adapter/get-model-name.d.mts +12 -0
- package/dist/db/adapter/get-model-name.mjs +21 -0
- package/dist/db/adapter/index.d.mts +615 -0
- package/dist/db/adapter/index.mjs +24 -0
- package/dist/db/adapter/types.d.mts +105 -0
- package/dist/db/adapter/utils.d.mts +7 -0
- package/dist/db/adapter/utils.mjs +37 -0
- package/dist/db/get-tables.d.mts +6 -0
- package/dist/db/get-tables.mjs +266 -0
- package/dist/db/index.d.mts +10 -0
- package/dist/db/index.mjs +8 -0
- package/dist/db/plugin.d.mts +12 -0
- package/dist/db/schema/account.d.mts +28 -0
- package/dist/db/schema/account.mjs +17 -0
- package/dist/db/schema/rate-limit.d.mts +18 -0
- package/dist/db/schema/rate-limit.mjs +9 -0
- package/dist/db/schema/session.d.mts +23 -0
- package/dist/db/schema/session.mjs +12 -0
- package/dist/db/schema/shared.d.mts +10 -0
- package/dist/db/schema/shared.mjs +9 -0
- package/dist/db/schema/user.d.mts +22 -0
- package/dist/db/schema/user.mjs +11 -0
- package/dist/db/schema/verification.d.mts +21 -0
- package/dist/db/schema/verification.mjs +10 -0
- package/dist/db/type.d.mts +194 -0
- package/dist/env/color-depth.d.mts +4 -0
- package/dist/env/color-depth.mjs +86 -0
- package/dist/env/env-impl.d.mts +32 -0
- package/dist/env/env-impl.mjs +81 -0
- package/dist/env/index.d.mts +4 -0
- package/dist/env/index.mjs +4 -0
- package/dist/env/logger.d.mts +48 -0
- package/dist/env/logger.mjs +79 -0
- package/dist/error/codes.d.mts +69 -0
- package/dist/error/codes.mjs +55 -0
- package/dist/error/index.d.mts +26 -0
- package/dist/error/index.mjs +27 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.mjs +1 -0
- package/dist/instrumentation/api.mjs +12 -0
- package/dist/instrumentation/attributes.d.mts +11 -0
- package/dist/instrumentation/attributes.mjs +10 -0
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.mjs +3 -0
- package/dist/instrumentation/noop.mjs +42 -0
- package/dist/instrumentation/pure.index.d.mts +7 -0
- package/dist/instrumentation/pure.index.mjs +7 -0
- package/dist/instrumentation/tracer.d.mts +13 -0
- package/dist/instrumentation/tracer.mjs +53 -0
- package/dist/oauth2/client-credentials-token.d.mts +56 -0
- package/dist/oauth2/client-credentials-token.mjs +64 -0
- package/dist/oauth2/create-authorization-url.d.mts +44 -0
- package/dist/oauth2/create-authorization-url.mjs +41 -0
- package/dist/oauth2/index.d.mts +8 -0
- package/dist/oauth2/index.mjs +7 -0
- package/dist/oauth2/oauth-provider.d.mts +192 -0
- package/dist/oauth2/refresh-access-token.d.mts +54 -0
- package/dist/oauth2/refresh-access-token.mjs +73 -0
- package/dist/oauth2/reject-redirects.mjs +60 -0
- package/dist/oauth2/utils.d.mts +24 -0
- package/dist/oauth2/utils.mjs +48 -0
- package/dist/oauth2/validate-authorization-code.d.mts +85 -0
- package/dist/oauth2/validate-authorization-code.mjs +86 -0
- package/dist/oauth2/verify.d.mts +65 -0
- package/dist/oauth2/verify.mjs +202 -0
- package/dist/social-providers/apple.d.mts +133 -0
- package/dist/social-providers/apple.mjs +117 -0
- package/dist/social-providers/atlassian.d.mts +70 -0
- package/dist/social-providers/atlassian.mjs +80 -0
- package/dist/social-providers/cognito.d.mts +85 -0
- package/dist/social-providers/cognito.mjs +162 -0
- package/dist/social-providers/discord.d.mts +124 -0
- package/dist/social-providers/discord.mjs +62 -0
- package/dist/social-providers/dropbox.d.mts +69 -0
- package/dist/social-providers/dropbox.mjs +72 -0
- package/dist/social-providers/facebook.d.mts +79 -0
- package/dist/social-providers/facebook.mjs +157 -0
- package/dist/social-providers/figma.d.mts +61 -0
- package/dist/social-providers/figma.mjs +83 -0
- package/dist/social-providers/github.d.mts +102 -0
- package/dist/social-providers/github.mjs +92 -0
- package/dist/social-providers/gitlab.d.mts +123 -0
- package/dist/social-providers/gitlab.mjs +79 -0
- package/dist/social-providers/google.d.mts +123 -0
- package/dist/social-providers/google.mjs +137 -0
- package/dist/social-providers/huggingface.d.mts +83 -0
- package/dist/social-providers/huggingface.mjs +73 -0
- package/dist/social-providers/index.d.mts +1834 -0
- package/dist/social-providers/index.mjs +78 -0
- package/dist/social-providers/kakao.d.mts +161 -0
- package/dist/social-providers/kakao.mjs +70 -0
- package/dist/social-providers/kick.d.mts +73 -0
- package/dist/social-providers/kick.mjs +68 -0
- package/dist/social-providers/line.d.mts +105 -0
- package/dist/social-providers/line.mjs +110 -0
- package/dist/social-providers/linear.d.mts +68 -0
- package/dist/social-providers/linear.mjs +85 -0
- package/dist/social-providers/linkedin.d.mts +67 -0
- package/dist/social-providers/linkedin.mjs +73 -0
- package/dist/social-providers/microsoft-entra-id.d.mts +174 -0
- package/dist/social-providers/microsoft-entra-id.mjs +152 -0
- package/dist/social-providers/naver.d.mts +92 -0
- package/dist/social-providers/naver.mjs +65 -0
- package/dist/social-providers/notion.d.mts +64 -0
- package/dist/social-providers/notion.mjs +72 -0
- package/dist/social-providers/paybin.d.mts +71 -0
- package/dist/social-providers/paybin.mjs +81 -0
- package/dist/social-providers/paypal.d.mts +131 -0
- package/dist/social-providers/paypal.mjs +188 -0
- package/dist/social-providers/polar.d.mts +74 -0
- package/dist/social-providers/polar.mjs +71 -0
- package/dist/social-providers/railway.d.mts +65 -0
- package/dist/social-providers/railway.mjs +74 -0
- package/dist/social-providers/reddit.d.mts +62 -0
- package/dist/social-providers/reddit.mjs +81 -0
- package/dist/social-providers/roblox.d.mts +70 -0
- package/dist/social-providers/roblox.mjs +57 -0
- package/dist/social-providers/salesforce.d.mts +79 -0
- package/dist/social-providers/salesforce.mjs +87 -0
- package/dist/social-providers/slack.d.mts +83 -0
- package/dist/social-providers/slack.mjs +66 -0
- package/dist/social-providers/spotify.d.mts +63 -0
- package/dist/social-providers/spotify.mjs +69 -0
- package/dist/social-providers/tiktok.d.mts +168 -0
- package/dist/social-providers/tiktok.mjs +60 -0
- package/dist/social-providers/twitch.d.mts +79 -0
- package/dist/social-providers/twitch.mjs +75 -0
- package/dist/social-providers/twitter.d.mts +126 -0
- package/dist/social-providers/twitter.mjs +85 -0
- package/dist/social-providers/vercel.d.mts +62 -0
- package/dist/social-providers/vercel.mjs +58 -0
- package/dist/social-providers/vk.d.mts +70 -0
- package/dist/social-providers/vk.mjs +81 -0
- package/dist/social-providers/wechat.d.mts +113 -0
- package/dist/social-providers/wechat.mjs +81 -0
- package/dist/social-providers/zoom.d.mts +163 -0
- package/dist/social-providers/zoom.mjs +69 -0
- package/dist/types/context.d.mts +319 -0
- package/dist/types/cookie.d.mts +15 -0
- package/dist/types/helper.d.mts +10 -0
- package/dist/types/index.d.mts +9 -0
- package/dist/types/init-options.d.mts +1430 -0
- package/dist/types/plugin-client.d.mts +123 -0
- package/dist/types/plugin.d.mts +124 -0
- package/dist/types/secret.d.mts +11 -0
- package/dist/utils/async.d.mts +22 -0
- package/dist/utils/async.mjs +32 -0
- package/dist/utils/db.d.mts +9 -0
- package/dist/utils/db.mjs +15 -0
- package/dist/utils/deprecate.d.mts +9 -0
- package/dist/utils/deprecate.mjs +16 -0
- package/dist/utils/error-codes.d.mts +13 -0
- package/dist/utils/error-codes.mjs +10 -0
- package/dist/utils/fetch-metadata.d.mts +4 -0
- package/dist/utils/fetch-metadata.mjs +6 -0
- package/dist/utils/host.d.mts +147 -0
- package/dist/utils/host.mjs +295 -0
- package/dist/utils/id.d.mts +4 -0
- package/dist/utils/id.mjs +7 -0
- package/dist/utils/ip.d.mts +77 -0
- package/dist/utils/ip.mjs +230 -0
- package/dist/utils/is-api-error.d.mts +6 -0
- package/dist/utils/is-api-error.mjs +8 -0
- package/dist/utils/json.d.mts +4 -0
- package/dist/utils/json.mjs +41 -0
- package/dist/utils/redirect-uri.d.mts +20 -0
- package/dist/utils/redirect-uri.mjs +48 -0
- package/dist/utils/string.d.mts +8 -0
- package/dist/utils/string.mjs +25 -0
- package/dist/utils/url.d.mts +37 -0
- package/dist/utils/url.mjs +61 -0
- package/package.json +216 -0
- package/src/api/index.ts +185 -0
- package/src/async_hooks/index.ts +40 -0
- package/src/async_hooks/pure.index.ts +46 -0
- package/src/context/endpoint-context.ts +50 -0
- package/src/context/global.ts +57 -0
- package/src/context/index.ts +23 -0
- package/src/context/request-state.ts +91 -0
- package/src/context/transaction.ts +169 -0
- package/src/db/adapter/factory.ts +1740 -0
- package/src/db/adapter/get-default-field-name.ts +59 -0
- package/src/db/adapter/get-default-model-name.ts +51 -0
- package/src/db/adapter/get-field-attributes.ts +62 -0
- package/src/db/adapter/get-field-name.ts +43 -0
- package/src/db/adapter/get-id-field.ts +150 -0
- package/src/db/adapter/get-model-name.ts +36 -0
- package/src/db/adapter/index.ts +656 -0
- package/src/db/adapter/types.ts +134 -0
- package/src/db/adapter/utils.ts +61 -0
- package/src/db/get-tables.ts +304 -0
- package/src/db/index.ts +43 -0
- package/src/db/plugin.ts +11 -0
- package/src/db/schema/account.ts +47 -0
- package/src/db/schema/rate-limit.ts +36 -0
- package/src/db/schema/session.ts +29 -0
- package/src/db/schema/shared.ts +7 -0
- package/src/db/schema/user.ts +31 -0
- package/src/db/schema/verification.ts +28 -0
- package/src/db/type.ts +360 -0
- package/src/env/color-depth.ts +172 -0
- package/src/env/env-impl.ts +123 -0
- package/src/env/index.ts +23 -0
- package/src/env/logger.ts +145 -0
- package/src/error/codes.ts +72 -0
- package/src/error/index.ts +44 -0
- package/src/index.ts +1 -0
- package/src/instrumentation/api.ts +17 -0
- package/src/instrumentation/attributes.ts +22 -0
- package/src/instrumentation/index.ts +2 -0
- package/src/instrumentation/noop.ts +74 -0
- package/src/instrumentation/pure.index.ts +31 -0
- package/src/instrumentation/tracer.ts +95 -0
- package/src/oauth2/client-credentials-token.ts +126 -0
- package/src/oauth2/create-authorization-url.ts +89 -0
- package/src/oauth2/index.ts +34 -0
- package/src/oauth2/oauth-provider.ts +222 -0
- package/src/oauth2/refresh-access-token.ts +157 -0
- package/src/oauth2/reject-redirects.ts +70 -0
- package/src/oauth2/utils.ts +70 -0
- package/src/oauth2/validate-authorization-code.ts +190 -0
- package/src/oauth2/verify.ts +408 -0
- package/src/social-providers/apple.ts +249 -0
- package/src/social-providers/atlassian.ts +133 -0
- package/src/social-providers/cognito.ts +281 -0
- package/src/social-providers/discord.ts +170 -0
- package/src/social-providers/dropbox.ts +112 -0
- package/src/social-providers/facebook.ts +288 -0
- package/src/social-providers/figma.ts +118 -0
- package/src/social-providers/github.ts +184 -0
- package/src/social-providers/gitlab.ts +155 -0
- package/src/social-providers/google.ts +263 -0
- package/src/social-providers/huggingface.ts +119 -0
- package/src/social-providers/index.ts +132 -0
- package/src/social-providers/kakao.ts +179 -0
- package/src/social-providers/kick.ts +109 -0
- package/src/social-providers/line.ts +169 -0
- package/src/social-providers/linear.ts +121 -0
- package/src/social-providers/linkedin.ts +110 -0
- package/src/social-providers/microsoft-entra-id.ts +391 -0
- package/src/social-providers/naver.ts +113 -0
- package/src/social-providers/notion.ts +108 -0
- package/src/social-providers/paybin.ts +118 -0
- package/src/social-providers/paypal.ts +371 -0
- package/src/social-providers/polar.ts +111 -0
- package/src/social-providers/railway.ts +100 -0
- package/src/social-providers/reddit.ts +126 -0
- package/src/social-providers/roblox.ts +112 -0
- package/src/social-providers/salesforce.ts +159 -0
- package/src/social-providers/slack.ts +112 -0
- package/src/social-providers/spotify.ts +94 -0
- package/src/social-providers/tiktok.ts +211 -0
- package/src/social-providers/twitch.ts +112 -0
- package/src/social-providers/twitter.ts +199 -0
- package/src/social-providers/vercel.ts +87 -0
- package/src/social-providers/vk.ts +125 -0
- package/src/social-providers/wechat.ts +220 -0
- package/src/social-providers/zoom.ts +230 -0
- package/src/types/context.ts +460 -0
- package/src/types/cookie.ts +10 -0
- package/src/types/helper.ts +27 -0
- package/src/types/index.ts +40 -0
- package/src/types/init-options.ts +1679 -0
- package/src/types/plugin-client.ts +143 -0
- package/src/types/plugin.ts +163 -0
- package/src/types/secret.ts +8 -0
- package/src/utils/async.ts +53 -0
- package/src/utils/db.ts +20 -0
- package/src/utils/deprecate.ts +21 -0
- package/src/utils/error-codes.ts +68 -0
- package/src/utils/fetch-metadata.ts +3 -0
- package/src/utils/host.ts +416 -0
- package/src/utils/id.ts +5 -0
- package/src/utils/ip.ts +395 -0
- package/src/utils/is-api-error.ts +10 -0
- package/src/utils/json.ts +56 -0
- package/src/utils/redirect-uri.ts +54 -0
- package/src/utils/string.ts +40 -0
- package/src/utils/url.ts +77 -0
package/src/env/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { getColorDepth } from "./color-depth";
|
|
2
|
+
export {
|
|
3
|
+
ENV,
|
|
4
|
+
type EnvObject,
|
|
5
|
+
env,
|
|
6
|
+
getBooleanEnvVar,
|
|
7
|
+
getEnvVar,
|
|
8
|
+
isDevelopment,
|
|
9
|
+
isProduction,
|
|
10
|
+
isTest,
|
|
11
|
+
nodeENV,
|
|
12
|
+
} from "./env-impl";
|
|
13
|
+
export {
|
|
14
|
+
createLogger,
|
|
15
|
+
type InternalLogger,
|
|
16
|
+
type Logger,
|
|
17
|
+
type LogHandlerParams,
|
|
18
|
+
type LogLevel,
|
|
19
|
+
levels,
|
|
20
|
+
logger,
|
|
21
|
+
shouldPublishLog,
|
|
22
|
+
TTY_COLORS,
|
|
23
|
+
} from "./logger";
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { getColorDepth } from "./color-depth";
|
|
2
|
+
|
|
3
|
+
export const TTY_COLORS = {
|
|
4
|
+
reset: "\x1b[0m",
|
|
5
|
+
bright: "\x1b[1m",
|
|
6
|
+
dim: "\x1b[2m",
|
|
7
|
+
undim: "\x1b[22m",
|
|
8
|
+
underscore: "\x1b[4m",
|
|
9
|
+
blink: "\x1b[5m",
|
|
10
|
+
reverse: "\x1b[7m",
|
|
11
|
+
hidden: "\x1b[8m",
|
|
12
|
+
fg: {
|
|
13
|
+
black: "\x1b[30m",
|
|
14
|
+
red: "\x1b[31m",
|
|
15
|
+
green: "\x1b[32m",
|
|
16
|
+
yellow: "\x1b[33m",
|
|
17
|
+
blue: "\x1b[34m",
|
|
18
|
+
magenta: "\x1b[35m",
|
|
19
|
+
cyan: "\x1b[36m",
|
|
20
|
+
white: "\x1b[37m",
|
|
21
|
+
},
|
|
22
|
+
bg: {
|
|
23
|
+
black: "\x1b[40m",
|
|
24
|
+
red: "\x1b[41m",
|
|
25
|
+
green: "\x1b[42m",
|
|
26
|
+
yellow: "\x1b[43m",
|
|
27
|
+
blue: "\x1b[44m",
|
|
28
|
+
magenta: "\x1b[45m",
|
|
29
|
+
cyan: "\x1b[46m",
|
|
30
|
+
white: "\x1b[47m",
|
|
31
|
+
},
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
export type LogLevel = "debug" | "info" | "success" | "warn" | "error";
|
|
35
|
+
|
|
36
|
+
export const levels = ["debug", "info", "success", "warn", "error"] as const;
|
|
37
|
+
|
|
38
|
+
export function shouldPublishLog(
|
|
39
|
+
currentLogLevel: LogLevel,
|
|
40
|
+
logLevel: LogLevel,
|
|
41
|
+
): boolean {
|
|
42
|
+
return levels.indexOf(logLevel) >= levels.indexOf(currentLogLevel);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface Logger {
|
|
46
|
+
disabled?: boolean | undefined;
|
|
47
|
+
disableColors?: boolean | undefined;
|
|
48
|
+
level?: Exclude<LogLevel, "success"> | undefined;
|
|
49
|
+
log?:
|
|
50
|
+
| ((
|
|
51
|
+
level: Exclude<LogLevel, "success">,
|
|
52
|
+
message: string,
|
|
53
|
+
...args: any[]
|
|
54
|
+
) => void)
|
|
55
|
+
| undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type LogHandlerParams =
|
|
59
|
+
Parameters<NonNullable<Logger["log"]>> extends [LogLevel, ...infer Rest]
|
|
60
|
+
? Rest
|
|
61
|
+
: never;
|
|
62
|
+
|
|
63
|
+
const levelColors: Record<LogLevel, string> = {
|
|
64
|
+
info: TTY_COLORS.fg.blue,
|
|
65
|
+
success: TTY_COLORS.fg.green,
|
|
66
|
+
warn: TTY_COLORS.fg.yellow,
|
|
67
|
+
error: TTY_COLORS.fg.red,
|
|
68
|
+
debug: TTY_COLORS.fg.magenta,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const formatMessage = (
|
|
72
|
+
level: LogLevel,
|
|
73
|
+
message: string,
|
|
74
|
+
colorsEnabled: boolean,
|
|
75
|
+
): string => {
|
|
76
|
+
const timestamp = new Date().toISOString();
|
|
77
|
+
|
|
78
|
+
if (colorsEnabled) {
|
|
79
|
+
return `${TTY_COLORS.dim}${timestamp}${TTY_COLORS.reset} ${
|
|
80
|
+
levelColors[level]
|
|
81
|
+
}${level.toUpperCase()}${TTY_COLORS.reset} ${TTY_COLORS.bright}[Better Auth]:${
|
|
82
|
+
TTY_COLORS.reset
|
|
83
|
+
} ${message}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return `${timestamp} ${level.toUpperCase()} [Better Auth]: ${message}`;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export type InternalLogger = {
|
|
90
|
+
[K in LogLevel]: (...params: LogHandlerParams) => void;
|
|
91
|
+
} & {
|
|
92
|
+
get level(): LogLevel;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const createLogger = (options?: Logger | undefined): InternalLogger => {
|
|
96
|
+
const enabled = options?.disabled !== true;
|
|
97
|
+
const logLevel = options?.level ?? "warn";
|
|
98
|
+
|
|
99
|
+
const isDisableColorsSpecified = options?.disableColors !== undefined;
|
|
100
|
+
const colorsEnabled = isDisableColorsSpecified
|
|
101
|
+
? !options.disableColors
|
|
102
|
+
: getColorDepth() !== 1;
|
|
103
|
+
|
|
104
|
+
const LogFunc = (
|
|
105
|
+
level: LogLevel,
|
|
106
|
+
message: string,
|
|
107
|
+
args: any[] = [],
|
|
108
|
+
): void => {
|
|
109
|
+
if (!enabled || !shouldPublishLog(logLevel, level)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const formattedMessage = formatMessage(level, message, colorsEnabled);
|
|
114
|
+
|
|
115
|
+
if (!options || typeof options.log !== "function") {
|
|
116
|
+
if (level === "error") {
|
|
117
|
+
console.error(formattedMessage, ...args);
|
|
118
|
+
} else if (level === "warn") {
|
|
119
|
+
console.warn(formattedMessage, ...args);
|
|
120
|
+
} else {
|
|
121
|
+
console.log(formattedMessage, ...args);
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
options.log(level === "success" ? "info" : level, message, ...args);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const logger = Object.fromEntries(
|
|
130
|
+
levels.map((level) => [
|
|
131
|
+
level,
|
|
132
|
+
(...[message, ...args]: LogHandlerParams) =>
|
|
133
|
+
LogFunc(level, message, args),
|
|
134
|
+
]),
|
|
135
|
+
) as Record<LogLevel, (...params: LogHandlerParams) => void>;
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
...logger,
|
|
139
|
+
get level() {
|
|
140
|
+
return logLevel;
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export const logger = createLogger();
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { defineErrorCodes } from "../utils/error-codes";
|
|
2
|
+
|
|
3
|
+
declare module "@better-auth/core" {
|
|
4
|
+
interface BetterAuthPluginRegistry<AuthOptions, Options> {
|
|
5
|
+
/**
|
|
6
|
+
* This plugin does not exist, do not use it in runtime.
|
|
7
|
+
*/
|
|
8
|
+
"$internal:base": {
|
|
9
|
+
creator: () => {
|
|
10
|
+
$ERROR_CODES: typeof BASE_ERROR_CODES;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const BASE_ERROR_CODES = defineErrorCodes({
|
|
17
|
+
USER_NOT_FOUND: "User not found",
|
|
18
|
+
FAILED_TO_CREATE_USER: "Failed to create user",
|
|
19
|
+
FAILED_TO_CREATE_SESSION: "Failed to create session",
|
|
20
|
+
FAILED_TO_UPDATE_USER: "Failed to update user",
|
|
21
|
+
FAILED_TO_GET_SESSION: "Failed to get session",
|
|
22
|
+
INVALID_PASSWORD: "Invalid password",
|
|
23
|
+
INVALID_EMAIL: "Invalid email",
|
|
24
|
+
INVALID_EMAIL_OR_PASSWORD: "Invalid email or password",
|
|
25
|
+
INVALID_USER: "Invalid user",
|
|
26
|
+
SOCIAL_ACCOUNT_ALREADY_LINKED: "Social account already linked",
|
|
27
|
+
PROVIDER_NOT_FOUND: "Provider not found",
|
|
28
|
+
INVALID_TOKEN: "Invalid token",
|
|
29
|
+
TOKEN_EXPIRED: "Token expired",
|
|
30
|
+
ID_TOKEN_NOT_SUPPORTED: "id_token not supported",
|
|
31
|
+
FAILED_TO_GET_USER_INFO: "Failed to get user info",
|
|
32
|
+
USER_EMAIL_NOT_FOUND: "User email not found",
|
|
33
|
+
EMAIL_NOT_VERIFIED: "Email not verified",
|
|
34
|
+
PASSWORD_TOO_SHORT: "Password too short",
|
|
35
|
+
PASSWORD_TOO_LONG: "Password too long",
|
|
36
|
+
USER_ALREADY_EXISTS: "User already exists.",
|
|
37
|
+
USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL:
|
|
38
|
+
"User already exists. Use another email.",
|
|
39
|
+
EMAIL_CAN_NOT_BE_UPDATED: "Email can not be updated",
|
|
40
|
+
CHANGE_EMAIL_DISABLED: "Change email is disabled",
|
|
41
|
+
CREDENTIAL_ACCOUNT_NOT_FOUND: "Credential account not found",
|
|
42
|
+
SESSION_EXPIRED: "Session expired. Re-authenticate to perform this action.",
|
|
43
|
+
FAILED_TO_UNLINK_LAST_ACCOUNT: "You can't unlink your last account",
|
|
44
|
+
ACCOUNT_NOT_FOUND: "Account not found",
|
|
45
|
+
USER_ALREADY_HAS_PASSWORD:
|
|
46
|
+
"User already has a password. Provide that to delete the account.",
|
|
47
|
+
CROSS_SITE_NAVIGATION_LOGIN_BLOCKED:
|
|
48
|
+
"Cross-site navigation login blocked. This request appears to be a CSRF attack.",
|
|
49
|
+
VERIFICATION_EMAIL_NOT_ENABLED: "Verification email isn't enabled",
|
|
50
|
+
EMAIL_ALREADY_VERIFIED: "Email is already verified",
|
|
51
|
+
EMAIL_MISMATCH: "Email mismatch",
|
|
52
|
+
SESSION_NOT_FRESH: "Session is not fresh",
|
|
53
|
+
LINKED_ACCOUNT_ALREADY_EXISTS: "Linked account already exists",
|
|
54
|
+
INVALID_ORIGIN: "Invalid origin",
|
|
55
|
+
INVALID_CALLBACK_URL: "Invalid callbackURL",
|
|
56
|
+
INVALID_REDIRECT_URL: "Invalid redirectURL",
|
|
57
|
+
INVALID_ERROR_CALLBACK_URL: "Invalid errorCallbackURL",
|
|
58
|
+
INVALID_NEW_USER_CALLBACK_URL: "Invalid newUserCallbackURL",
|
|
59
|
+
MISSING_OR_NULL_ORIGIN: "Missing or null Origin",
|
|
60
|
+
CALLBACK_URL_REQUIRED: "callbackURL is required",
|
|
61
|
+
FAILED_TO_CREATE_VERIFICATION: "Unable to create verification",
|
|
62
|
+
FIELD_NOT_ALLOWED: "Field not allowed to be set",
|
|
63
|
+
ASYNC_VALIDATION_NOT_SUPPORTED: "Async validation is not supported",
|
|
64
|
+
VALIDATION_ERROR: "Validation Error",
|
|
65
|
+
MISSING_FIELD: "Field is required",
|
|
66
|
+
METHOD_NOT_ALLOWED_DEFER_SESSION_REQUIRED:
|
|
67
|
+
"POST method requires deferSessionRefresh to be enabled in session config",
|
|
68
|
+
BODY_MUST_BE_AN_OBJECT: "Body must be an object",
|
|
69
|
+
PASSWORD_ALREADY_SET: "User already has a password set",
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export type APIErrorCode = keyof typeof BASE_ERROR_CODES;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { APIError as BaseAPIError } from "better-call/error";
|
|
2
|
+
|
|
3
|
+
export class BetterAuthError extends Error {
|
|
4
|
+
constructor(message: string, options?: { cause?: unknown | undefined }) {
|
|
5
|
+
super(message, options);
|
|
6
|
+
this.name = "BetterAuthError";
|
|
7
|
+
this.message = message;
|
|
8
|
+
this.stack = "";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { type APIErrorCode, BASE_ERROR_CODES } from "./codes";
|
|
13
|
+
|
|
14
|
+
type BaseAPIErrorInstance = InstanceType<typeof BaseAPIError>;
|
|
15
|
+
|
|
16
|
+
export class APIError extends BaseAPIError {
|
|
17
|
+
declare status: BaseAPIErrorInstance["status"];
|
|
18
|
+
declare body: BaseAPIErrorInstance["body"];
|
|
19
|
+
declare headers: BaseAPIErrorInstance["headers"];
|
|
20
|
+
declare statusCode: BaseAPIErrorInstance["statusCode"];
|
|
21
|
+
declare message: string;
|
|
22
|
+
declare errorStack: BaseAPIErrorInstance["errorStack"];
|
|
23
|
+
|
|
24
|
+
constructor(...args: ConstructorParameters<typeof BaseAPIError>) {
|
|
25
|
+
super(...args);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static fromStatus(
|
|
29
|
+
status: ConstructorParameters<typeof BaseAPIError>[0],
|
|
30
|
+
body?: ConstructorParameters<typeof BaseAPIError>[1],
|
|
31
|
+
) {
|
|
32
|
+
return new APIError(status, body);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static from(
|
|
36
|
+
status: ConstructorParameters<typeof BaseAPIError>[0],
|
|
37
|
+
error: { code: string; message: string },
|
|
38
|
+
) {
|
|
39
|
+
return new APIError(status, {
|
|
40
|
+
message: error.message,
|
|
41
|
+
code: error.code,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./types";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { OpenTelemetryAPI } from "./noop";
|
|
2
|
+
import { noopOpenTelemetryAPI } from "./noop";
|
|
3
|
+
|
|
4
|
+
let openTelemetryAPIPromise: Promise<void> | undefined;
|
|
5
|
+
let openTelemetryAPI: OpenTelemetryAPI | undefined;
|
|
6
|
+
|
|
7
|
+
export function getOpenTelemetryAPI(): OpenTelemetryAPI {
|
|
8
|
+
if (!openTelemetryAPIPromise) {
|
|
9
|
+
openTelemetryAPIPromise = import("@opentelemetry/api")
|
|
10
|
+
.then((mod) => {
|
|
11
|
+
openTelemetryAPI = mod;
|
|
12
|
+
})
|
|
13
|
+
.catch(() => /* ignore failures */ undefined);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return openTelemetryAPI ?? noopOpenTelemetryAPI;
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ATTR_DB_COLLECTION_NAME,
|
|
3
|
+
ATTR_DB_OPERATION_NAME,
|
|
4
|
+
ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
5
|
+
ATTR_HTTP_ROUTE,
|
|
6
|
+
} from "@opentelemetry/semantic-conventions";
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
ATTR_DB_COLLECTION_NAME,
|
|
10
|
+
ATTR_DB_OPERATION_NAME,
|
|
11
|
+
ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
12
|
+
ATTR_HTTP_ROUTE,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Operation identifier (e.g. getSession, signUpWithEmailAndPassword). Uses endpoint operationId when set, otherwise the endpoint key. */
|
|
16
|
+
export const ATTR_OPERATION_ID = "better_auth.operation_id" as const;
|
|
17
|
+
|
|
18
|
+
/** Hook type (e.g. before, after, create.before). */
|
|
19
|
+
export const ATTR_HOOK_TYPE = "better_auth.hook.type" as const;
|
|
20
|
+
|
|
21
|
+
/** Execution context (e.g. user, plugin:id). */
|
|
22
|
+
export const ATTR_CONTEXT = "better_auth.context" as const;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Span, Tracer } from "@opentelemetry/api";
|
|
2
|
+
|
|
3
|
+
export type OpenTelemetryAPI = Pick<
|
|
4
|
+
typeof import("@opentelemetry/api"),
|
|
5
|
+
"trace" | "SpanStatusCode"
|
|
6
|
+
>;
|
|
7
|
+
|
|
8
|
+
function createNoopSpan(): Span {
|
|
9
|
+
const span = {
|
|
10
|
+
end(): void {},
|
|
11
|
+
setAttribute(_key: string, _value: unknown): void {},
|
|
12
|
+
setStatus(_status: unknown): void {},
|
|
13
|
+
recordException(_exception: unknown): void {},
|
|
14
|
+
updateName(_name: string) {
|
|
15
|
+
return span;
|
|
16
|
+
},
|
|
17
|
+
} as unknown as Span;
|
|
18
|
+
return span;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function createNoopTracer(noopSpan: Span): Tracer {
|
|
22
|
+
// OpenTelemetry `Tracer.startActiveSpan` has three overloads:
|
|
23
|
+
// (name, fn)
|
|
24
|
+
// (name, options, fn)
|
|
25
|
+
// (name, options, context, fn)
|
|
26
|
+
// The callback is always the last argument; fish it out by arity so a
|
|
27
|
+
// 2-arg call (options omitted) doesn't try to invoke `undefined`.
|
|
28
|
+
function startActiveSpan<F extends (span: Span) => unknown>(
|
|
29
|
+
_name: string,
|
|
30
|
+
fn: F,
|
|
31
|
+
): ReturnType<F>;
|
|
32
|
+
function startActiveSpan<F extends (span: Span) => unknown>(
|
|
33
|
+
_name: string,
|
|
34
|
+
_options: { attributes?: Record<string, string | number | boolean> },
|
|
35
|
+
fn: F,
|
|
36
|
+
): ReturnType<F>;
|
|
37
|
+
function startActiveSpan<F extends (span: Span) => unknown>(
|
|
38
|
+
_name: string,
|
|
39
|
+
_options: { attributes?: Record<string, string | number | boolean> },
|
|
40
|
+
_context: unknown,
|
|
41
|
+
fn: F,
|
|
42
|
+
): ReturnType<F>;
|
|
43
|
+
function startActiveSpan(_name: string, ...rest: Array<unknown>): unknown {
|
|
44
|
+
const fn = rest[rest.length - 1] as (span: Span) => unknown;
|
|
45
|
+
return fn(noopSpan);
|
|
46
|
+
}
|
|
47
|
+
return { startActiveSpan } as Tracer;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function createNoopTraceAPI() {
|
|
51
|
+
const noopTracer = createNoopTracer(createNoopSpan());
|
|
52
|
+
return {
|
|
53
|
+
getTracer(_name?: string, _version?: string) {
|
|
54
|
+
return noopTracer;
|
|
55
|
+
},
|
|
56
|
+
getActiveSpan(): Span | undefined {
|
|
57
|
+
return undefined;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function createNoopOpenTelemetryAPI(): OpenTelemetryAPI {
|
|
63
|
+
return {
|
|
64
|
+
SpanStatusCode: {
|
|
65
|
+
UNSET: 0,
|
|
66
|
+
OK: 1,
|
|
67
|
+
ERROR: 2,
|
|
68
|
+
},
|
|
69
|
+
trace: createNoopTraceAPI(),
|
|
70
|
+
} as OpenTelemetryAPI;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const noopOpenTelemetryAPI: OpenTelemetryAPI =
|
|
74
|
+
createNoopOpenTelemetryAPI();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Noop variant of `./instrumentation` for runtimes where the dynamic
|
|
3
|
+
* `import("@opentelemetry/api")` in `./api` throws synchronously instead of
|
|
4
|
+
* rejecting its returned promise. Convex's V8 isolate is the reproducer: bare
|
|
5
|
+
* specifiers are rejected at resolve time in `get-convex/convex-backend`
|
|
6
|
+
* `crates/isolate/src/request_scope.rs`, so the `.catch()` in
|
|
7
|
+
* `getOpenTelemetryAPI` never runs and every `withSpan` call surfaces an
|
|
8
|
+
* uncaught error.
|
|
9
|
+
*
|
|
10
|
+
* Public surface must stay identical to `./index` (enforced by `pure.test.ts`).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export * from "./attributes";
|
|
14
|
+
|
|
15
|
+
export function withSpan<T>(
|
|
16
|
+
name: string,
|
|
17
|
+
attributes: Record<string, string | number | boolean>,
|
|
18
|
+
fn: () => T,
|
|
19
|
+
): T;
|
|
20
|
+
export function withSpan<T>(
|
|
21
|
+
name: string,
|
|
22
|
+
attributes: Record<string, string | number | boolean>,
|
|
23
|
+
fn: () => Promise<T>,
|
|
24
|
+
): Promise<T>;
|
|
25
|
+
export function withSpan<T>(
|
|
26
|
+
_name: string,
|
|
27
|
+
_attributes: Record<string, string | number | boolean>,
|
|
28
|
+
fn: () => T | Promise<T>,
|
|
29
|
+
): T | Promise<T> {
|
|
30
|
+
return fn();
|
|
31
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Span } from "@opentelemetry/api";
|
|
2
|
+
import { getOpenTelemetryAPI } from "./api";
|
|
3
|
+
import { ATTR_HTTP_RESPONSE_STATUS_CODE } from "./attributes";
|
|
4
|
+
|
|
5
|
+
const INSTRUMENTATION_SCOPE = "better-auth";
|
|
6
|
+
const INSTRUMENTATION_VERSION = import.meta.env?.BETTER_AUTH_VERSION ?? "1.0.0";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Better-auth uses `throw ctx.redirect(url)` for flow control (e.g. OAuth
|
|
10
|
+
* callbacks). These are APIErrors with 3xx status codes and should not be
|
|
11
|
+
* recorded as span errors.
|
|
12
|
+
*/
|
|
13
|
+
function isRedirectError(err: unknown): boolean {
|
|
14
|
+
if (
|
|
15
|
+
err != null &&
|
|
16
|
+
typeof err === "object" &&
|
|
17
|
+
"name" in err &&
|
|
18
|
+
(err as { name: string }).name === "APIError" &&
|
|
19
|
+
"statusCode" in err
|
|
20
|
+
) {
|
|
21
|
+
const status = (err as { statusCode: number }).statusCode;
|
|
22
|
+
return status >= 300 && status < 400;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function endSpanWithError(span: Span, err: unknown) {
|
|
28
|
+
const { SpanStatusCode } = getOpenTelemetryAPI();
|
|
29
|
+
if (isRedirectError(err)) {
|
|
30
|
+
span.setAttribute(
|
|
31
|
+
ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
32
|
+
(err as { statusCode: number }).statusCode,
|
|
33
|
+
);
|
|
34
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
35
|
+
} else {
|
|
36
|
+
span.recordException(err as Error);
|
|
37
|
+
span.setStatus({
|
|
38
|
+
code: SpanStatusCode.ERROR,
|
|
39
|
+
message: String((err as Error)?.message ?? err),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
span.end();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a child span whose lifetime is bound to the execution of the given function
|
|
47
|
+
*
|
|
48
|
+
* @param name - The name of the span.
|
|
49
|
+
* @param attributes - The attributes of the span.
|
|
50
|
+
* @param fn - The function to execute within the span.
|
|
51
|
+
* @returns The result of the function.
|
|
52
|
+
*/
|
|
53
|
+
export function withSpan<T>(
|
|
54
|
+
name: string,
|
|
55
|
+
attributes: Record<string, string | number | boolean>,
|
|
56
|
+
fn: () => T,
|
|
57
|
+
): T;
|
|
58
|
+
export function withSpan<T>(
|
|
59
|
+
name: string,
|
|
60
|
+
attributes: Record<string, string | number | boolean>,
|
|
61
|
+
fn: () => Promise<T>,
|
|
62
|
+
): Promise<T>;
|
|
63
|
+
export function withSpan<T>(
|
|
64
|
+
name: string,
|
|
65
|
+
attributes: Record<string, string | number | boolean>,
|
|
66
|
+
fn: () => T | Promise<T>,
|
|
67
|
+
): T | Promise<T> {
|
|
68
|
+
const { trace } = getOpenTelemetryAPI();
|
|
69
|
+
const tracer = trace.getTracer(
|
|
70
|
+
INSTRUMENTATION_SCOPE,
|
|
71
|
+
INSTRUMENTATION_VERSION,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return tracer.startActiveSpan(name, { attributes }, (span) => {
|
|
75
|
+
try {
|
|
76
|
+
const result = fn();
|
|
77
|
+
if (result instanceof Promise) {
|
|
78
|
+
return result
|
|
79
|
+
.then((value) => {
|
|
80
|
+
span.end();
|
|
81
|
+
return value;
|
|
82
|
+
})
|
|
83
|
+
.catch((err) => {
|
|
84
|
+
endSpanWithError(span, err);
|
|
85
|
+
throw err;
|
|
86
|
+
}) as Promise<T>;
|
|
87
|
+
}
|
|
88
|
+
span.end();
|
|
89
|
+
return result;
|
|
90
|
+
} catch (err) {
|
|
91
|
+
endSpanWithError(span, err);
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { base64Url } from "@better-auth/utils/base64";
|
|
2
|
+
import type { AwaitableFunction } from "../types";
|
|
3
|
+
import type { OAuth2Tokens, ProviderOptions } from "./oauth-provider";
|
|
4
|
+
import { fetchRefusingRedirects } from "./reject-redirects";
|
|
5
|
+
|
|
6
|
+
export async function clientCredentialsTokenRequest({
|
|
7
|
+
options,
|
|
8
|
+
scope,
|
|
9
|
+
authentication,
|
|
10
|
+
resource,
|
|
11
|
+
}: {
|
|
12
|
+
options: AwaitableFunction<ProviderOptions & { clientSecret: string }>;
|
|
13
|
+
scope?: string | undefined;
|
|
14
|
+
authentication?: ("basic" | "post") | undefined;
|
|
15
|
+
resource?: (string | string[]) | undefined;
|
|
16
|
+
}) {
|
|
17
|
+
options = typeof options === "function" ? await options() : options;
|
|
18
|
+
return createClientCredentialsTokenRequest({
|
|
19
|
+
options,
|
|
20
|
+
scope,
|
|
21
|
+
authentication,
|
|
22
|
+
resource,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated use async'd clientCredentialsTokenRequest instead
|
|
28
|
+
*/
|
|
29
|
+
export function createClientCredentialsTokenRequest({
|
|
30
|
+
options,
|
|
31
|
+
scope,
|
|
32
|
+
authentication,
|
|
33
|
+
resource,
|
|
34
|
+
}: {
|
|
35
|
+
options: ProviderOptions & { clientSecret: string };
|
|
36
|
+
scope?: string | undefined;
|
|
37
|
+
authentication?: ("basic" | "post") | undefined;
|
|
38
|
+
resource?: (string | string[]) | undefined;
|
|
39
|
+
}) {
|
|
40
|
+
const body = new URLSearchParams();
|
|
41
|
+
const headers: Record<string, any> = {
|
|
42
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
43
|
+
accept: "application/json",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
body.set("grant_type", "client_credentials");
|
|
47
|
+
scope && body.set("scope", scope);
|
|
48
|
+
if (resource) {
|
|
49
|
+
if (typeof resource === "string") {
|
|
50
|
+
body.append("resource", resource);
|
|
51
|
+
} else {
|
|
52
|
+
for (const _resource of resource) {
|
|
53
|
+
body.append("resource", _resource);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (authentication === "basic") {
|
|
58
|
+
const primaryClientId = Array.isArray(options.clientId)
|
|
59
|
+
? options.clientId[0]
|
|
60
|
+
: options.clientId;
|
|
61
|
+
const encodedCredentials = base64Url.encode(
|
|
62
|
+
`${primaryClientId}:${options.clientSecret}`,
|
|
63
|
+
);
|
|
64
|
+
headers["authorization"] = `Basic ${encodedCredentials}`;
|
|
65
|
+
} else {
|
|
66
|
+
const primaryClientId = Array.isArray(options.clientId)
|
|
67
|
+
? options.clientId[0]
|
|
68
|
+
: options.clientId;
|
|
69
|
+
body.set("client_id", primaryClientId);
|
|
70
|
+
body.set("client_secret", options.clientSecret);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
body,
|
|
75
|
+
headers,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function clientCredentialsToken({
|
|
80
|
+
options,
|
|
81
|
+
tokenEndpoint,
|
|
82
|
+
scope,
|
|
83
|
+
authentication,
|
|
84
|
+
resource,
|
|
85
|
+
}: {
|
|
86
|
+
options: AwaitableFunction<ProviderOptions & { clientSecret: string }>;
|
|
87
|
+
tokenEndpoint: string;
|
|
88
|
+
scope: string;
|
|
89
|
+
authentication?: ("basic" | "post") | undefined;
|
|
90
|
+
resource?: (string | string[]) | undefined;
|
|
91
|
+
}): Promise<OAuth2Tokens> {
|
|
92
|
+
const { body, headers } = await clientCredentialsTokenRequest({
|
|
93
|
+
options,
|
|
94
|
+
scope,
|
|
95
|
+
authentication,
|
|
96
|
+
resource,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const { data, error } = await fetchRefusingRedirects<{
|
|
100
|
+
access_token: string;
|
|
101
|
+
expires_in?: number | undefined;
|
|
102
|
+
token_type?: string | undefined;
|
|
103
|
+
scope?: string | undefined;
|
|
104
|
+
}>(tokenEndpoint, {
|
|
105
|
+
method: "POST",
|
|
106
|
+
body,
|
|
107
|
+
headers,
|
|
108
|
+
});
|
|
109
|
+
if (error) {
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
const tokens: OAuth2Tokens = {
|
|
113
|
+
accessToken: data.access_token,
|
|
114
|
+
tokenType: data.token_type,
|
|
115
|
+
scopes: data.scope?.split(" "),
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
if (data.expires_in) {
|
|
119
|
+
const now = new Date();
|
|
120
|
+
tokens.accessTokenExpiresAt = new Date(
|
|
121
|
+
now.getTime() + data.expires_in * 1000,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return tokens;
|
|
126
|
+
}
|