@better-auth/core 1.5.0-beta.9 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/api/index.d.mts +144 -41
- package/dist/api/index.mjs +2 -1
- package/dist/api/index.mjs.map +1 -0
- package/dist/async_hooks/index.d.mts +2 -1
- package/dist/async_hooks/index.mjs +2 -1
- package/dist/async_hooks/index.mjs.map +1 -0
- package/dist/async_hooks/pure.index.d.mts +2 -1
- package/dist/async_hooks/pure.index.mjs +2 -1
- package/dist/async_hooks/pure.index.mjs.map +1 -0
- package/dist/context/endpoint-context.d.mts +2 -1
- package/dist/context/endpoint-context.mjs +4 -3
- package/dist/context/endpoint-context.mjs.map +1 -0
- package/dist/context/global.d.mts +2 -2
- package/dist/context/global.mjs +3 -2
- package/dist/context/global.mjs.map +1 -0
- package/dist/context/request-state.d.mts +2 -1
- package/dist/context/request-state.mjs +4 -3
- package/dist/context/request-state.mjs.map +1 -0
- package/dist/context/transaction.d.mts +2 -1
- package/dist/context/transaction.mjs +4 -3
- package/dist/context/transaction.mjs.map +1 -0
- package/dist/db/adapter/factory.d.mts +6 -13
- package/dist/db/adapter/factory.mjs +44 -57
- package/dist/db/adapter/factory.mjs.map +1 -0
- package/dist/db/adapter/get-default-field-name.d.mts +2 -1
- package/dist/db/adapter/get-default-field-name.mjs +3 -2
- package/dist/db/adapter/get-default-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-default-model-name.d.mts +2 -1
- package/dist/db/adapter/get-default-model-name.mjs +5 -4
- package/dist/db/adapter/get-default-model-name.mjs.map +1 -0
- package/dist/db/adapter/get-field-attributes.d.mts +3 -2
- package/dist/db/adapter/get-field-attributes.mjs +2 -1
- package/dist/db/adapter/get-field-attributes.mjs.map +1 -0
- package/dist/db/adapter/get-field-name.d.mts +2 -1
- package/dist/db/adapter/get-field-name.mjs +2 -1
- package/dist/db/adapter/get-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-id-field.d.mts +3 -2
- package/dist/db/adapter/get-id-field.mjs +3 -2
- package/dist/db/adapter/get-id-field.mjs.map +1 -0
- package/dist/db/adapter/get-model-name.d.mts +2 -1
- package/dist/db/adapter/get-model-name.mjs +2 -1
- package/dist/db/adapter/get-model-name.mjs.map +1 -0
- package/dist/db/adapter/index.d.mts +10 -4
- package/dist/db/adapter/index.mjs +19 -2
- package/dist/db/adapter/index.mjs.map +1 -0
- package/dist/db/adapter/types.d.mts +3 -34
- package/dist/db/adapter/utils.d.mts +2 -1
- package/dist/db/adapter/utils.mjs +2 -1
- package/dist/db/adapter/utils.mjs.map +1 -0
- package/dist/db/get-tables.d.mts +2 -1
- package/dist/db/get-tables.mjs +46 -39
- package/dist/db/get-tables.mjs.map +1 -0
- package/dist/db/index.d.mts +7 -7
- package/dist/db/plugin.d.mts +2 -1
- package/dist/db/schema/account.d.mts +8 -4
- package/dist/db/schema/account.mjs +2 -1
- package/dist/db/schema/account.mjs.map +1 -0
- package/dist/db/schema/rate-limit.d.mts +8 -2
- package/dist/db/schema/rate-limit.mjs +2 -1
- package/dist/db/schema/rate-limit.mjs.map +1 -0
- package/dist/db/schema/session.d.mts +8 -4
- package/dist/db/schema/session.mjs +2 -1
- package/dist/db/schema/session.mjs.map +1 -0
- package/dist/db/schema/shared.d.mts +2 -1
- package/dist/db/schema/shared.mjs +2 -1
- package/dist/db/schema/shared.mjs.map +1 -0
- package/dist/db/schema/user.d.mts +8 -4
- package/dist/db/schema/user.mjs +2 -1
- package/dist/db/schema/user.mjs.map +1 -0
- package/dist/db/schema/verification.d.mts +8 -4
- package/dist/db/schema/verification.mjs +2 -1
- package/dist/db/schema/verification.mjs.map +1 -0
- package/dist/db/type.d.mts +28 -2
- package/dist/env/color-depth.d.mts +2 -1
- package/dist/env/color-depth.mjs +2 -1
- package/dist/env/color-depth.mjs.map +1 -0
- package/dist/env/env-impl.d.mts +3 -2
- package/dist/env/env-impl.mjs +9 -8
- package/dist/env/env-impl.mjs.map +1 -0
- package/dist/env/logger.d.mts +2 -1
- package/dist/env/logger.mjs +3 -2
- package/dist/env/logger.mjs.map +1 -0
- package/dist/error/codes.d.mts +64 -181
- package/dist/error/codes.mjs +6 -2
- package/dist/error/codes.mjs.map +1 -0
- package/dist/error/index.d.mts +2 -1
- package/dist/error/index.mjs +2 -1
- package/dist/error/index.mjs.map +1 -0
- package/dist/index.d.mts +5 -4
- package/dist/oauth2/client-credentials-token.d.mts +25 -3
- package/dist/oauth2/client-credentials-token.mjs +15 -2
- package/dist/oauth2/client-credentials-token.mjs.map +1 -0
- package/dist/oauth2/create-authorization-url.d.mts +5 -2
- package/dist/oauth2/create-authorization-url.mjs +3 -1
- package/dist/oauth2/create-authorization-url.mjs.map +1 -0
- package/dist/oauth2/index.d.mts +4 -4
- package/dist/oauth2/index.mjs +4 -4
- package/dist/oauth2/oauth-provider.d.mts +3 -2
- package/dist/oauth2/refresh-access-token.d.mts +24 -4
- package/dist/oauth2/refresh-access-token.mjs +20 -2
- package/dist/oauth2/refresh-access-token.mjs.map +1 -0
- package/dist/oauth2/utils.d.mts +2 -1
- package/dist/oauth2/utils.mjs +2 -1
- package/dist/oauth2/utils.mjs.map +1 -0
- package/dist/oauth2/validate-authorization-code.d.mts +37 -4
- package/dist/oauth2/validate-authorization-code.mjs +25 -13
- package/dist/oauth2/validate-authorization-code.mjs.map +1 -0
- package/dist/oauth2/verify.d.mts +7 -13
- package/dist/oauth2/verify.mjs +2 -1
- package/dist/oauth2/verify.mjs.map +1 -0
- package/dist/social-providers/apple.d.mts +2 -1
- package/dist/social-providers/apple.mjs +22 -21
- package/dist/social-providers/apple.mjs.map +1 -0
- package/dist/social-providers/atlassian.d.mts +2 -1
- package/dist/social-providers/atlassian.mjs +2 -1
- package/dist/social-providers/atlassian.mjs.map +1 -0
- package/dist/social-providers/cognito.d.mts +2 -1
- package/dist/social-providers/cognito.mjs +4 -3
- package/dist/social-providers/cognito.mjs.map +1 -0
- package/dist/social-providers/discord.d.mts +2 -1
- package/dist/social-providers/discord.mjs +2 -1
- package/dist/social-providers/discord.mjs.map +1 -0
- package/dist/social-providers/dropbox.d.mts +2 -1
- package/dist/social-providers/dropbox.mjs +2 -1
- package/dist/social-providers/dropbox.mjs.map +1 -0
- package/dist/social-providers/facebook.d.mts +2 -1
- package/dist/social-providers/facebook.mjs +13 -12
- package/dist/social-providers/facebook.mjs.map +1 -0
- package/dist/social-providers/figma.d.mts +2 -1
- package/dist/social-providers/figma.mjs +2 -1
- package/dist/social-providers/figma.mjs.map +1 -0
- package/dist/social-providers/github.d.mts +3 -2
- package/dist/social-providers/github.mjs +23 -6
- package/dist/social-providers/github.mjs.map +1 -0
- package/dist/social-providers/gitlab.d.mts +2 -1
- package/dist/social-providers/gitlab.mjs +3 -2
- package/dist/social-providers/gitlab.mjs.map +1 -0
- package/dist/social-providers/google.d.mts +2 -1
- package/dist/social-providers/google.mjs +18 -13
- package/dist/social-providers/google.mjs.map +1 -0
- package/dist/social-providers/huggingface.d.mts +2 -1
- package/dist/social-providers/huggingface.mjs +3 -2
- package/dist/social-providers/huggingface.mjs.map +1 -0
- package/dist/social-providers/index.d.mts +61 -8
- package/dist/social-providers/index.mjs +5 -2
- package/dist/social-providers/index.mjs.map +1 -0
- package/dist/social-providers/kakao.d.mts +3 -2
- package/dist/social-providers/kakao.mjs +3 -2
- package/dist/social-providers/kakao.mjs.map +1 -0
- package/dist/social-providers/kick.d.mts +2 -1
- package/dist/social-providers/kick.mjs +2 -1
- package/dist/social-providers/kick.mjs.map +1 -0
- package/dist/social-providers/line.d.mts +2 -1
- package/dist/social-providers/line.mjs +3 -2
- package/dist/social-providers/line.mjs.map +1 -0
- package/dist/social-providers/linear.d.mts +2 -1
- package/dist/social-providers/linear.mjs +2 -1
- package/dist/social-providers/linear.mjs.map +1 -0
- package/dist/social-providers/linkedin.d.mts +2 -1
- package/dist/social-providers/linkedin.mjs +2 -1
- package/dist/social-providers/linkedin.mjs.map +1 -0
- package/dist/social-providers/microsoft-entra-id.d.mts +4 -1
- package/dist/social-providers/microsoft-entra-id.mjs +36 -2
- package/dist/social-providers/microsoft-entra-id.mjs.map +1 -0
- package/dist/social-providers/naver.d.mts +11 -20
- package/dist/social-providers/naver.mjs +3 -2
- package/dist/social-providers/naver.mjs.map +1 -0
- package/dist/social-providers/notion.d.mts +2 -1
- package/dist/social-providers/notion.mjs +3 -2
- package/dist/social-providers/notion.mjs.map +1 -0
- package/dist/social-providers/paybin.d.mts +2 -1
- package/dist/social-providers/paybin.mjs +3 -2
- package/dist/social-providers/paybin.mjs.map +1 -0
- package/dist/social-providers/paypal.d.mts +2 -1
- package/dist/social-providers/paypal.mjs +2 -1
- package/dist/social-providers/paypal.mjs.map +1 -0
- package/dist/social-providers/polar.d.mts +2 -1
- package/dist/social-providers/polar.mjs +3 -2
- package/dist/social-providers/polar.mjs.map +1 -0
- package/dist/social-providers/railway.d.mts +68 -0
- package/dist/social-providers/railway.mjs +78 -0
- package/dist/social-providers/railway.mjs.map +1 -0
- package/dist/social-providers/reddit.d.mts +2 -1
- package/dist/social-providers/reddit.mjs +2 -1
- package/dist/social-providers/reddit.mjs.map +1 -0
- package/dist/social-providers/roblox.d.mts +2 -1
- package/dist/social-providers/roblox.mjs +2 -1
- package/dist/social-providers/roblox.mjs.map +1 -0
- package/dist/social-providers/salesforce.d.mts +2 -1
- package/dist/social-providers/salesforce.mjs +2 -1
- package/dist/social-providers/salesforce.mjs.map +1 -0
- package/dist/social-providers/slack.d.mts +2 -1
- package/dist/social-providers/slack.mjs +2 -1
- package/dist/social-providers/slack.mjs.map +1 -0
- package/dist/social-providers/spotify.d.mts +2 -1
- package/dist/social-providers/spotify.mjs +2 -1
- package/dist/social-providers/spotify.mjs.map +1 -0
- package/dist/social-providers/tiktok.d.mts +3 -3
- package/dist/social-providers/tiktok.mjs +3 -2
- package/dist/social-providers/tiktok.mjs.map +1 -0
- package/dist/social-providers/twitch.d.mts +2 -1
- package/dist/social-providers/twitch.mjs +2 -1
- package/dist/social-providers/twitch.mjs.map +1 -0
- package/dist/social-providers/twitter.d.mts +14 -25
- package/dist/social-providers/twitter.mjs +2 -1
- package/dist/social-providers/twitter.mjs.map +1 -0
- package/dist/social-providers/vercel.d.mts +2 -1
- package/dist/social-providers/vercel.mjs +3 -2
- package/dist/social-providers/vercel.mjs.map +1 -0
- package/dist/social-providers/vk.d.mts +2 -1
- package/dist/social-providers/vk.mjs +2 -1
- package/dist/social-providers/vk.mjs.map +1 -0
- package/dist/social-providers/zoom.d.mts +3 -10
- package/dist/social-providers/zoom.mjs +2 -1
- package/dist/social-providers/zoom.mjs.map +1 -0
- package/dist/types/context.d.mts +53 -21
- package/dist/types/cookie.d.mts +2 -1
- package/dist/types/helper.d.mts +4 -1
- package/dist/types/index.d.mts +4 -3
- package/dist/types/init-options.d.mts +231 -159
- package/dist/types/plugin-client.d.mts +4 -1
- package/dist/types/plugin.d.mts +12 -11
- package/dist/types/secret.d.mts +12 -0
- package/dist/utils/db.d.mts +12 -0
- package/dist/utils/db.mjs +17 -0
- package/dist/utils/db.mjs.map +1 -0
- package/dist/utils/deprecate.d.mts +2 -2
- package/dist/utils/deprecate.mjs +2 -1
- package/dist/utils/deprecate.mjs.map +1 -0
- package/dist/utils/error-codes.d.mts +8 -6
- package/dist/utils/error-codes.mjs +3 -2
- package/dist/utils/error-codes.mjs.map +1 -0
- package/dist/utils/id.d.mts +2 -1
- package/dist/utils/id.mjs +2 -1
- package/dist/utils/id.mjs.map +1 -0
- package/dist/utils/ip.d.mts +2 -1
- package/dist/utils/ip.mjs +2 -1
- package/dist/utils/ip.mjs.map +1 -0
- package/dist/utils/json.d.mts +2 -1
- package/dist/utils/json.mjs +2 -1
- package/dist/utils/json.mjs.map +1 -0
- package/dist/utils/string.d.mts +2 -1
- package/dist/utils/string.mjs +2 -1
- package/dist/utils/string.mjs.map +1 -0
- package/dist/utils/url.d.mts +2 -1
- package/dist/utils/url.mjs +2 -1
- package/dist/utils/url.mjs.map +1 -0
- package/package.json +35 -13
- package/src/db/adapter/factory.ts +41 -73
- package/src/db/adapter/get-id-field.ts +1 -3
- package/src/db/adapter/index.ts +20 -15
- package/src/db/adapter/types.ts +2 -41
- package/src/db/get-tables.ts +48 -37
- package/src/db/index.ts +30 -5
- package/src/db/schema/account.ts +16 -3
- package/src/db/schema/rate-limit.ts +16 -1
- package/src/db/schema/session.ts +15 -3
- package/src/db/schema/user.ts +15 -3
- package/src/db/schema/verification.ts +16 -3
- package/src/db/test/get-tables.test.ts +33 -0
- package/src/db/type.ts +154 -1
- package/src/env/env-impl.ts +2 -2
- package/src/env/logger.ts +1 -1
- package/src/error/codes.ts +17 -0
- package/src/oauth2/client-credentials-token.ts +26 -2
- package/src/oauth2/create-authorization-url.ts +3 -1
- package/src/oauth2/index.ts +3 -0
- package/src/oauth2/oauth-provider.ts +1 -1
- package/src/oauth2/refresh-access-token.test.ts +90 -0
- package/src/oauth2/refresh-access-token.ts +37 -4
- package/src/oauth2/validate-authorization-code.ts +55 -24
- package/src/oauth2/validate-token.test.ts +107 -52
- package/src/social-providers/apple.ts +29 -29
- package/src/social-providers/cognito.ts +6 -5
- package/src/social-providers/facebook.ts +3 -3
- package/src/social-providers/github.ts +26 -4
- package/src/social-providers/gitlab.ts +1 -1
- package/src/social-providers/google.ts +18 -14
- package/src/social-providers/huggingface.ts +1 -1
- package/src/social-providers/index.ts +9 -5
- package/src/social-providers/kakao.ts +1 -1
- package/src/social-providers/line.ts +1 -1
- package/src/social-providers/microsoft-entra-id.ts +84 -1
- package/src/social-providers/naver.ts +1 -1
- package/src/social-providers/notion.ts +1 -1
- package/src/social-providers/paybin.ts +1 -5
- package/src/social-providers/polar.ts +1 -1
- package/src/social-providers/railway.ts +100 -0
- package/src/social-providers/tiktok.ts +2 -1
- package/src/social-providers/vercel.ts +1 -1
- package/src/social-providers/zoom.ts +0 -8
- package/src/types/context.ts +74 -14
- package/src/types/helper.ts +9 -0
- package/src/types/index.ts +14 -2
- package/src/types/init-options.ts +294 -186
- package/src/types/plugin-client.ts +1 -0
- package/src/types/plugin.ts +11 -6
- package/src/types/secret.ts +8 -0
- package/src/utils/db.ts +20 -0
- package/src/utils/deprecate.test.ts +0 -1
- package/src/utils/error-codes.ts +12 -9
- package/.turbo/turbo-build.log +0 -182
- package/tsconfig.json +0 -7
- package/tsdown.config.ts +0 -32
- package/vitest.config.ts +0 -3
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
vi.mock("@better-fetch/fetch", () => ({
|
|
4
|
+
betterFetch: vi.fn(),
|
|
5
|
+
}));
|
|
6
|
+
|
|
7
|
+
import { betterFetch } from "@better-fetch/fetch";
|
|
8
|
+
import { refreshAccessToken } from "./refresh-access-token";
|
|
9
|
+
|
|
10
|
+
const mockedBetterFetch = vi.mocked(betterFetch);
|
|
11
|
+
|
|
12
|
+
describe("refreshAccessToken", () => {
|
|
13
|
+
it("should set accessTokenExpiresAt when expires_in is returned", async () => {
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
mockedBetterFetch.mockResolvedValueOnce({
|
|
16
|
+
data: {
|
|
17
|
+
access_token: "new-access-token",
|
|
18
|
+
refresh_token: "new-refresh-token",
|
|
19
|
+
expires_in: 3600,
|
|
20
|
+
token_type: "Bearer",
|
|
21
|
+
},
|
|
22
|
+
error: null,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const tokens = await refreshAccessToken({
|
|
26
|
+
refreshToken: "old-refresh-token",
|
|
27
|
+
options: { clientId: "test-client", clientSecret: "test-secret" },
|
|
28
|
+
tokenEndpoint: "https://example.com/token",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
expect(tokens.accessToken).toBe("new-access-token");
|
|
32
|
+
expect(tokens.refreshToken).toBe("new-refresh-token");
|
|
33
|
+
expect(tokens.accessTokenExpiresAt).toBeInstanceOf(Date);
|
|
34
|
+
expect(tokens.accessTokenExpiresAt!.getTime()).toBeGreaterThanOrEqual(
|
|
35
|
+
now + 3600 * 1000 - 1000,
|
|
36
|
+
);
|
|
37
|
+
expect(tokens.refreshTokenExpiresAt).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @see https://github.com/better-auth/better-auth/issues/7682
|
|
42
|
+
*/
|
|
43
|
+
it("should set refreshTokenExpiresAt when refresh_token_expires_in is returned", async () => {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
mockedBetterFetch.mockResolvedValueOnce({
|
|
46
|
+
data: {
|
|
47
|
+
access_token: "new-access-token",
|
|
48
|
+
refresh_token: "new-refresh-token",
|
|
49
|
+
expires_in: 3600,
|
|
50
|
+
refresh_token_expires_in: 86400,
|
|
51
|
+
token_type: "Bearer",
|
|
52
|
+
},
|
|
53
|
+
error: null,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const tokens = await refreshAccessToken({
|
|
57
|
+
refreshToken: "old-refresh-token",
|
|
58
|
+
options: { clientId: "test-client", clientSecret: "test-secret" },
|
|
59
|
+
tokenEndpoint: "https://example.com/token",
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
expect(tokens.accessToken).toBe("new-access-token");
|
|
63
|
+
expect(tokens.refreshToken).toBe("new-refresh-token");
|
|
64
|
+
expect(tokens.accessTokenExpiresAt).toBeInstanceOf(Date);
|
|
65
|
+
expect(tokens.refreshTokenExpiresAt).toBeInstanceOf(Date);
|
|
66
|
+
expect(tokens.refreshTokenExpiresAt!.getTime()).toBeGreaterThanOrEqual(
|
|
67
|
+
now + 86400 * 1000 - 1000,
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should not set refreshTokenExpiresAt when refresh_token_expires_in is not returned", async () => {
|
|
72
|
+
mockedBetterFetch.mockResolvedValueOnce({
|
|
73
|
+
data: {
|
|
74
|
+
access_token: "new-access-token",
|
|
75
|
+
refresh_token: "new-refresh-token",
|
|
76
|
+
expires_in: 3600,
|
|
77
|
+
token_type: "Bearer",
|
|
78
|
+
},
|
|
79
|
+
error: null,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const tokens = await refreshAccessToken({
|
|
83
|
+
refreshToken: "old-refresh-token",
|
|
84
|
+
options: { clientId: "test-client", clientSecret: "test-secret" },
|
|
85
|
+
tokenEndpoint: "https://example.com/token",
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
expect(tokens.refreshTokenExpiresAt).toBeUndefined();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
import { base64 } from "@better-auth/utils/base64";
|
|
2
2
|
import { betterFetch } from "@better-fetch/fetch";
|
|
3
|
+
import type { AwaitableFunction } from "../types";
|
|
3
4
|
import type { OAuth2Tokens, ProviderOptions } from "./oauth-provider";
|
|
4
5
|
|
|
6
|
+
export async function refreshAccessTokenRequest({
|
|
7
|
+
refreshToken,
|
|
8
|
+
options,
|
|
9
|
+
authentication,
|
|
10
|
+
extraParams,
|
|
11
|
+
resource,
|
|
12
|
+
}: {
|
|
13
|
+
refreshToken: string;
|
|
14
|
+
options: AwaitableFunction<Partial<ProviderOptions>>;
|
|
15
|
+
authentication?: ("basic" | "post") | undefined;
|
|
16
|
+
extraParams?: Record<string, string> | undefined;
|
|
17
|
+
resource?: (string | string[]) | undefined;
|
|
18
|
+
}) {
|
|
19
|
+
options = typeof options === "function" ? await options() : options;
|
|
20
|
+
return createRefreshAccessTokenRequest({
|
|
21
|
+
refreshToken,
|
|
22
|
+
options,
|
|
23
|
+
authentication,
|
|
24
|
+
extraParams,
|
|
25
|
+
resource,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @deprecated use async'd refreshAccessTokenRequest instead
|
|
31
|
+
*/
|
|
5
32
|
export function createRefreshAccessTokenRequest({
|
|
6
33
|
refreshToken,
|
|
7
34
|
options,
|
|
@@ -10,7 +37,7 @@ export function createRefreshAccessTokenRequest({
|
|
|
10
37
|
resource,
|
|
11
38
|
}: {
|
|
12
39
|
refreshToken: string;
|
|
13
|
-
options:
|
|
40
|
+
options: ProviderOptions;
|
|
14
41
|
authentication?: ("basic" | "post") | undefined;
|
|
15
42
|
extraParams?: Record<string, string> | undefined;
|
|
16
43
|
resource?: (string | string[]) | undefined;
|
|
@@ -80,10 +107,8 @@ export async function refreshAccessToken({
|
|
|
80
107
|
tokenEndpoint: string;
|
|
81
108
|
authentication?: ("basic" | "post") | undefined;
|
|
82
109
|
extraParams?: Record<string, string> | undefined;
|
|
83
|
-
/** @deprecated always "refresh_token" */
|
|
84
|
-
grantType?: string | undefined;
|
|
85
110
|
}): Promise<OAuth2Tokens> {
|
|
86
|
-
const { body, headers } = createRefreshAccessTokenRequest({
|
|
111
|
+
const { body, headers } = await createRefreshAccessTokenRequest({
|
|
87
112
|
refreshToken,
|
|
88
113
|
options,
|
|
89
114
|
authentication,
|
|
@@ -94,6 +119,7 @@ export async function refreshAccessToken({
|
|
|
94
119
|
access_token: string;
|
|
95
120
|
refresh_token?: string | undefined;
|
|
96
121
|
expires_in?: number | undefined;
|
|
122
|
+
refresh_token_expires_in?: number | undefined;
|
|
97
123
|
token_type?: string | undefined;
|
|
98
124
|
scope?: string | undefined;
|
|
99
125
|
id_token?: string | undefined;
|
|
@@ -120,5 +146,12 @@ export async function refreshAccessToken({
|
|
|
120
146
|
);
|
|
121
147
|
}
|
|
122
148
|
|
|
149
|
+
if (data.refresh_token_expires_in) {
|
|
150
|
+
const now = new Date();
|
|
151
|
+
tokens.refreshTokenExpiresAt = new Date(
|
|
152
|
+
now.getTime() + data.refresh_token_expires_in * 1000,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
123
156
|
return tokens;
|
|
124
157
|
}
|
|
@@ -1,10 +1,48 @@
|
|
|
1
1
|
import { base64 } from "@better-auth/utils/base64";
|
|
2
2
|
import { betterFetch } from "@better-fetch/fetch";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
4
|
+
import type { AwaitableFunction } from "../types";
|
|
5
5
|
import type { ProviderOptions } from "./index";
|
|
6
6
|
import { getOAuth2Tokens } from "./index";
|
|
7
7
|
|
|
8
|
+
export async function authorizationCodeRequest({
|
|
9
|
+
code,
|
|
10
|
+
codeVerifier,
|
|
11
|
+
redirectURI,
|
|
12
|
+
options,
|
|
13
|
+
authentication,
|
|
14
|
+
deviceId,
|
|
15
|
+
headers,
|
|
16
|
+
additionalParams = {},
|
|
17
|
+
resource,
|
|
18
|
+
}: {
|
|
19
|
+
code: string;
|
|
20
|
+
redirectURI: string;
|
|
21
|
+
options: AwaitableFunction<Partial<ProviderOptions>>;
|
|
22
|
+
codeVerifier?: string | undefined;
|
|
23
|
+
deviceId?: string | undefined;
|
|
24
|
+
authentication?: ("basic" | "post") | undefined;
|
|
25
|
+
headers?: Record<string, string> | undefined;
|
|
26
|
+
additionalParams?: Record<string, string> | undefined;
|
|
27
|
+
resource?: (string | string[]) | undefined;
|
|
28
|
+
}) {
|
|
29
|
+
options = typeof options === "function" ? await options() : options;
|
|
30
|
+
return createAuthorizationCodeRequest({
|
|
31
|
+
code,
|
|
32
|
+
codeVerifier,
|
|
33
|
+
redirectURI,
|
|
34
|
+
options,
|
|
35
|
+
authentication,
|
|
36
|
+
deviceId,
|
|
37
|
+
headers,
|
|
38
|
+
additionalParams,
|
|
39
|
+
resource,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @deprecated use async'd authorizationCodeRequest instead
|
|
45
|
+
*/
|
|
8
46
|
export function createAuthorizationCodeRequest({
|
|
9
47
|
code,
|
|
10
48
|
codeVerifier,
|
|
@@ -32,6 +70,7 @@ export function createAuthorizationCodeRequest({
|
|
|
32
70
|
accept: "application/json",
|
|
33
71
|
...headers,
|
|
34
72
|
};
|
|
73
|
+
|
|
35
74
|
body.set("grant_type", "authorization_code");
|
|
36
75
|
body.set("code", code);
|
|
37
76
|
codeVerifier && body.set("code_verifier", codeVerifier);
|
|
@@ -91,7 +130,7 @@ export async function validateAuthorizationCode({
|
|
|
91
130
|
}: {
|
|
92
131
|
code: string;
|
|
93
132
|
redirectURI: string;
|
|
94
|
-
options: Partial<ProviderOptions
|
|
133
|
+
options: AwaitableFunction<Partial<ProviderOptions>>;
|
|
95
134
|
codeVerifier?: string | undefined;
|
|
96
135
|
deviceId?: string | undefined;
|
|
97
136
|
tokenEndpoint: string;
|
|
@@ -100,7 +139,7 @@ export async function validateAuthorizationCode({
|
|
|
100
139
|
additionalParams?: Record<string, string> | undefined;
|
|
101
140
|
resource?: (string | string[]) | undefined;
|
|
102
141
|
}) {
|
|
103
|
-
const { body, headers: requestHeaders } =
|
|
142
|
+
const { body, headers: requestHeaders } = await authorizationCodeRequest({
|
|
104
143
|
code,
|
|
105
144
|
codeVerifier,
|
|
106
145
|
redirectURI,
|
|
@@ -117,7 +156,6 @@ export async function validateAuthorizationCode({
|
|
|
117
156
|
body: body,
|
|
118
157
|
headers: requestHeaders,
|
|
119
158
|
});
|
|
120
|
-
|
|
121
159
|
if (error) {
|
|
122
160
|
throw error;
|
|
123
161
|
}
|
|
@@ -125,25 +163,18 @@ export async function validateAuthorizationCode({
|
|
|
125
163
|
return tokens;
|
|
126
164
|
}
|
|
127
165
|
|
|
128
|
-
export async function validateToken(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
166
|
+
export async function validateToken(
|
|
167
|
+
token: string,
|
|
168
|
+
jwksEndpoint: string,
|
|
169
|
+
options?: {
|
|
170
|
+
audience?: string | string[];
|
|
171
|
+
issuer?: string | string[];
|
|
172
|
+
},
|
|
173
|
+
) {
|
|
174
|
+
const jwks = createRemoteJWKSet(new URL(jwksEndpoint));
|
|
175
|
+
const verified = await jwtVerify(token, jwks, {
|
|
176
|
+
audience: options?.audience,
|
|
177
|
+
issuer: options?.issuer,
|
|
136
178
|
});
|
|
137
|
-
if (error) {
|
|
138
|
-
throw error;
|
|
139
|
-
}
|
|
140
|
-
const keys = data["keys"];
|
|
141
|
-
const header = decodeProtectedHeader(token);
|
|
142
|
-
const key = keys.find((k) => k.kid === header.kid);
|
|
143
|
-
if (!key) {
|
|
144
|
-
throw new Error("Key not found");
|
|
145
|
-
}
|
|
146
|
-
const cryptoKey = await importJWK(key, header.alg);
|
|
147
|
-
const verified = await jwtVerify(token, cryptoKey);
|
|
148
179
|
return verified;
|
|
149
180
|
}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
+
import type { JWK } from "jose";
|
|
1
2
|
import { exportJWK, generateKeyPair, SignJWT } from "jose";
|
|
2
|
-
import {
|
|
3
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
3
4
|
import { validateToken } from "./validate-authorization-code";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { betterFetch } from "@better-fetch/fetch";
|
|
6
|
+
describe("validateToken", () => {
|
|
7
|
+
const originalFetch = globalThis.fetch;
|
|
8
|
+
const mockedFetch = vi.fn() as unknown as typeof fetch &
|
|
9
|
+
ReturnType<typeof vi.fn>;
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
beforeAll(() => {
|
|
12
|
+
globalThis.fetch = mockedFetch;
|
|
13
|
+
});
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
vi.clearAllMocks();
|
|
15
|
+
afterAll(() => {
|
|
16
|
+
globalThis.fetch = originalFetch;
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
async function createTestJWKS(alg: string, crv?: string) {
|
|
@@ -24,7 +25,9 @@ describe("validateToken", () => {
|
|
|
24
25
|
const privateJWK = await exportJWK(privateKey);
|
|
25
26
|
const kid = `test-key-${Date.now()}`;
|
|
26
27
|
publicJWK.kid = kid;
|
|
28
|
+
publicJWK.alg = alg;
|
|
27
29
|
privateJWK.kid = kid;
|
|
30
|
+
privateJWK.alg = alg;
|
|
28
31
|
return { publicJWK, privateJWK, kid, publicKey, privateKey };
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -47,14 +50,19 @@ describe("validateToken", () => {
|
|
|
47
50
|
.sign(privateKey);
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
function mockJWKSResponse(...publicJWKs: JWK[]) {
|
|
54
|
+
mockedFetch.mockResolvedValueOnce(
|
|
55
|
+
new Response(JSON.stringify({ keys: publicJWKs }), {
|
|
56
|
+
status: 200,
|
|
57
|
+
headers: { "content-type": "application/json" },
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
50
62
|
it("should verify RS256 signed token", async () => {
|
|
51
63
|
const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
|
|
52
64
|
const token = await createSignedToken(privateKey, "RS256", kid);
|
|
53
|
-
|
|
54
|
-
mockedBetterFetch.mockResolvedValueOnce({
|
|
55
|
-
data: { keys: [publicJWK] },
|
|
56
|
-
error: null,
|
|
57
|
-
});
|
|
65
|
+
mockJWKSResponse(publicJWK);
|
|
58
66
|
|
|
59
67
|
const result = await validateToken(
|
|
60
68
|
token,
|
|
@@ -64,20 +72,12 @@ describe("validateToken", () => {
|
|
|
64
72
|
expect(result).toBeDefined();
|
|
65
73
|
expect(result.payload.sub).toBe("user-123");
|
|
66
74
|
expect(result.payload.email).toBe("test@example.com");
|
|
67
|
-
expect(mockedBetterFetch).toHaveBeenCalledWith(
|
|
68
|
-
"https://example.com/.well-known/jwks",
|
|
69
|
-
expect.objectContaining({ method: "GET" }),
|
|
70
|
-
);
|
|
71
75
|
});
|
|
72
76
|
|
|
73
77
|
it("should verify ES256 signed token", async () => {
|
|
74
78
|
const { publicJWK, privateKey, kid } = await createTestJWKS("ES256");
|
|
75
79
|
const token = await createSignedToken(privateKey, "ES256", kid);
|
|
76
|
-
|
|
77
|
-
mockedBetterFetch.mockResolvedValueOnce({
|
|
78
|
-
data: { keys: [publicJWK] },
|
|
79
|
-
error: null,
|
|
80
|
-
});
|
|
80
|
+
mockJWKSResponse(publicJWK);
|
|
81
81
|
|
|
82
82
|
const result = await validateToken(
|
|
83
83
|
token,
|
|
@@ -94,11 +94,7 @@ describe("validateToken", () => {
|
|
|
94
94
|
"Ed25519",
|
|
95
95
|
);
|
|
96
96
|
const token = await createSignedToken(privateKey, "EdDSA", kid);
|
|
97
|
-
|
|
98
|
-
mockedBetterFetch.mockResolvedValueOnce({
|
|
99
|
-
data: { keys: [publicJWK] },
|
|
100
|
-
error: null,
|
|
101
|
-
});
|
|
97
|
+
mockJWKSResponse(publicJWK);
|
|
102
98
|
|
|
103
99
|
const result = await validateToken(
|
|
104
100
|
token,
|
|
@@ -109,19 +105,15 @@ describe("validateToken", () => {
|
|
|
109
105
|
expect(result.payload.sub).toBe("user-123");
|
|
110
106
|
});
|
|
111
107
|
|
|
112
|
-
it("should throw
|
|
108
|
+
it("should throw when kid doesn't match any key", async () => {
|
|
113
109
|
const { publicJWK, privateKey } = await createTestJWKS("RS256");
|
|
114
110
|
publicJWK.kid = "different-kid";
|
|
115
111
|
const token = await createSignedToken(privateKey, "RS256", "original-kid");
|
|
116
|
-
|
|
117
|
-
mockedBetterFetch.mockResolvedValueOnce({
|
|
118
|
-
data: { keys: [publicJWK] },
|
|
119
|
-
error: null,
|
|
120
|
-
});
|
|
112
|
+
mockJWKSResponse(publicJWK);
|
|
121
113
|
|
|
122
114
|
await expect(
|
|
123
115
|
validateToken(token, "https://example.com/.well-known/jwks"),
|
|
124
|
-
).rejects.toThrow(
|
|
116
|
+
).rejects.toThrow();
|
|
125
117
|
});
|
|
126
118
|
|
|
127
119
|
it("should find correct key when multiple keys exist", async () => {
|
|
@@ -129,11 +121,7 @@ describe("validateToken", () => {
|
|
|
129
121
|
const key2 = await createTestJWKS("RS256");
|
|
130
122
|
const key3 = await createTestJWKS("ES256");
|
|
131
123
|
const token = await createSignedToken(key2.privateKey, "RS256", key2.kid);
|
|
132
|
-
|
|
133
|
-
mockedBetterFetch.mockResolvedValueOnce({
|
|
134
|
-
data: { keys: [key1.publicJWK, key2.publicJWK, key3.publicJWK] },
|
|
135
|
-
error: null,
|
|
136
|
-
});
|
|
124
|
+
mockJWKSResponse(key1.publicJWK, key2.publicJWK, key3.publicJWK);
|
|
137
125
|
|
|
138
126
|
const result = await validateToken(
|
|
139
127
|
token,
|
|
@@ -147,28 +135,95 @@ describe("validateToken", () => {
|
|
|
147
135
|
it("should throw when JWKS returns empty keys array", async () => {
|
|
148
136
|
const { privateKey, kid } = await createTestJWKS("RS256");
|
|
149
137
|
const token = await createSignedToken(privateKey, "RS256", kid);
|
|
150
|
-
|
|
151
|
-
mockedBetterFetch.mockResolvedValueOnce({
|
|
152
|
-
data: { keys: [] },
|
|
153
|
-
error: null,
|
|
154
|
-
});
|
|
138
|
+
mockJWKSResponse();
|
|
155
139
|
|
|
156
140
|
await expect(
|
|
157
141
|
validateToken(token, "https://example.com/.well-known/jwks"),
|
|
158
|
-
).rejects.toThrow(
|
|
142
|
+
).rejects.toThrow();
|
|
159
143
|
});
|
|
160
144
|
|
|
161
145
|
it("should throw when JWKS fetch fails", async () => {
|
|
162
146
|
const { privateKey, kid } = await createTestJWKS("RS256");
|
|
163
147
|
const token = await createSignedToken(privateKey, "RS256", kid);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
error: { status: 500, statusText: "Internal Server Error" },
|
|
168
|
-
});
|
|
148
|
+
mockedFetch.mockResolvedValueOnce(
|
|
149
|
+
new Response("Internal Server Error", { status: 500 }),
|
|
150
|
+
);
|
|
169
151
|
|
|
170
152
|
await expect(
|
|
171
153
|
validateToken(token, "https://example.com/.well-known/jwks"),
|
|
172
154
|
).rejects.toBeDefined();
|
|
173
155
|
});
|
|
156
|
+
|
|
157
|
+
it("should verify token with matching audience", async () => {
|
|
158
|
+
const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
|
|
159
|
+
const token = await createSignedToken(privateKey, "RS256", kid);
|
|
160
|
+
mockJWKSResponse(publicJWK);
|
|
161
|
+
|
|
162
|
+
const result = await validateToken(
|
|
163
|
+
token,
|
|
164
|
+
"https://example.com/.well-known/jwks",
|
|
165
|
+
{ audience: "test-client" },
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
expect(result).toBeDefined();
|
|
169
|
+
expect(result.payload.aud).toBe("test-client");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("should reject token with mismatched audience", async () => {
|
|
173
|
+
const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
|
|
174
|
+
const token = await createSignedToken(privateKey, "RS256", kid);
|
|
175
|
+
mockJWKSResponse(publicJWK);
|
|
176
|
+
|
|
177
|
+
await expect(
|
|
178
|
+
validateToken(token, "https://example.com/.well-known/jwks", {
|
|
179
|
+
audience: "wrong-client",
|
|
180
|
+
}),
|
|
181
|
+
).rejects.toThrow();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("should verify token with matching issuer", async () => {
|
|
185
|
+
const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
|
|
186
|
+
const token = await createSignedToken(privateKey, "RS256", kid);
|
|
187
|
+
mockJWKSResponse(publicJWK);
|
|
188
|
+
|
|
189
|
+
const result = await validateToken(
|
|
190
|
+
token,
|
|
191
|
+
"https://example.com/.well-known/jwks",
|
|
192
|
+
{ issuer: "https://example.com" },
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
expect(result).toBeDefined();
|
|
196
|
+
expect(result.payload.iss).toBe("https://example.com");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("should reject token with mismatched issuer", async () => {
|
|
200
|
+
const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
|
|
201
|
+
const token = await createSignedToken(privateKey, "RS256", kid);
|
|
202
|
+
mockJWKSResponse(publicJWK);
|
|
203
|
+
|
|
204
|
+
await expect(
|
|
205
|
+
validateToken(token, "https://example.com/.well-known/jwks", {
|
|
206
|
+
issuer: "https://wrong-issuer.com",
|
|
207
|
+
}),
|
|
208
|
+
).rejects.toThrow();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("should verify token with both audience and issuer", async () => {
|
|
212
|
+
const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
|
|
213
|
+
const token = await createSignedToken(privateKey, "RS256", kid);
|
|
214
|
+
mockJWKSResponse(publicJWK);
|
|
215
|
+
|
|
216
|
+
const result = await validateToken(
|
|
217
|
+
token,
|
|
218
|
+
"https://example.com/.well-known/jwks",
|
|
219
|
+
{
|
|
220
|
+
audience: "test-client",
|
|
221
|
+
issuer: "https://example.com",
|
|
222
|
+
},
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
expect(result).toBeDefined();
|
|
226
|
+
expect(result.payload.aud).toBe("test-client");
|
|
227
|
+
expect(result.payload.iss).toBe("https://example.com");
|
|
228
|
+
});
|
|
174
229
|
});
|
|
@@ -112,41 +112,41 @@ export const apple = (options: AppleOptions) => {
|
|
|
112
112
|
if (options.verifyIdToken) {
|
|
113
113
|
return options.verifyIdToken(token, nonce);
|
|
114
114
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
jwtClaims[field]
|
|
115
|
+
try {
|
|
116
|
+
const decodedHeader = decodeProtectedHeader(token);
|
|
117
|
+
const { kid, alg: jwtAlg } = decodedHeader;
|
|
118
|
+
if (!kid || !jwtAlg) return false;
|
|
119
|
+
const publicKey = await getApplePublicKey(kid);
|
|
120
|
+
const { payload: jwtClaims } = await jwtVerify(token, publicKey, {
|
|
121
|
+
algorithms: [jwtAlg],
|
|
122
|
+
issuer: "https://appleid.apple.com",
|
|
123
|
+
audience:
|
|
124
|
+
options.audience && options.audience.length
|
|
125
|
+
? options.audience
|
|
126
|
+
: options.appBundleIdentifier
|
|
127
|
+
? options.appBundleIdentifier
|
|
128
|
+
: options.clientId,
|
|
129
|
+
maxTokenAge: "1h",
|
|
130
|
+
});
|
|
131
|
+
["email_verified", "is_private_email"].forEach((field) => {
|
|
132
|
+
if (jwtClaims[field] !== undefined) {
|
|
133
|
+
jwtClaims[field] = Boolean(jwtClaims[field]);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
if (nonce && jwtClaims.nonce !== nonce) {
|
|
137
|
+
return false;
|
|
133
138
|
}
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
return !!jwtClaims;
|
|
140
|
+
} catch {
|
|
136
141
|
return false;
|
|
137
142
|
}
|
|
138
|
-
return !!jwtClaims;
|
|
139
143
|
},
|
|
140
144
|
refreshAccessToken: options.refreshAccessToken
|
|
141
145
|
? options.refreshAccessToken
|
|
142
146
|
: async (refreshToken) => {
|
|
143
147
|
return refreshAccessToken({
|
|
144
148
|
refreshToken,
|
|
145
|
-
options
|
|
146
|
-
clientId: options.clientId,
|
|
147
|
-
clientKey: options.clientKey,
|
|
148
|
-
clientSecret: options.clientSecret,
|
|
149
|
-
},
|
|
149
|
+
options,
|
|
150
150
|
tokenEndpoint: "https://appleid.apple.com/auth/token",
|
|
151
151
|
});
|
|
152
152
|
},
|
|
@@ -162,15 +162,15 @@ export const apple = (options: AppleOptions) => {
|
|
|
162
162
|
return null;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
// TODO: "
|
|
165
|
+
// TODO: "" masking will be removed when the name field is made optional
|
|
166
166
|
let name: string;
|
|
167
167
|
if (token.user?.name) {
|
|
168
168
|
const firstName = token.user.name.firstName || "";
|
|
169
169
|
const lastName = token.user.name.lastName || "";
|
|
170
170
|
const fullName = `${firstName} ${lastName}`.trim();
|
|
171
|
-
name = fullName
|
|
171
|
+
name = fullName;
|
|
172
172
|
} else {
|
|
173
|
-
name = profile.name || "
|
|
173
|
+
name = profile.name || "";
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
const emailVerified =
|
|
@@ -178,10 +178,7 @@ export const cognito = (options: CognitoOptions) => {
|
|
|
178
178
|
return null;
|
|
179
179
|
}
|
|
180
180
|
const name =
|
|
181
|
-
profile.name ||
|
|
182
|
-
profile.given_name ||
|
|
183
|
-
profile.username ||
|
|
184
|
-
profile.email;
|
|
181
|
+
profile.name || profile.given_name || profile.username || "";
|
|
185
182
|
const enrichedProfile = {
|
|
186
183
|
...profile,
|
|
187
184
|
name,
|
|
@@ -220,7 +217,11 @@ export const cognito = (options: CognitoOptions) => {
|
|
|
220
217
|
return {
|
|
221
218
|
user: {
|
|
222
219
|
id: userInfo.sub,
|
|
223
|
-
name:
|
|
220
|
+
name:
|
|
221
|
+
userInfo.name ||
|
|
222
|
+
userInfo.given_name ||
|
|
223
|
+
userInfo.username ||
|
|
224
|
+
"",
|
|
224
225
|
email: userInfo.email,
|
|
225
226
|
image: userInfo.picture,
|
|
226
227
|
emailVerified: userInfo.email_verified,
|
|
@@ -49,7 +49,7 @@ export const facebook = (options: FacebookOptions) => {
|
|
|
49
49
|
return await createAuthorizationURL({
|
|
50
50
|
id: "facebook",
|
|
51
51
|
options,
|
|
52
|
-
authorizationEndpoint: "https://www.facebook.com/
|
|
52
|
+
authorizationEndpoint: "https://www.facebook.com/v24.0/dialog/oauth",
|
|
53
53
|
scopes: _scopes,
|
|
54
54
|
state,
|
|
55
55
|
redirectURI,
|
|
@@ -66,7 +66,7 @@ export const facebook = (options: FacebookOptions) => {
|
|
|
66
66
|
code,
|
|
67
67
|
redirectURI,
|
|
68
68
|
options,
|
|
69
|
-
tokenEndpoint: "https://graph.facebook.com/oauth/access_token",
|
|
69
|
+
tokenEndpoint: "https://graph.facebook.com/v24.0/oauth/access_token",
|
|
70
70
|
});
|
|
71
71
|
},
|
|
72
72
|
async verifyIdToken(token, nonce) {
|
|
@@ -121,7 +121,7 @@ export const facebook = (options: FacebookOptions) => {
|
|
|
121
121
|
clientSecret: options.clientSecret,
|
|
122
122
|
},
|
|
123
123
|
tokenEndpoint:
|
|
124
|
-
"https://graph.facebook.com/
|
|
124
|
+
"https://graph.facebook.com/v24.0/oauth/access_token",
|
|
125
125
|
});
|
|
126
126
|
},
|
|
127
127
|
async getUserInfo(token) {
|