@vercel/oidc 3.0.5 → 3.2.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/CHANGELOG.md +18 -0
- package/README.md +38 -0
- package/dist/auth-config.d.ts +30 -0
- package/dist/auth-config.js +85 -0
- package/dist/auth-errors.d.ts +16 -0
- package/dist/auth-errors.js +43 -0
- package/dist/get-vercel-oidc-token.d.ts +34 -1
- package/dist/get-vercel-oidc-token.js +10 -6
- package/dist/get-vercel-oidc-token.test.d.ts +1 -0
- package/dist/get-vercel-oidc-token.test.js +363 -0
- package/dist/index-browser.d.ts +2 -0
- package/dist/index-browser.js +12 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +10 -2
- package/dist/oauth.d.ts +17 -0
- package/dist/oauth.js +88 -0
- package/dist/token-io.d.ts +1 -1
- package/dist/token-io.js +1 -1
- package/dist/token-util.d.ts +10 -2
- package/dist/token-util.js +101 -75
- package/dist/token-util.test.d.ts +1 -0
- package/dist/token-util.test.js +232 -0
- package/dist/token.d.ts +19 -1
- package/dist/token.js +21 -14
- package/dist/token.test.js +108 -2
- package/docs/README.md +49 -4
- package/docs/classes/AccessTokenMissingError.md +160 -0
- package/docs/classes/RefreshAccessTokenFailedError.md +166 -0
- package/package.json +1 -1
|
@@ -0,0 +1,363 @@
|
|
|
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 __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var import_crypto = require("crypto");
|
|
25
|
+
var import_vitest = require("vitest");
|
|
26
|
+
var os = __toESM(require("os"));
|
|
27
|
+
var path = __toESM(require("path"));
|
|
28
|
+
var fs = __toESM(require("fs"));
|
|
29
|
+
var import_token_io = require("./token-io");
|
|
30
|
+
var import_get_vercel_oidc_token = require("./get-vercel-oidc-token");
|
|
31
|
+
var tokenUtil = __toESM(require("./token-util"));
|
|
32
|
+
import_vitest.vi.mock("./token-io");
|
|
33
|
+
import_vitest.vi.mock("./get-context", () => ({
|
|
34
|
+
getContext: () => ({ headers: {} })
|
|
35
|
+
}));
|
|
36
|
+
(0, import_vitest.describe)("getVercelOidcToken - Error Scenarios", () => {
|
|
37
|
+
let rootDir;
|
|
38
|
+
let userDataDir;
|
|
39
|
+
let cliDataDir;
|
|
40
|
+
let tokenDataDir;
|
|
41
|
+
const projectId = "prj_test123";
|
|
42
|
+
const teamId = "team_test456";
|
|
43
|
+
(0, import_vitest.beforeEach)(() => {
|
|
44
|
+
import_vitest.vi.clearAllMocks();
|
|
45
|
+
import_vitest.vi.restoreAllMocks();
|
|
46
|
+
process.env.VERCEL_OIDC_TOKEN = void 0;
|
|
47
|
+
const random = `test-${(0, import_crypto.randomUUID)()}`;
|
|
48
|
+
rootDir = path.join(os.tmpdir(), random);
|
|
49
|
+
userDataDir = path.join(rootDir, "data");
|
|
50
|
+
cliDataDir = path.join(userDataDir, "com.vercel.cli");
|
|
51
|
+
tokenDataDir = path.join(userDataDir, "com.vercel.token");
|
|
52
|
+
fs.mkdirSync(cliDataDir, { recursive: true });
|
|
53
|
+
fs.mkdirSync(tokenDataDir, { recursive: true });
|
|
54
|
+
fs.mkdirSync(path.join(rootDir, ".vercel"), {
|
|
55
|
+
recursive: true
|
|
56
|
+
});
|
|
57
|
+
import_vitest.vi.spyOn(process, "cwd").mockReturnValue(rootDir);
|
|
58
|
+
import_vitest.vi.mocked(import_token_io.findRootDir).mockReturnValue(rootDir);
|
|
59
|
+
import_vitest.vi.mocked(import_token_io.getUserDataDir).mockReturnValue(userDataDir);
|
|
60
|
+
});
|
|
61
|
+
(0, import_vitest.afterEach)(() => {
|
|
62
|
+
if (fs.existsSync(rootDir)) {
|
|
63
|
+
fs.rmSync(rootDir, { recursive: true, force: true });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
(0, import_vitest.test)("should throw AccessTokenMissingError when CLI auth file is missing", async () => {
|
|
67
|
+
fs.writeFileSync(
|
|
68
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
69
|
+
JSON.stringify({ projectId, orgId: teamId })
|
|
70
|
+
);
|
|
71
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
72
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(
|
|
73
|
+
/No authentication found/
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
(0, import_vitest.test)("should throw helpful error when project.json is missing", async () => {
|
|
77
|
+
fs.writeFileSync(
|
|
78
|
+
path.join(cliDataDir, "auth.json"),
|
|
79
|
+
JSON.stringify({ token: "test-auth-token" })
|
|
80
|
+
);
|
|
81
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
82
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(
|
|
83
|
+
/project\.json not found, have you linked your project with `vc link\?`/
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
(0, import_vitest.test)("should throw helpful error when root directory cannot be found", async () => {
|
|
87
|
+
import_vitest.vi.mocked(import_token_io.findRootDir).mockReturnValue(null);
|
|
88
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
89
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(
|
|
90
|
+
/Unable to find project root directory\. Have you linked your project with `vc link\?`/
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
(0, import_vitest.test)("should throw helpful error when user data directory cannot be found", async () => {
|
|
94
|
+
fs.writeFileSync(
|
|
95
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
96
|
+
JSON.stringify({ projectId, orgId: teamId })
|
|
97
|
+
);
|
|
98
|
+
import_vitest.vi.mocked(import_token_io.getUserDataDir).mockReturnValue(null);
|
|
99
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
100
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(
|
|
101
|
+
/Unable to find user data directory\. Please reach out to Vercel support\./
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
(0, import_vitest.test)("should throw helpful error when API returns non-200", async () => {
|
|
105
|
+
fs.writeFileSync(
|
|
106
|
+
path.join(cliDataDir, "auth.json"),
|
|
107
|
+
JSON.stringify({ token: "test-auth-token" })
|
|
108
|
+
);
|
|
109
|
+
fs.writeFileSync(
|
|
110
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
111
|
+
JSON.stringify({ projectId, orgId: teamId })
|
|
112
|
+
);
|
|
113
|
+
import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockRejectedValue(
|
|
114
|
+
new Error("Failed to refresh OIDC token: Unauthorized")
|
|
115
|
+
);
|
|
116
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
117
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(
|
|
118
|
+
/Failed to refresh OIDC token: Unauthorized/
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
(0, import_vitest.test)("should throw helpful error when token response is malformed", async () => {
|
|
122
|
+
fs.writeFileSync(
|
|
123
|
+
path.join(cliDataDir, "auth.json"),
|
|
124
|
+
JSON.stringify({ token: "test-auth-token" })
|
|
125
|
+
);
|
|
126
|
+
fs.writeFileSync(
|
|
127
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
128
|
+
JSON.stringify({ projectId, orgId: teamId })
|
|
129
|
+
);
|
|
130
|
+
import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockRejectedValue(
|
|
131
|
+
new TypeError(
|
|
132
|
+
"Vercel OIDC token is malformed. Expected a string-valued token property. Please run `vc env pull` and try again"
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
136
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(
|
|
137
|
+
/Vercel OIDC token is malformed\. Expected a string-valued token property\. Please run `vc env pull` and try again/
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
(0, import_vitest.test)("should throw helpful error when token has invalid format", async () => {
|
|
141
|
+
process.env.VERCEL_OIDC_TOKEN = "not-a-valid-jwt-token";
|
|
142
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockImplementation(() => {
|
|
143
|
+
throw new Error("Invalid token. Please run `vc env pull` and try again");
|
|
144
|
+
});
|
|
145
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(
|
|
146
|
+
/Invalid token\. Please run `vc env pull` and try again/
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
(0, import_vitest.test)("should throw error when token expiry check fails", async () => {
|
|
150
|
+
process.env.VERCEL_OIDC_TOKEN = "not-a-jwt-token";
|
|
151
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(
|
|
152
|
+
/Invalid token\. Please run `vc env pull` and try again/
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
(0, import_vitest.test)("should fail when no token exists and no CLI credentials available", async () => {
|
|
156
|
+
process.env.VERCEL_OIDC_TOKEN = void 0;
|
|
157
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(/Invalid token/);
|
|
158
|
+
});
|
|
159
|
+
(0, import_vitest.test)("should propagate filesystem errors when saving token fails", async () => {
|
|
160
|
+
fs.writeFileSync(
|
|
161
|
+
path.join(cliDataDir, "auth.json"),
|
|
162
|
+
JSON.stringify({ token: "test-auth-token" })
|
|
163
|
+
);
|
|
164
|
+
fs.writeFileSync(
|
|
165
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
166
|
+
JSON.stringify({ projectId, orgId: teamId })
|
|
167
|
+
);
|
|
168
|
+
import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({
|
|
169
|
+
token: "new-valid-token"
|
|
170
|
+
});
|
|
171
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValue({
|
|
172
|
+
sub: "test-sub",
|
|
173
|
+
name: "test-name",
|
|
174
|
+
exp: Date.now() / 1e3 - 1e3
|
|
175
|
+
});
|
|
176
|
+
import_vitest.vi.spyOn(tokenUtil, "saveToken").mockImplementation(() => {
|
|
177
|
+
throw new Error("EACCES: permission denied");
|
|
178
|
+
});
|
|
179
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
180
|
+
await (0, import_vitest.expect)((0, import_get_vercel_oidc_token.getVercelOidcToken)()).rejects.toThrow(/EACCES|permission/i);
|
|
181
|
+
});
|
|
182
|
+
(0, import_vitest.test)("should succeed when valid token exists in env", async () => {
|
|
183
|
+
const validToken = createValidToken();
|
|
184
|
+
process.env.VERCEL_OIDC_TOKEN = validToken;
|
|
185
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValue({
|
|
186
|
+
sub: "test-sub",
|
|
187
|
+
name: "test-name",
|
|
188
|
+
exp: Date.now() / 1e3 + 43200
|
|
189
|
+
});
|
|
190
|
+
const token = await (0, import_get_vercel_oidc_token.getVercelOidcToken)();
|
|
191
|
+
(0, import_vitest.expect)(token).toBe(validToken);
|
|
192
|
+
});
|
|
193
|
+
(0, import_vitest.test)("should refresh when token is expired but all configs are valid", async () => {
|
|
194
|
+
fs.writeFileSync(
|
|
195
|
+
path.join(cliDataDir, "auth.json"),
|
|
196
|
+
JSON.stringify({ token: "test-auth-token" })
|
|
197
|
+
);
|
|
198
|
+
fs.writeFileSync(
|
|
199
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
200
|
+
JSON.stringify({ projectId, orgId: teamId })
|
|
201
|
+
);
|
|
202
|
+
const newToken = createValidToken("new-token");
|
|
203
|
+
import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({
|
|
204
|
+
token: newToken
|
|
205
|
+
});
|
|
206
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValueOnce({
|
|
207
|
+
sub: "test-sub",
|
|
208
|
+
name: "test-name",
|
|
209
|
+
exp: Date.now() / 1e3 - 1e3
|
|
210
|
+
}).mockReturnValue({
|
|
211
|
+
sub: "test-sub",
|
|
212
|
+
name: "test-name",
|
|
213
|
+
exp: Date.now() / 1e3 + 43200
|
|
214
|
+
});
|
|
215
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
216
|
+
const token = await (0, import_get_vercel_oidc_token.getVercelOidcToken)();
|
|
217
|
+
(0, import_vitest.expect)(token).toBe(newToken);
|
|
218
|
+
});
|
|
219
|
+
(0, import_vitest.test)("should use provided team and project for refresh instead of reading project.json", async () => {
|
|
220
|
+
const customProjectId = "prj_custom123";
|
|
221
|
+
const customTeamId = "team_custom456";
|
|
222
|
+
fs.writeFileSync(
|
|
223
|
+
path.join(cliDataDir, "auth.json"),
|
|
224
|
+
JSON.stringify({ token: "test-auth-token" })
|
|
225
|
+
);
|
|
226
|
+
const newToken = createValidToken("custom-token");
|
|
227
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({
|
|
228
|
+
token: newToken
|
|
229
|
+
});
|
|
230
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValueOnce({
|
|
231
|
+
sub: "test-sub",
|
|
232
|
+
name: "test-name",
|
|
233
|
+
exp: Date.now() / 1e3 - 1e3
|
|
234
|
+
}).mockReturnValue({
|
|
235
|
+
sub: "test-sub",
|
|
236
|
+
name: "test-name",
|
|
237
|
+
exp: Date.now() / 1e3 + 43200
|
|
238
|
+
});
|
|
239
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
240
|
+
const token = await (0, import_get_vercel_oidc_token.getVercelOidcToken)({
|
|
241
|
+
team: customTeamId,
|
|
242
|
+
project: customProjectId
|
|
243
|
+
});
|
|
244
|
+
(0, import_vitest.expect)(token).toBe(newToken);
|
|
245
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).toHaveBeenCalledWith(
|
|
246
|
+
"test-auth-token",
|
|
247
|
+
customProjectId,
|
|
248
|
+
customTeamId
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
(0, import_vitest.test)("should use provided project and read team from project.json", async () => {
|
|
252
|
+
const customProjectId = "prj_custom234";
|
|
253
|
+
fs.writeFileSync(
|
|
254
|
+
path.join(cliDataDir, "auth.json"),
|
|
255
|
+
JSON.stringify({ token: "test-auth-token" })
|
|
256
|
+
);
|
|
257
|
+
fs.writeFileSync(
|
|
258
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
259
|
+
JSON.stringify({ projectId: "original-project-id", orgId: teamId })
|
|
260
|
+
);
|
|
261
|
+
const newToken = createValidToken("partial-custom-token");
|
|
262
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({
|
|
263
|
+
token: newToken
|
|
264
|
+
});
|
|
265
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValueOnce({
|
|
266
|
+
sub: "test-sub",
|
|
267
|
+
name: "test-name",
|
|
268
|
+
exp: Date.now() / 1e3 - 1e3
|
|
269
|
+
}).mockReturnValue({
|
|
270
|
+
sub: "test-sub",
|
|
271
|
+
name: "test-name",
|
|
272
|
+
exp: Date.now() / 1e3 + 43200
|
|
273
|
+
});
|
|
274
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
275
|
+
const token = await (0, import_get_vercel_oidc_token.getVercelOidcToken)({
|
|
276
|
+
project: customProjectId
|
|
277
|
+
});
|
|
278
|
+
(0, import_vitest.expect)(token).toBe(newToken);
|
|
279
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).toHaveBeenCalledWith(
|
|
280
|
+
"test-auth-token",
|
|
281
|
+
customProjectId,
|
|
282
|
+
teamId
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
(0, import_vitest.test)("should use provided team and read project from project.json", async () => {
|
|
286
|
+
const customTeamId = "team_custom789";
|
|
287
|
+
fs.writeFileSync(
|
|
288
|
+
path.join(cliDataDir, "auth.json"),
|
|
289
|
+
JSON.stringify({ token: "test-auth-token" })
|
|
290
|
+
);
|
|
291
|
+
fs.writeFileSync(
|
|
292
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
293
|
+
JSON.stringify({ projectId, orgId: "original-team-id" })
|
|
294
|
+
);
|
|
295
|
+
const newToken = createValidToken("partial-custom-token-2");
|
|
296
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({
|
|
297
|
+
token: newToken
|
|
298
|
+
});
|
|
299
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValueOnce({
|
|
300
|
+
sub: "test-sub",
|
|
301
|
+
name: "test-name",
|
|
302
|
+
exp: Date.now() / 1e3 - 1e3
|
|
303
|
+
}).mockReturnValue({
|
|
304
|
+
sub: "test-sub",
|
|
305
|
+
name: "test-name",
|
|
306
|
+
exp: Date.now() / 1e3 + 43200
|
|
307
|
+
});
|
|
308
|
+
process.env.VERCEL_OIDC_TOKEN = createExpiredToken();
|
|
309
|
+
const token = await (0, import_get_vercel_oidc_token.getVercelOidcToken)({
|
|
310
|
+
team: customTeamId
|
|
311
|
+
});
|
|
312
|
+
(0, import_vitest.expect)(token).toBe(newToken);
|
|
313
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).toHaveBeenCalledWith(
|
|
314
|
+
"test-auth-token",
|
|
315
|
+
projectId,
|
|
316
|
+
customTeamId
|
|
317
|
+
);
|
|
318
|
+
});
|
|
319
|
+
(0, import_vitest.test)("should not refresh when token is valid even with options provided", async () => {
|
|
320
|
+
const validToken = createValidToken();
|
|
321
|
+
process.env.VERCEL_OIDC_TOKEN = validToken;
|
|
322
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({
|
|
323
|
+
token: "should-not-be-called"
|
|
324
|
+
});
|
|
325
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValue({
|
|
326
|
+
sub: "test-sub",
|
|
327
|
+
name: "test-name",
|
|
328
|
+
exp: Date.now() / 1e3 + 43200
|
|
329
|
+
});
|
|
330
|
+
const token = await (0, import_get_vercel_oidc_token.getVercelOidcToken)({
|
|
331
|
+
team: "custom-team",
|
|
332
|
+
project: "custom-project"
|
|
333
|
+
});
|
|
334
|
+
(0, import_vitest.expect)(token).toBe(validToken);
|
|
335
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).not.toHaveBeenCalled();
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
function createExpiredToken() {
|
|
339
|
+
const header = Buffer.from(
|
|
340
|
+
JSON.stringify({ alg: "RS256", typ: "JWT" })
|
|
341
|
+
).toString("base64url");
|
|
342
|
+
const payload = Buffer.from(
|
|
343
|
+
JSON.stringify({
|
|
344
|
+
sub: "test-sub",
|
|
345
|
+
exp: 1,
|
|
346
|
+
iat: 1
|
|
347
|
+
})
|
|
348
|
+
).toString("base64url");
|
|
349
|
+
return `${header}.${payload}.fake_signature`;
|
|
350
|
+
}
|
|
351
|
+
function createValidToken(value = "valid-token") {
|
|
352
|
+
const header = Buffer.from(
|
|
353
|
+
JSON.stringify({ alg: "RS256", typ: "JWT" })
|
|
354
|
+
).toString("base64url");
|
|
355
|
+
const payload = Buffer.from(
|
|
356
|
+
JSON.stringify({
|
|
357
|
+
sub: "test-sub",
|
|
358
|
+
exp: Math.floor(Date.now() / 1e3) + 43200,
|
|
359
|
+
iat: Math.floor(Date.now() / 1e3)
|
|
360
|
+
})
|
|
361
|
+
).toString("base64url");
|
|
362
|
+
return `${header}.${payload}.fake_signature_${value}`;
|
|
363
|
+
}
|
package/dist/index-browser.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { getContext } from './get-context';
|
|
2
|
+
export { AccessTokenMissingError, RefreshAccessTokenFailedError, } from './auth-errors';
|
|
2
3
|
export declare function getVercelOidcToken(): Promise<string>;
|
|
3
4
|
export declare function getVercelOidcTokenSync(): string;
|
|
5
|
+
export declare function getVercelToken(): Promise<string>;
|
package/dist/index-browser.js
CHANGED
|
@@ -18,21 +18,31 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var index_browser_exports = {};
|
|
20
20
|
__export(index_browser_exports, {
|
|
21
|
+
AccessTokenMissingError: () => import_auth_errors.AccessTokenMissingError,
|
|
22
|
+
RefreshAccessTokenFailedError: () => import_auth_errors.RefreshAccessTokenFailedError,
|
|
21
23
|
getContext: () => import_get_context.getContext,
|
|
22
24
|
getVercelOidcToken: () => getVercelOidcToken,
|
|
23
|
-
getVercelOidcTokenSync: () => getVercelOidcTokenSync
|
|
25
|
+
getVercelOidcTokenSync: () => getVercelOidcTokenSync,
|
|
26
|
+
getVercelToken: () => getVercelToken
|
|
24
27
|
});
|
|
25
28
|
module.exports = __toCommonJS(index_browser_exports);
|
|
26
29
|
var import_get_context = require("./get-context");
|
|
30
|
+
var import_auth_errors = require("./auth-errors");
|
|
27
31
|
async function getVercelOidcToken() {
|
|
28
32
|
return "";
|
|
29
33
|
}
|
|
30
34
|
function getVercelOidcTokenSync() {
|
|
31
35
|
return "";
|
|
32
36
|
}
|
|
37
|
+
async function getVercelToken() {
|
|
38
|
+
throw new Error("getVercelToken is not supported in browser environments");
|
|
39
|
+
}
|
|
33
40
|
// Annotate the CommonJS export names for ESM import in node:
|
|
34
41
|
0 && (module.exports = {
|
|
42
|
+
AccessTokenMissingError,
|
|
43
|
+
RefreshAccessTokenFailedError,
|
|
35
44
|
getContext,
|
|
36
45
|
getVercelOidcToken,
|
|
37
|
-
getVercelOidcTokenSync
|
|
46
|
+
getVercelOidcTokenSync,
|
|
47
|
+
getVercelToken
|
|
38
48
|
});
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -18,16 +18,24 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var src_exports = {};
|
|
20
20
|
__export(src_exports, {
|
|
21
|
+
AccessTokenMissingError: () => import_auth_errors.AccessTokenMissingError,
|
|
22
|
+
RefreshAccessTokenFailedError: () => import_auth_errors.RefreshAccessTokenFailedError,
|
|
21
23
|
getContext: () => import_get_context.getContext,
|
|
22
24
|
getVercelOidcToken: () => import_get_vercel_oidc_token.getVercelOidcToken,
|
|
23
|
-
getVercelOidcTokenSync: () => import_get_vercel_oidc_token.getVercelOidcTokenSync
|
|
25
|
+
getVercelOidcTokenSync: () => import_get_vercel_oidc_token.getVercelOidcTokenSync,
|
|
26
|
+
getVercelToken: () => import_token_util.getVercelToken
|
|
24
27
|
});
|
|
25
28
|
module.exports = __toCommonJS(src_exports);
|
|
26
29
|
var import_get_vercel_oidc_token = require("./get-vercel-oidc-token");
|
|
27
30
|
var import_get_context = require("./get-context");
|
|
31
|
+
var import_auth_errors = require("./auth-errors");
|
|
32
|
+
var import_token_util = require("./token-util");
|
|
28
33
|
// Annotate the CommonJS export names for ESM import in node:
|
|
29
34
|
0 && (module.exports = {
|
|
35
|
+
AccessTokenMissingError,
|
|
36
|
+
RefreshAccessTokenFailedError,
|
|
30
37
|
getContext,
|
|
31
38
|
getVercelOidcToken,
|
|
32
|
-
getVercelOidcTokenSync
|
|
39
|
+
getVercelOidcTokenSync,
|
|
40
|
+
getVercelToken
|
|
33
41
|
});
|
package/dist/oauth.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface TokenSet {
|
|
2
|
+
access_token: string;
|
|
3
|
+
token_type: 'Bearer';
|
|
4
|
+
expires_in: number;
|
|
5
|
+
refresh_token?: string;
|
|
6
|
+
scope?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Refresh an OAuth access token using a refresh token
|
|
10
|
+
*/
|
|
11
|
+
export declare function refreshTokenRequest(options: {
|
|
12
|
+
refresh_token: string;
|
|
13
|
+
}): Promise<Response>;
|
|
14
|
+
/**
|
|
15
|
+
* Process the token response and extract the token set
|
|
16
|
+
*/
|
|
17
|
+
export declare function processTokenResponse(response: Response): Promise<[Error] | [null, TokenSet]>;
|
package/dist/oauth.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var oauth_exports = {};
|
|
20
|
+
__export(oauth_exports, {
|
|
21
|
+
processTokenResponse: () => processTokenResponse,
|
|
22
|
+
refreshTokenRequest: () => refreshTokenRequest
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(oauth_exports);
|
|
25
|
+
var import_os = require("os");
|
|
26
|
+
const VERCEL_ISSUER = "https://vercel.com";
|
|
27
|
+
const VERCEL_CLI_CLIENT_ID = "cl_HYyOPBNtFMfHhaUn9L4QPfTZz6TP47bp";
|
|
28
|
+
const userAgent = `@vercel/oidc node-${process.version} ${(0, import_os.platform)()} (${(0, import_os.arch)()}) ${(0, import_os.hostname)()}`;
|
|
29
|
+
let _tokenEndpoint = null;
|
|
30
|
+
async function getTokenEndpoint() {
|
|
31
|
+
if (_tokenEndpoint) {
|
|
32
|
+
return _tokenEndpoint;
|
|
33
|
+
}
|
|
34
|
+
const discoveryUrl = `${VERCEL_ISSUER}/.well-known/openid-configuration`;
|
|
35
|
+
const response = await fetch(discoveryUrl, {
|
|
36
|
+
headers: { "user-agent": userAgent }
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new Error("Failed to discover OAuth endpoints");
|
|
40
|
+
}
|
|
41
|
+
const metadata = await response.json();
|
|
42
|
+
if (!metadata || typeof metadata.token_endpoint !== "string") {
|
|
43
|
+
throw new Error("Invalid OAuth discovery response");
|
|
44
|
+
}
|
|
45
|
+
const endpoint = metadata.token_endpoint;
|
|
46
|
+
_tokenEndpoint = endpoint;
|
|
47
|
+
return endpoint;
|
|
48
|
+
}
|
|
49
|
+
async function refreshTokenRequest(options) {
|
|
50
|
+
const tokenEndpoint = await getTokenEndpoint();
|
|
51
|
+
return await fetch(tokenEndpoint, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: {
|
|
54
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
55
|
+
"user-agent": userAgent
|
|
56
|
+
},
|
|
57
|
+
body: new URLSearchParams({
|
|
58
|
+
client_id: VERCEL_CLI_CLIENT_ID,
|
|
59
|
+
grant_type: "refresh_token",
|
|
60
|
+
...options
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async function processTokenResponse(response) {
|
|
65
|
+
const json = await response.json();
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const errorMsg = typeof json === "object" && json && "error" in json ? String(json.error) : "Token refresh failed";
|
|
68
|
+
return [new Error(errorMsg)];
|
|
69
|
+
}
|
|
70
|
+
if (typeof json !== "object" || json === null) {
|
|
71
|
+
return [new Error("Invalid token response")];
|
|
72
|
+
}
|
|
73
|
+
if (typeof json.access_token !== "string") {
|
|
74
|
+
return [new Error("Missing access_token in response")];
|
|
75
|
+
}
|
|
76
|
+
if (json.token_type !== "Bearer") {
|
|
77
|
+
return [new Error("Invalid token_type in response")];
|
|
78
|
+
}
|
|
79
|
+
if (typeof json.expires_in !== "number") {
|
|
80
|
+
return [new Error("Missing expires_in in response")];
|
|
81
|
+
}
|
|
82
|
+
return [null, json];
|
|
83
|
+
}
|
|
84
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
85
|
+
0 && (module.exports = {
|
|
86
|
+
processTokenResponse,
|
|
87
|
+
refreshTokenRequest
|
|
88
|
+
});
|
package/dist/token-io.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function findRootDir(): string;
|
|
1
|
+
export declare function findRootDir(): string | null;
|
|
2
2
|
export declare function getUserDataDir(): string | null;
|
package/dist/token-io.js
CHANGED
|
@@ -51,7 +51,7 @@ function findRootDir() {
|
|
|
51
51
|
"Token refresh only supported in node server environments"
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
return null;
|
|
55
55
|
}
|
|
56
56
|
function getUserDataDir() {
|
|
57
57
|
if (process.env.XDG_DATA_HOME) {
|
package/dist/token-util.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
export declare function getVercelDataDir(): string | null;
|
|
2
|
-
export
|
|
2
|
+
export interface GetVercelTokenOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Optional time buffer in milliseconds before token expiry to consider it expired.
|
|
5
|
+
* When provided, the token will be refreshed if it expires within this buffer time.
|
|
6
|
+
* @default 0
|
|
7
|
+
*/
|
|
8
|
+
expirationBufferMs?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function getVercelToken(options?: GetVercelTokenOptions): Promise<string>;
|
|
3
11
|
interface VercelTokenResponse {
|
|
4
12
|
token: string;
|
|
5
13
|
}
|
|
@@ -17,5 +25,5 @@ interface TokenPayload {
|
|
|
17
25
|
exp: number;
|
|
18
26
|
}
|
|
19
27
|
export declare function getTokenPayload(token: string): TokenPayload;
|
|
20
|
-
export declare function isExpired(token: TokenPayload): boolean;
|
|
28
|
+
export declare function isExpired(token: TokenPayload, bufferMs?: number): boolean;
|
|
21
29
|
export {};
|