@shware/security 0.4.3

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.
Files changed (128) hide show
  1. package/README.md +1 -0
  2. package/dist/auth/index.cjs +158 -0
  3. package/dist/auth/index.cjs.map +1 -0
  4. package/dist/auth/index.d.cts +27 -0
  5. package/dist/auth/index.d.ts +27 -0
  6. package/dist/auth/index.mjs +129 -0
  7. package/dist/auth/index.mjs.map +1 -0
  8. package/dist/auth/types.cjs +19 -0
  9. package/dist/auth/types.cjs.map +1 -0
  10. package/dist/auth/types.d.cts +25 -0
  11. package/dist/auth/types.d.ts +25 -0
  12. package/dist/auth/types.mjs +1 -0
  13. package/dist/auth/types.mjs.map +1 -0
  14. package/dist/core/index.cjs +19 -0
  15. package/dist/core/index.cjs.map +1 -0
  16. package/dist/core/index.d.cts +17 -0
  17. package/dist/core/index.d.ts +17 -0
  18. package/dist/core/index.mjs +1 -0
  19. package/dist/core/index.mjs.map +1 -0
  20. package/dist/index.cjs +41 -0
  21. package/dist/index.cjs.map +1 -0
  22. package/dist/index.d.cts +11 -0
  23. package/dist/index.d.ts +11 -0
  24. package/dist/index.mjs +12 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/oauth2/client.cjs +110 -0
  27. package/dist/oauth2/client.cjs.map +1 -0
  28. package/dist/oauth2/client.d.cts +39 -0
  29. package/dist/oauth2/client.d.ts +39 -0
  30. package/dist/oauth2/client.mjs +74 -0
  31. package/dist/oauth2/client.mjs.map +1 -0
  32. package/dist/oauth2/error.cjs +54 -0
  33. package/dist/oauth2/error.cjs.map +1 -0
  34. package/dist/oauth2/error.d.cts +11 -0
  35. package/dist/oauth2/error.d.ts +11 -0
  36. package/dist/oauth2/error.mjs +28 -0
  37. package/dist/oauth2/error.mjs.map +1 -0
  38. package/dist/oauth2/provider/apple.cjs +85 -0
  39. package/dist/oauth2/provider/apple.cjs.map +1 -0
  40. package/dist/oauth2/provider/apple.d.cts +31 -0
  41. package/dist/oauth2/provider/apple.d.ts +31 -0
  42. package/dist/oauth2/provider/apple.mjs +50 -0
  43. package/dist/oauth2/provider/apple.mjs.map +1 -0
  44. package/dist/oauth2/provider/common.cjs +159 -0
  45. package/dist/oauth2/provider/common.cjs.map +1 -0
  46. package/dist/oauth2/provider/common.d.cts +38 -0
  47. package/dist/oauth2/provider/common.d.ts +38 -0
  48. package/dist/oauth2/provider/common.mjs +119 -0
  49. package/dist/oauth2/provider/common.mjs.map +1 -0
  50. package/dist/oauth2/provider/facebook.cjs +106 -0
  51. package/dist/oauth2/provider/facebook.cjs.map +1 -0
  52. package/dist/oauth2/provider/facebook.d.cts +29 -0
  53. package/dist/oauth2/provider/facebook.d.ts +29 -0
  54. package/dist/oauth2/provider/facebook.mjs +71 -0
  55. package/dist/oauth2/provider/facebook.mjs.map +1 -0
  56. package/dist/oauth2/provider/github.cjs +101 -0
  57. package/dist/oauth2/provider/github.cjs.map +1 -0
  58. package/dist/oauth2/provider/github.d.cts +51 -0
  59. package/dist/oauth2/provider/github.d.ts +51 -0
  60. package/dist/oauth2/provider/github.mjs +66 -0
  61. package/dist/oauth2/provider/github.mjs.map +1 -0
  62. package/dist/oauth2/provider/google.cjs +91 -0
  63. package/dist/oauth2/provider/google.cjs.map +1 -0
  64. package/dist/oauth2/provider/google.d.cts +35 -0
  65. package/dist/oauth2/provider/google.d.ts +35 -0
  66. package/dist/oauth2/provider/google.mjs +56 -0
  67. package/dist/oauth2/provider/google.mjs.map +1 -0
  68. package/dist/oauth2/provider/index.cjs +43 -0
  69. package/dist/oauth2/provider/index.cjs.map +1 -0
  70. package/dist/oauth2/provider/index.d.cts +6 -0
  71. package/dist/oauth2/provider/index.d.ts +6 -0
  72. package/dist/oauth2/provider/index.mjs +14 -0
  73. package/dist/oauth2/provider/index.mjs.map +1 -0
  74. package/dist/oauth2/provider/x.cjs +126 -0
  75. package/dist/oauth2/provider/x.cjs.map +1 -0
  76. package/dist/oauth2/provider/x.d.cts +60 -0
  77. package/dist/oauth2/provider/x.d.ts +60 -0
  78. package/dist/oauth2/provider/x.mjs +97 -0
  79. package/dist/oauth2/provider/x.mjs.map +1 -0
  80. package/dist/oauth2/schema.cjs +2 -0
  81. package/dist/oauth2/schema.cjs.map +1 -0
  82. package/dist/oauth2/schema.d.cts +2 -0
  83. package/dist/oauth2/schema.d.ts +2 -0
  84. package/dist/oauth2/schema.mjs +1 -0
  85. package/dist/oauth2/schema.mjs.map +1 -0
  86. package/dist/oauth2/types.cjs +19 -0
  87. package/dist/oauth2/types.cjs.map +1 -0
  88. package/dist/oauth2/types.d.cts +138 -0
  89. package/dist/oauth2/types.d.ts +138 -0
  90. package/dist/oauth2/types.mjs +1 -0
  91. package/dist/oauth2/types.mjs.map +1 -0
  92. package/dist/oidc/index.cjs +39 -0
  93. package/dist/oidc/index.cjs.map +1 -0
  94. package/dist/oidc/index.d.cts +10 -0
  95. package/dist/oidc/index.d.ts +10 -0
  96. package/dist/oidc/index.mjs +14 -0
  97. package/dist/oidc/index.mjs.map +1 -0
  98. package/dist/session/__test__/redis-session.test.cjs +94 -0
  99. package/dist/session/__test__/redis-session.test.cjs.map +1 -0
  100. package/dist/session/__test__/redis-session.test.d.cts +2 -0
  101. package/dist/session/__test__/redis-session.test.d.ts +2 -0
  102. package/dist/session/__test__/redis-session.test.mjs +70 -0
  103. package/dist/session/__test__/redis-session.test.mjs.map +1 -0
  104. package/dist/session/index.cjs +33 -0
  105. package/dist/session/index.cjs.map +1 -0
  106. package/dist/session/index.d.cts +4 -0
  107. package/dist/session/index.d.ts +4 -0
  108. package/dist/session/index.mjs +7 -0
  109. package/dist/session/index.mjs.map +1 -0
  110. package/dist/session/redis-session.cjs +403 -0
  111. package/dist/session/redis-session.cjs.map +1 -0
  112. package/dist/session/redis-session.d.cts +73 -0
  113. package/dist/session/redis-session.d.ts +73 -0
  114. package/dist/session/redis-session.mjs +377 -0
  115. package/dist/session/redis-session.mjs.map +1 -0
  116. package/dist/session/types.cjs +19 -0
  117. package/dist/session/types.cjs.map +1 -0
  118. package/dist/session/types.d.cts +39 -0
  119. package/dist/session/types.d.ts +39 -0
  120. package/dist/session/types.mjs +1 -0
  121. package/dist/session/types.mjs.map +1 -0
  122. package/dist/utils/http.cjs +63 -0
  123. package/dist/utils/http.cjs.map +1 -0
  124. package/dist/utils/http.d.cts +17 -0
  125. package/dist/utils/http.d.ts +17 -0
  126. package/dist/utils/http.mjs +34 -0
  127. package/dist/utils/http.mjs.map +1 -0
  128. package/package.json +44 -0
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/oauth2/provider/common.ts
31
+ var common_exports = {};
32
+ __export(common_exports, {
33
+ createAuthorizationUri: () => createAuthorizationUri,
34
+ exchangeAuthorizationCode: () => exchangeAuthorizationCode,
35
+ proxyAgent: () => proxyAgent,
36
+ refreshAccessToken: () => refreshAccessToken,
37
+ revokeToken: () => revokeToken,
38
+ verifyIdToken: () => verifyIdToken
39
+ });
40
+ module.exports = __toCommonJS(common_exports);
41
+ var import_crypto = require("crypto");
42
+ var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
43
+ var import_undici = require("undici");
44
+ var import_error = require("../error.cjs");
45
+ function createAuthorizationUri(options) {
46
+ const url = new URL(options.authorizationUri);
47
+ url.searchParams.append("response_type", "code");
48
+ url.searchParams.append("client_id", options.clientId);
49
+ url.searchParams.append("state", options.state);
50
+ url.searchParams.append("scope", options.scope.join(" "));
51
+ url.searchParams.append("redirect_uri", options.redirectUri);
52
+ if (options.codeVerifier) {
53
+ const codeChallenge = (0, import_crypto.createHash)("sha256").update(options.codeVerifier).digest().toString("base64url");
54
+ url.searchParams.append("code_challenge_method", "S256");
55
+ url.searchParams.append("code_challenge", codeChallenge);
56
+ }
57
+ return url;
58
+ }
59
+ var proxyAgent = new import_undici.ProxyAgent("http://localhost:7890");
60
+ async function exchangeAuthorizationCode(params) {
61
+ const body = new URLSearchParams();
62
+ body.append("code", params.code);
63
+ body.append("redirect_uri", params.redirectUri);
64
+ body.append("grant_type", "authorization_code");
65
+ if (params.codeVerifier) body.append("code_verifier", params.codeVerifier);
66
+ const headers = {
67
+ Accept: "application/json",
68
+ "Content-Type": "application/x-www-form-urlencoded"
69
+ };
70
+ if (params.authentication === "basic") {
71
+ const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString("base64");
72
+ headers.Authorization = `Basic ${token}`;
73
+ } else {
74
+ body.append("client_id", params.clientId);
75
+ body.append("client_secret", params.clientSecret);
76
+ }
77
+ return (0, import_undici.fetch)(params.tokenUri, { method: "POST", headers, body, dispatcher: proxyAgent });
78
+ }
79
+ async function refreshAccessToken(params) {
80
+ const body = new URLSearchParams();
81
+ body.append("grant_type", "refresh_token");
82
+ body.append("refresh_token", params.refreshToken);
83
+ const headers = {
84
+ Accept: "application/json",
85
+ "Content-Type": "application/x-www-form-urlencoded"
86
+ };
87
+ if (params.authentication === "basic") {
88
+ const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString("base64");
89
+ headers.Authorization = `Basic ${token}`;
90
+ } else {
91
+ body.append("client_id", params.clientId);
92
+ body.append("client_secret", params.clientSecret);
93
+ }
94
+ const response = await (0, import_undici.fetch)(params.tokenUri, { method: "POST", headers, body });
95
+ if (!response.ok) {
96
+ const error = await response.json();
97
+ console.error("Refresh token error:", error);
98
+ throw new import_error.OAuth2Error(response.status, "invalid_request", "Failed to refresh token");
99
+ }
100
+ return await response.json();
101
+ }
102
+ async function revokeToken(params) {
103
+ const body = new URLSearchParams();
104
+ body.append("token", params.token);
105
+ const headers = {
106
+ Accept: "application/json",
107
+ "Content-Type": "application/x-www-form-urlencoded"
108
+ };
109
+ if (params.authentication === "basic") {
110
+ const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString("base64");
111
+ headers.Authorization = `Basic ${token}`;
112
+ } else {
113
+ body.append("client_id", params.clientId);
114
+ body.append("client_secret", params.clientSecret);
115
+ }
116
+ const response = await (0, import_undici.fetch)(params.tokenRevokeUri, { method: "POST", headers, body });
117
+ if (!response.ok) {
118
+ const error = await response.json();
119
+ console.error("Refresh token error:", error);
120
+ throw new import_error.OAuth2Error(response.status, "invalid_request", "Failed to revoke token");
121
+ }
122
+ }
123
+ var cache = /* @__PURE__ */ new Map();
124
+ async function getJWK(kid, jwkSetUri) {
125
+ let jwkSet;
126
+ if (cache.has(jwkSetUri)) {
127
+ jwkSet = cache.get(jwkSetUri);
128
+ } else {
129
+ const response = await (0, import_undici.fetch)(jwkSetUri);
130
+ if (!response.ok) throw new import_error.OAuth2Error(response.status, "server_error", "Failed to fetch JWK");
131
+ jwkSet = await response.json();
132
+ cache.set(jwkSetUri, jwkSet);
133
+ }
134
+ const jwk = jwkSet.keys.find((key) => key.kid === kid);
135
+ if (!jwk) throw new import_error.OAuth2Error(400, "invalid_request", `JWK not found for kid: ${kid}`);
136
+ return jwk;
137
+ }
138
+ async function verifyIdToken(idToken, jwkSetUri) {
139
+ const header = import_jsonwebtoken.default.decode(idToken, { complete: true });
140
+ if (!header?.header.kid) {
141
+ throw new import_error.OAuth2Error(400, "invalid_request", "kid not found in id_token header");
142
+ }
143
+ try {
144
+ const key = await getJWK(header.header.kid, jwkSetUri);
145
+ return import_jsonwebtoken.default.verify(idToken, { key, format: "jwk" });
146
+ } catch (e) {
147
+ throw new import_error.OAuth2Error(400, "invalid_request", "Failed to verify id_token");
148
+ }
149
+ }
150
+ // Annotate the CommonJS export names for ESM import in node:
151
+ 0 && (module.exports = {
152
+ createAuthorizationUri,
153
+ exchangeAuthorizationCode,
154
+ proxyAgent,
155
+ refreshAccessToken,
156
+ revokeToken,
157
+ verifyIdToken
158
+ });
159
+ //# sourceMappingURL=common.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/oauth2/provider/common.ts"],"sourcesContent":["import { createHash } from 'crypto';\nimport jwt from 'jsonwebtoken';\nimport { fetch, ProxyAgent } from 'undici';\nimport { OAuth2Error } from '../error';\nimport { CodeExchangeParams, OAuth2Token } from '../types';\n\nexport function createAuthorizationUri(options: {\n state: string;\n scope: string[];\n clientId: string;\n redirectUri: string;\n authorizationUri: string;\n codeVerifier?: string;\n}) {\n const url = new URL(options.authorizationUri);\n url.searchParams.append('response_type', 'code');\n url.searchParams.append('client_id', options.clientId);\n url.searchParams.append('state', options.state);\n url.searchParams.append('scope', options.scope.join(' '));\n url.searchParams.append('redirect_uri', options.redirectUri);\n if (options.codeVerifier) {\n const codeChallenge = createHash('sha256')\n .update(options.codeVerifier)\n .digest()\n .toString('base64url');\n url.searchParams.append('code_challenge_method', 'S256');\n url.searchParams.append('code_challenge', codeChallenge);\n }\n return url;\n}\n\ninterface Params extends CodeExchangeParams {\n tokenUri: string;\n authentication?: 'basic' | 'post';\n}\n\nexport const proxyAgent = new ProxyAgent('http://localhost:7890');\nexport async function exchangeAuthorizationCode(params: Params) {\n const body = new URLSearchParams();\n body.append('code', params.code);\n body.append('redirect_uri', params.redirectUri);\n body.append('grant_type', 'authorization_code');\n if (params.codeVerifier) body.append('code_verifier', params.codeVerifier);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n return fetch(params.tokenUri, { method: 'POST', headers, body, dispatcher: proxyAgent });\n}\n\ninterface RefreshTokenParams {\n tokenUri: string;\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n authentication?: 'basic' | 'post';\n}\n\nexport async function refreshAccessToken(params: RefreshTokenParams) {\n const body = new URLSearchParams();\n body.append('grant_type', 'refresh_token');\n body.append('refresh_token', params.refreshToken);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n const response = await fetch(params.tokenUri, { method: 'POST', headers, body });\n if (!response.ok) {\n const error = await response.json();\n console.error('Refresh token error:', error);\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to refresh token');\n }\n return (await response.json()) as OAuth2Token;\n}\n\ninterface RevokeTokenParams {\n token: string;\n clientId: string;\n clientSecret: string;\n tokenRevokeUri: string;\n authentication?: 'basic' | 'post';\n}\n\nexport async function revokeToken(params: RevokeTokenParams) {\n const body = new URLSearchParams();\n body.append('token', params.token);\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n const response = await fetch(params.tokenRevokeUri, { method: 'POST', headers, body });\n if (!response.ok) {\n const error = await response.json();\n console.error('Refresh token error:', error);\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to revoke token');\n }\n}\n\ninterface JWKSet {\n keys: { kty: string; kid: string; use: string; alg: string; n: string; e: string }[];\n}\n\nconst cache = new Map<string, JWKSet>();\n\nasync function getJWK(kid: string, jwkSetUri: string) {\n let jwkSet: JWKSet;\n if (cache.has(jwkSetUri)) {\n jwkSet = cache.get(jwkSetUri)!;\n } else {\n const response = await fetch(jwkSetUri);\n if (!response.ok) throw new OAuth2Error(response.status, 'server_error', 'Failed to fetch JWK');\n jwkSet = (await response.json()) as JWKSet;\n cache.set(jwkSetUri, jwkSet);\n }\n\n const jwk = jwkSet.keys.find((key) => key.kid === kid);\n if (!jwk) throw new OAuth2Error(400, 'invalid_request', `JWK not found for kid: ${kid}`);\n return jwk;\n}\n\nexport async function verifyIdToken<T>(idToken: string, jwkSetUri: string) {\n const header = jwt.decode(idToken, { complete: true });\n if (!header?.header.kid) {\n throw new OAuth2Error(400, 'invalid_request', 'kid not found in id_token header');\n }\n try {\n const key = await getJWK(header.header.kid, jwkSetUri);\n return jwt.verify(idToken, { key, format: 'jwk' }) as T;\n } catch (e) {\n throw new OAuth2Error(400, 'invalid_request', 'Failed to verify id_token');\n }\n}\n"],"mappings":"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","names":["jwt"]}
@@ -0,0 +1,38 @@
1
+ import * as undici from 'undici';
2
+ import { ProxyAgent } from 'undici';
3
+ import * as url from 'url';
4
+ import { CodeExchangeParams, OAuth2Token } from '../types.cjs';
5
+
6
+ declare function createAuthorizationUri(options: {
7
+ state: string;
8
+ scope: string[];
9
+ clientId: string;
10
+ redirectUri: string;
11
+ authorizationUri: string;
12
+ codeVerifier?: string;
13
+ }): url.URL;
14
+ interface Params extends CodeExchangeParams {
15
+ tokenUri: string;
16
+ authentication?: 'basic' | 'post';
17
+ }
18
+ declare const proxyAgent: ProxyAgent;
19
+ declare function exchangeAuthorizationCode(params: Params): Promise<undici.Response>;
20
+ interface RefreshTokenParams {
21
+ tokenUri: string;
22
+ clientId: string;
23
+ clientSecret: string;
24
+ refreshToken: string;
25
+ authentication?: 'basic' | 'post';
26
+ }
27
+ declare function refreshAccessToken(params: RefreshTokenParams): Promise<OAuth2Token>;
28
+ interface RevokeTokenParams {
29
+ token: string;
30
+ clientId: string;
31
+ clientSecret: string;
32
+ tokenRevokeUri: string;
33
+ authentication?: 'basic' | 'post';
34
+ }
35
+ declare function revokeToken(params: RevokeTokenParams): Promise<void>;
36
+ declare function verifyIdToken<T>(idToken: string, jwkSetUri: string): Promise<T>;
37
+
38
+ export { createAuthorizationUri, exchangeAuthorizationCode, proxyAgent, refreshAccessToken, revokeToken, verifyIdToken };
@@ -0,0 +1,38 @@
1
+ import * as undici from 'undici';
2
+ import { ProxyAgent } from 'undici';
3
+ import * as url from 'url';
4
+ import { CodeExchangeParams, OAuth2Token } from '../types.js';
5
+
6
+ declare function createAuthorizationUri(options: {
7
+ state: string;
8
+ scope: string[];
9
+ clientId: string;
10
+ redirectUri: string;
11
+ authorizationUri: string;
12
+ codeVerifier?: string;
13
+ }): url.URL;
14
+ interface Params extends CodeExchangeParams {
15
+ tokenUri: string;
16
+ authentication?: 'basic' | 'post';
17
+ }
18
+ declare const proxyAgent: ProxyAgent;
19
+ declare function exchangeAuthorizationCode(params: Params): Promise<undici.Response>;
20
+ interface RefreshTokenParams {
21
+ tokenUri: string;
22
+ clientId: string;
23
+ clientSecret: string;
24
+ refreshToken: string;
25
+ authentication?: 'basic' | 'post';
26
+ }
27
+ declare function refreshAccessToken(params: RefreshTokenParams): Promise<OAuth2Token>;
28
+ interface RevokeTokenParams {
29
+ token: string;
30
+ clientId: string;
31
+ clientSecret: string;
32
+ tokenRevokeUri: string;
33
+ authentication?: 'basic' | 'post';
34
+ }
35
+ declare function revokeToken(params: RevokeTokenParams): Promise<void>;
36
+ declare function verifyIdToken<T>(idToken: string, jwkSetUri: string): Promise<T>;
37
+
38
+ export { createAuthorizationUri, exchangeAuthorizationCode, proxyAgent, refreshAccessToken, revokeToken, verifyIdToken };
@@ -0,0 +1,119 @@
1
+ // src/oauth2/provider/common.ts
2
+ import { createHash } from "crypto";
3
+ import jwt from "jsonwebtoken";
4
+ import { fetch, ProxyAgent } from "undici";
5
+ import { OAuth2Error } from "../error.mjs";
6
+ function createAuthorizationUri(options) {
7
+ const url = new URL(options.authorizationUri);
8
+ url.searchParams.append("response_type", "code");
9
+ url.searchParams.append("client_id", options.clientId);
10
+ url.searchParams.append("state", options.state);
11
+ url.searchParams.append("scope", options.scope.join(" "));
12
+ url.searchParams.append("redirect_uri", options.redirectUri);
13
+ if (options.codeVerifier) {
14
+ const codeChallenge = createHash("sha256").update(options.codeVerifier).digest().toString("base64url");
15
+ url.searchParams.append("code_challenge_method", "S256");
16
+ url.searchParams.append("code_challenge", codeChallenge);
17
+ }
18
+ return url;
19
+ }
20
+ var proxyAgent = new ProxyAgent("http://localhost:7890");
21
+ async function exchangeAuthorizationCode(params) {
22
+ const body = new URLSearchParams();
23
+ body.append("code", params.code);
24
+ body.append("redirect_uri", params.redirectUri);
25
+ body.append("grant_type", "authorization_code");
26
+ if (params.codeVerifier) body.append("code_verifier", params.codeVerifier);
27
+ const headers = {
28
+ Accept: "application/json",
29
+ "Content-Type": "application/x-www-form-urlencoded"
30
+ };
31
+ if (params.authentication === "basic") {
32
+ const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString("base64");
33
+ headers.Authorization = `Basic ${token}`;
34
+ } else {
35
+ body.append("client_id", params.clientId);
36
+ body.append("client_secret", params.clientSecret);
37
+ }
38
+ return fetch(params.tokenUri, { method: "POST", headers, body, dispatcher: proxyAgent });
39
+ }
40
+ async function refreshAccessToken(params) {
41
+ const body = new URLSearchParams();
42
+ body.append("grant_type", "refresh_token");
43
+ body.append("refresh_token", params.refreshToken);
44
+ const headers = {
45
+ Accept: "application/json",
46
+ "Content-Type": "application/x-www-form-urlencoded"
47
+ };
48
+ if (params.authentication === "basic") {
49
+ const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString("base64");
50
+ headers.Authorization = `Basic ${token}`;
51
+ } else {
52
+ body.append("client_id", params.clientId);
53
+ body.append("client_secret", params.clientSecret);
54
+ }
55
+ const response = await fetch(params.tokenUri, { method: "POST", headers, body });
56
+ if (!response.ok) {
57
+ const error = await response.json();
58
+ console.error("Refresh token error:", error);
59
+ throw new OAuth2Error(response.status, "invalid_request", "Failed to refresh token");
60
+ }
61
+ return await response.json();
62
+ }
63
+ async function revokeToken(params) {
64
+ const body = new URLSearchParams();
65
+ body.append("token", params.token);
66
+ const headers = {
67
+ Accept: "application/json",
68
+ "Content-Type": "application/x-www-form-urlencoded"
69
+ };
70
+ if (params.authentication === "basic") {
71
+ const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString("base64");
72
+ headers.Authorization = `Basic ${token}`;
73
+ } else {
74
+ body.append("client_id", params.clientId);
75
+ body.append("client_secret", params.clientSecret);
76
+ }
77
+ const response = await fetch(params.tokenRevokeUri, { method: "POST", headers, body });
78
+ if (!response.ok) {
79
+ const error = await response.json();
80
+ console.error("Refresh token error:", error);
81
+ throw new OAuth2Error(response.status, "invalid_request", "Failed to revoke token");
82
+ }
83
+ }
84
+ var cache = /* @__PURE__ */ new Map();
85
+ async function getJWK(kid, jwkSetUri) {
86
+ let jwkSet;
87
+ if (cache.has(jwkSetUri)) {
88
+ jwkSet = cache.get(jwkSetUri);
89
+ } else {
90
+ const response = await fetch(jwkSetUri);
91
+ if (!response.ok) throw new OAuth2Error(response.status, "server_error", "Failed to fetch JWK");
92
+ jwkSet = await response.json();
93
+ cache.set(jwkSetUri, jwkSet);
94
+ }
95
+ const jwk = jwkSet.keys.find((key) => key.kid === kid);
96
+ if (!jwk) throw new OAuth2Error(400, "invalid_request", `JWK not found for kid: ${kid}`);
97
+ return jwk;
98
+ }
99
+ async function verifyIdToken(idToken, jwkSetUri) {
100
+ const header = jwt.decode(idToken, { complete: true });
101
+ if (!header?.header.kid) {
102
+ throw new OAuth2Error(400, "invalid_request", "kid not found in id_token header");
103
+ }
104
+ try {
105
+ const key = await getJWK(header.header.kid, jwkSetUri);
106
+ return jwt.verify(idToken, { key, format: "jwk" });
107
+ } catch (e) {
108
+ throw new OAuth2Error(400, "invalid_request", "Failed to verify id_token");
109
+ }
110
+ }
111
+ export {
112
+ createAuthorizationUri,
113
+ exchangeAuthorizationCode,
114
+ proxyAgent,
115
+ refreshAccessToken,
116
+ revokeToken,
117
+ verifyIdToken
118
+ };
119
+ //# sourceMappingURL=common.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/oauth2/provider/common.ts"],"sourcesContent":["import { createHash } from 'crypto';\nimport jwt from 'jsonwebtoken';\nimport { fetch, ProxyAgent } from 'undici';\nimport { OAuth2Error } from '../error';\nimport { CodeExchangeParams, OAuth2Token } from '../types';\n\nexport function createAuthorizationUri(options: {\n state: string;\n scope: string[];\n clientId: string;\n redirectUri: string;\n authorizationUri: string;\n codeVerifier?: string;\n}) {\n const url = new URL(options.authorizationUri);\n url.searchParams.append('response_type', 'code');\n url.searchParams.append('client_id', options.clientId);\n url.searchParams.append('state', options.state);\n url.searchParams.append('scope', options.scope.join(' '));\n url.searchParams.append('redirect_uri', options.redirectUri);\n if (options.codeVerifier) {\n const codeChallenge = createHash('sha256')\n .update(options.codeVerifier)\n .digest()\n .toString('base64url');\n url.searchParams.append('code_challenge_method', 'S256');\n url.searchParams.append('code_challenge', codeChallenge);\n }\n return url;\n}\n\ninterface Params extends CodeExchangeParams {\n tokenUri: string;\n authentication?: 'basic' | 'post';\n}\n\nexport const proxyAgent = new ProxyAgent('http://localhost:7890');\nexport async function exchangeAuthorizationCode(params: Params) {\n const body = new URLSearchParams();\n body.append('code', params.code);\n body.append('redirect_uri', params.redirectUri);\n body.append('grant_type', 'authorization_code');\n if (params.codeVerifier) body.append('code_verifier', params.codeVerifier);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n return fetch(params.tokenUri, { method: 'POST', headers, body, dispatcher: proxyAgent });\n}\n\ninterface RefreshTokenParams {\n tokenUri: string;\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n authentication?: 'basic' | 'post';\n}\n\nexport async function refreshAccessToken(params: RefreshTokenParams) {\n const body = new URLSearchParams();\n body.append('grant_type', 'refresh_token');\n body.append('refresh_token', params.refreshToken);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n const response = await fetch(params.tokenUri, { method: 'POST', headers, body });\n if (!response.ok) {\n const error = await response.json();\n console.error('Refresh token error:', error);\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to refresh token');\n }\n return (await response.json()) as OAuth2Token;\n}\n\ninterface RevokeTokenParams {\n token: string;\n clientId: string;\n clientSecret: string;\n tokenRevokeUri: string;\n authentication?: 'basic' | 'post';\n}\n\nexport async function revokeToken(params: RevokeTokenParams) {\n const body = new URLSearchParams();\n body.append('token', params.token);\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'Content-Type': 'application/x-www-form-urlencoded',\n };\n\n if (params.authentication === 'basic') {\n const token = Buffer.from(`${params.clientId}:${params.clientSecret}`).toString('base64');\n headers.Authorization = `Basic ${token}`;\n } else {\n body.append('client_id', params.clientId);\n body.append('client_secret', params.clientSecret);\n }\n\n const response = await fetch(params.tokenRevokeUri, { method: 'POST', headers, body });\n if (!response.ok) {\n const error = await response.json();\n console.error('Refresh token error:', error);\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to revoke token');\n }\n}\n\ninterface JWKSet {\n keys: { kty: string; kid: string; use: string; alg: string; n: string; e: string }[];\n}\n\nconst cache = new Map<string, JWKSet>();\n\nasync function getJWK(kid: string, jwkSetUri: string) {\n let jwkSet: JWKSet;\n if (cache.has(jwkSetUri)) {\n jwkSet = cache.get(jwkSetUri)!;\n } else {\n const response = await fetch(jwkSetUri);\n if (!response.ok) throw new OAuth2Error(response.status, 'server_error', 'Failed to fetch JWK');\n jwkSet = (await response.json()) as JWKSet;\n cache.set(jwkSetUri, jwkSet);\n }\n\n const jwk = jwkSet.keys.find((key) => key.kid === kid);\n if (!jwk) throw new OAuth2Error(400, 'invalid_request', `JWK not found for kid: ${kid}`);\n return jwk;\n}\n\nexport async function verifyIdToken<T>(idToken: string, jwkSetUri: string) {\n const header = jwt.decode(idToken, { complete: true });\n if (!header?.header.kid) {\n throw new OAuth2Error(400, 'invalid_request', 'kid not found in id_token header');\n }\n try {\n const key = await getJWK(header.header.kid, jwkSetUri);\n return jwt.verify(idToken, { key, format: 'jwk' }) as T;\n } catch (e) {\n throw new OAuth2Error(400, 'invalid_request', 'Failed to verify id_token');\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/oauth2/provider/facebook.ts
31
+ var facebook_exports = {};
32
+ __export(facebook_exports, {
33
+ facebook: () => facebook
34
+ });
35
+ module.exports = __toCommonJS(facebook_exports);
36
+ var import_tiny_invariant = __toESM(require("tiny-invariant"), 1);
37
+ var import_error = require("../error.cjs");
38
+ var import_common = require("./common.cjs");
39
+ function facebook() {
40
+ return {
41
+ authorizationUri: "https://www.facebook.com/v21.0/dialog/oauth",
42
+ tokenUri: "https://graph.facebook.com/v19.0/oauth/access_token",
43
+ userInfoUri: "https://graph.facebook.com/me",
44
+ jwkSetUri: "https://limited.facebook.com/.well-known/oauth/openid/jwks/",
45
+ userNameAttribute: "id",
46
+ defaultScope: ["profile", "email"],
47
+ createAuthorizationUri({ codeVerifier, ...params }) {
48
+ return (0, import_common.createAuthorizationUri)({
49
+ ...params,
50
+ scope: params.scope ?? this.defaultScope,
51
+ authorizationUri: this.authorizationUri
52
+ });
53
+ },
54
+ async exchangeAuthorizationCode({ codeVerifier, ...params }) {
55
+ const response = await (0, import_common.exchangeAuthorizationCode)({ ...params, tokenUri: this.tokenUri });
56
+ if (!response.ok) {
57
+ const { error } = await response.json();
58
+ throw new import_error.OAuth2Error(response.status, "invalid_request", error.message);
59
+ }
60
+ return await response.json();
61
+ },
62
+ async getUserInfo({ id_token, access_token }) {
63
+ (0, import_tiny_invariant.default)(this.jwkSetUri, "jwkSetUri is required");
64
+ if (id_token) {
65
+ const data2 = await (0, import_common.verifyIdToken)(id_token, this.jwkSetUri);
66
+ return {
67
+ data: data2,
68
+ claims: {
69
+ sub: data2.sub,
70
+ name: data2.name,
71
+ picture: data2.picture,
72
+ email: data2.email,
73
+ email_verified: true
74
+ }
75
+ };
76
+ }
77
+ (0, import_tiny_invariant.default)(access_token, "access_token is required");
78
+ (0, import_tiny_invariant.default)(this.userInfoUri, "userInfoUri is required");
79
+ const url = new URL(this.userInfoUri);
80
+ const fields = ["id", "name", "email", "picture.width(320).height(320)"];
81
+ url.searchParams.append("access_token", access_token);
82
+ url.searchParams.append("fields", fields.join(","));
83
+ const headers = { Accept: "application/json" };
84
+ const response = await fetch(url.href, { headers });
85
+ if (!response.ok) {
86
+ throw new import_error.OAuth2Error(response.status, "invalid_request", "Failed to fetch user info");
87
+ }
88
+ const data = await response.json();
89
+ return {
90
+ data,
91
+ claims: {
92
+ sub: data.id,
93
+ name: data.name,
94
+ email: data.email,
95
+ picture: data.picture.data.url,
96
+ email_verified: data.email_verified
97
+ }
98
+ };
99
+ }
100
+ };
101
+ }
102
+ // Annotate the CommonJS export names for ESM import in node:
103
+ 0 && (module.exports = {
104
+ facebook
105
+ });
106
+ //# sourceMappingURL=facebook.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/oauth2/provider/facebook.ts"],"sourcesContent":["import invariant from 'tiny-invariant';\nimport { Provider } from '../types';\nimport { OAuth2Error } from '../error';\nimport { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from './common';\n\n/**\n * ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/\n * ref: https://developers.facebook.com/tools/explorer\n * */\nexport function facebook(): Provider<FacebookUserInfo | FacebookDecodedIdToken> {\n return {\n authorizationUri: 'https://www.facebook.com/v21.0/dialog/oauth',\n tokenUri: 'https://graph.facebook.com/v19.0/oauth/access_token',\n userInfoUri: 'https://graph.facebook.com/me',\n jwkSetUri: 'https://limited.facebook.com/.well-known/oauth/openid/jwks/',\n userNameAttribute: 'id',\n defaultScope: ['profile', 'email'],\n createAuthorizationUri({ codeVerifier, ...params }) {\n return createAuthorizationUri({\n ...params,\n scope: params.scope ?? this.defaultScope,\n authorizationUri: this.authorizationUri,\n });\n },\n async exchangeAuthorizationCode({ codeVerifier, ...params }) {\n const response = await exchangeAuthorizationCode({ ...params, tokenUri: this.tokenUri });\n if (!response.ok) {\n const { error } = (await response.json()) as FacebookErrorResponse;\n throw new OAuth2Error(response.status, 'invalid_request', error.message);\n }\n return (await response.json()) as FacebookOAuth2Token;\n },\n async getUserInfo({ id_token, access_token }) {\n invariant(this.jwkSetUri, 'jwkSetUri is required');\n if (id_token) {\n const data = await verifyIdToken<FacebookDecodedIdToken>(id_token, this.jwkSetUri);\n return {\n data,\n claims: {\n sub: data.sub,\n name: data.name,\n picture: data.picture,\n email: data.email,\n email_verified: true,\n },\n };\n }\n invariant(access_token, 'access_token is required');\n invariant(this.userInfoUri, 'userInfoUri is required');\n\n const url = new URL(this.userInfoUri);\n const fields = ['id', 'name', 'email', 'picture.width(320).height(320)'];\n url.searchParams.append('access_token', access_token);\n url.searchParams.append('fields', fields.join(','));\n const headers = { Accept: 'application/json' };\n const response = await fetch(url.href, { headers });\n if (!response.ok) {\n throw new OAuth2Error(response.status, 'invalid_request', 'Failed to fetch user info');\n }\n const data = (await response.json()) as FacebookUserInfo;\n return {\n data,\n claims: {\n sub: data.id,\n name: data.name,\n email: data.email,\n picture: data.picture.data.url,\n email_verified: data.email_verified,\n },\n };\n },\n };\n}\n\nexport interface FacebookDecodedIdToken {\n sub: string;\n name: string;\n email: string;\n picture: string;\n}\n\nexport interface FacebookUserInfo {\n id: string;\n name: string;\n email: string;\n email_verified: boolean;\n picture: {\n data: {\n url: string;\n width: number;\n height: number;\n is_silhouette: boolean;\n };\n };\n}\n\ninterface FacebookOAuth2Token {\n access_token: string;\n token_type: 'bearer';\n expires_in: number;\n}\n\ninterface FacebookErrorResponse {\n error: {\n message: string;\n type: 'OAuthException';\n code: number;\n error_subcode: number;\n fbtrace_id: string;\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAsB;AAEtB,mBAA4B;AAC5B,oBAAiF;AAM1E,SAAS,WAAgE;AAC9E,SAAO;AAAA,IACL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,cAAc,CAAC,WAAW,OAAO;AAAA,IACjC,uBAAuB,EAAE,cAAc,GAAG,OAAO,GAAG;AAClD,iBAAO,sCAAuB;AAAA,QAC5B,GAAG;AAAA,QACH,OAAO,OAAO,SAAS,KAAK;AAAA,QAC5B,kBAAkB,KAAK;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,IACA,MAAM,0BAA0B,EAAE,cAAc,GAAG,OAAO,GAAG;AAC3D,YAAM,WAAW,UAAM,yCAA0B,EAAE,GAAG,QAAQ,UAAU,KAAK,SAAS,CAAC;AACvF,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,EAAE,MAAM,IAAK,MAAM,SAAS,KAAK;AACvC,cAAM,IAAI,yBAAY,SAAS,QAAQ,mBAAmB,MAAM,OAAO;AAAA,MACzE;AACA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAAA,IACA,MAAM,YAAY,EAAE,UAAU,aAAa,GAAG;AAC5C,gCAAAA,SAAU,KAAK,WAAW,uBAAuB;AACjD,UAAI,UAAU;AACZ,cAAMC,QAAO,UAAM,6BAAsC,UAAU,KAAK,SAAS;AACjF,eAAO;AAAA,UACL,MAAAA;AAAA,UACA,QAAQ;AAAA,YACN,KAAKA,MAAK;AAAA,YACV,MAAMA,MAAK;AAAA,YACX,SAASA,MAAK;AAAA,YACd,OAAOA,MAAK;AAAA,YACZ,gBAAgB;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AACA,gCAAAD,SAAU,cAAc,0BAA0B;AAClD,gCAAAA,SAAU,KAAK,aAAa,yBAAyB;AAErD,YAAM,MAAM,IAAI,IAAI,KAAK,WAAW;AACpC,YAAM,SAAS,CAAC,MAAM,QAAQ,SAAS,gCAAgC;AACvE,UAAI,aAAa,OAAO,gBAAgB,YAAY;AACpD,UAAI,aAAa,OAAO,UAAU,OAAO,KAAK,GAAG,CAAC;AAClD,YAAM,UAAU,EAAE,QAAQ,mBAAmB;AAC7C,YAAM,WAAW,MAAM,MAAM,IAAI,MAAM,EAAE,QAAQ,CAAC;AAClD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,yBAAY,SAAS,QAAQ,mBAAmB,2BAA2B;AAAA,MACvF;AACA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,UACN,KAAK,KAAK;AAAA,UACV,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK,QAAQ,KAAK;AAAA,UAC3B,gBAAgB,KAAK;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":["invariant","data"]}
@@ -0,0 +1,29 @@
1
+ import { Provider } from '../types.cjs';
2
+
3
+ /**
4
+ * ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/
5
+ * ref: https://developers.facebook.com/tools/explorer
6
+ * */
7
+ declare function facebook(): Provider<FacebookUserInfo | FacebookDecodedIdToken>;
8
+ interface FacebookDecodedIdToken {
9
+ sub: string;
10
+ name: string;
11
+ email: string;
12
+ picture: string;
13
+ }
14
+ interface FacebookUserInfo {
15
+ id: string;
16
+ name: string;
17
+ email: string;
18
+ email_verified: boolean;
19
+ picture: {
20
+ data: {
21
+ url: string;
22
+ width: number;
23
+ height: number;
24
+ is_silhouette: boolean;
25
+ };
26
+ };
27
+ }
28
+
29
+ export { type FacebookDecodedIdToken, type FacebookUserInfo, facebook };
@@ -0,0 +1,29 @@
1
+ import { Provider } from '../types.js';
2
+
3
+ /**
4
+ * ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/
5
+ * ref: https://developers.facebook.com/tools/explorer
6
+ * */
7
+ declare function facebook(): Provider<FacebookUserInfo | FacebookDecodedIdToken>;
8
+ interface FacebookDecodedIdToken {
9
+ sub: string;
10
+ name: string;
11
+ email: string;
12
+ picture: string;
13
+ }
14
+ interface FacebookUserInfo {
15
+ id: string;
16
+ name: string;
17
+ email: string;
18
+ email_verified: boolean;
19
+ picture: {
20
+ data: {
21
+ url: string;
22
+ width: number;
23
+ height: number;
24
+ is_silhouette: boolean;
25
+ };
26
+ };
27
+ }
28
+
29
+ export { type FacebookDecodedIdToken, type FacebookUserInfo, facebook };
@@ -0,0 +1,71 @@
1
+ // src/oauth2/provider/facebook.ts
2
+ import invariant from "tiny-invariant";
3
+ import { OAuth2Error } from "../error.mjs";
4
+ import { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from "./common.mjs";
5
+ function facebook() {
6
+ return {
7
+ authorizationUri: "https://www.facebook.com/v21.0/dialog/oauth",
8
+ tokenUri: "https://graph.facebook.com/v19.0/oauth/access_token",
9
+ userInfoUri: "https://graph.facebook.com/me",
10
+ jwkSetUri: "https://limited.facebook.com/.well-known/oauth/openid/jwks/",
11
+ userNameAttribute: "id",
12
+ defaultScope: ["profile", "email"],
13
+ createAuthorizationUri({ codeVerifier, ...params }) {
14
+ return createAuthorizationUri({
15
+ ...params,
16
+ scope: params.scope ?? this.defaultScope,
17
+ authorizationUri: this.authorizationUri
18
+ });
19
+ },
20
+ async exchangeAuthorizationCode({ codeVerifier, ...params }) {
21
+ const response = await exchangeAuthorizationCode({ ...params, tokenUri: this.tokenUri });
22
+ if (!response.ok) {
23
+ const { error } = await response.json();
24
+ throw new OAuth2Error(response.status, "invalid_request", error.message);
25
+ }
26
+ return await response.json();
27
+ },
28
+ async getUserInfo({ id_token, access_token }) {
29
+ invariant(this.jwkSetUri, "jwkSetUri is required");
30
+ if (id_token) {
31
+ const data2 = await verifyIdToken(id_token, this.jwkSetUri);
32
+ return {
33
+ data: data2,
34
+ claims: {
35
+ sub: data2.sub,
36
+ name: data2.name,
37
+ picture: data2.picture,
38
+ email: data2.email,
39
+ email_verified: true
40
+ }
41
+ };
42
+ }
43
+ invariant(access_token, "access_token is required");
44
+ invariant(this.userInfoUri, "userInfoUri is required");
45
+ const url = new URL(this.userInfoUri);
46
+ const fields = ["id", "name", "email", "picture.width(320).height(320)"];
47
+ url.searchParams.append("access_token", access_token);
48
+ url.searchParams.append("fields", fields.join(","));
49
+ const headers = { Accept: "application/json" };
50
+ const response = await fetch(url.href, { headers });
51
+ if (!response.ok) {
52
+ throw new OAuth2Error(response.status, "invalid_request", "Failed to fetch user info");
53
+ }
54
+ const data = await response.json();
55
+ return {
56
+ data,
57
+ claims: {
58
+ sub: data.id,
59
+ name: data.name,
60
+ email: data.email,
61
+ picture: data.picture.data.url,
62
+ email_verified: data.email_verified
63
+ }
64
+ };
65
+ }
66
+ };
67
+ }
68
+ export {
69
+ facebook
70
+ };
71
+ //# sourceMappingURL=facebook.mjs.map