@vercel/oidc 3.1.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +38 -0
- package/dist/auth-config.d.ts +1 -1
- package/dist/auth-config.js +4 -3
- 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 +3 -3
- package/dist/get-vercel-oidc-token.test.js +122 -4
- 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/token-io.js +1 -1
- package/dist/token-util.d.ts +10 -2
- package/dist/token-util.js +17 -13
- package/dist/token-util.test.js +22 -19
- 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 +3 -3
package/dist/token-util.test.js
CHANGED
|
@@ -25,12 +25,13 @@ var import_vitest = require("vitest");
|
|
|
25
25
|
var import_token_util = require("./token-util");
|
|
26
26
|
var authConfig = __toESM(require("./auth-config"));
|
|
27
27
|
var oauth = __toESM(require("./oauth"));
|
|
28
|
+
var import_auth_errors = require("./auth-errors");
|
|
28
29
|
import_vitest.vi.mock("fs");
|
|
29
30
|
import_vitest.vi.mock("./token-io", () => ({
|
|
30
31
|
getUserDataDir: import_vitest.vi.fn(() => "/mock/user/data"),
|
|
31
32
|
findRootDir: import_vitest.vi.fn(() => "/mock/root")
|
|
32
33
|
}));
|
|
33
|
-
(0, import_vitest.describe)("
|
|
34
|
+
(0, import_vitest.describe)("getVercelToken", () => {
|
|
34
35
|
(0, import_vitest.beforeEach)(() => {
|
|
35
36
|
import_vitest.vi.clearAllMocks();
|
|
36
37
|
});
|
|
@@ -47,14 +48,13 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
47
48
|
import_vitest.vi.spyOn(authConfig, "readAuthConfig").mockReturnValue(validToken);
|
|
48
49
|
import_vitest.vi.spyOn(authConfig, "writeAuthConfig").mockImplementation(() => {
|
|
49
50
|
});
|
|
50
|
-
const token = await (0, import_token_util.
|
|
51
|
+
const token = await (0, import_token_util.getVercelToken)();
|
|
51
52
|
(0, import_vitest.expect)(token).toBe("valid-access-token");
|
|
52
53
|
(0, import_vitest.expect)(authConfig.writeAuthConfig).not.toHaveBeenCalled();
|
|
53
54
|
});
|
|
54
|
-
(0, import_vitest.it)("should
|
|
55
|
+
(0, import_vitest.it)("should throw AccessTokenMissingError if auth config does not exist", async () => {
|
|
55
56
|
import_vitest.vi.spyOn(authConfig, "readAuthConfig").mockReturnValue(null);
|
|
56
|
-
|
|
57
|
-
(0, import_vitest.expect)(token).toBeNull();
|
|
57
|
+
await (0, import_vitest.expect)((0, import_token_util.getVercelToken)()).rejects.toThrow(import_auth_errors.AccessTokenMissingError);
|
|
58
58
|
});
|
|
59
59
|
(0, import_vitest.it)("should refresh token if expired and refresh token exists", async () => {
|
|
60
60
|
const expiredToken = {
|
|
@@ -76,7 +76,7 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
76
76
|
import_vitest.vi.spyOn(authConfig, "writeAuthConfig").mockImplementation(() => {
|
|
77
77
|
});
|
|
78
78
|
import_vitest.vi.spyOn(oauth, "refreshTokenRequest").mockResolvedValue(mockResponse);
|
|
79
|
-
const token = await (0, import_token_util.
|
|
79
|
+
const token = await (0, import_token_util.getVercelToken)();
|
|
80
80
|
(0, import_vitest.expect)(token).toBe("new-access-token");
|
|
81
81
|
(0, import_vitest.expect)(oauth.refreshTokenRequest).toHaveBeenCalledWith({
|
|
82
82
|
refresh_token: "valid-refresh-token"
|
|
@@ -89,7 +89,7 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
89
89
|
})
|
|
90
90
|
);
|
|
91
91
|
});
|
|
92
|
-
(0, import_vitest.it)("should clear auth and
|
|
92
|
+
(0, import_vitest.it)("should clear auth and throw RefreshAccessTokenFailedError if token expired and no refresh token", async () => {
|
|
93
93
|
const expiredTokenNoRefresh = {
|
|
94
94
|
token: "expired-access-token",
|
|
95
95
|
expiresAt: Math.floor(Date.now() / 1e3) - 3600
|
|
@@ -99,11 +99,12 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
99
99
|
);
|
|
100
100
|
import_vitest.vi.spyOn(authConfig, "writeAuthConfig").mockImplementation(() => {
|
|
101
101
|
});
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
await (0, import_vitest.expect)((0, import_token_util.getVercelToken)()).rejects.toThrow(
|
|
103
|
+
import_auth_errors.RefreshAccessTokenFailedError
|
|
104
|
+
);
|
|
104
105
|
(0, import_vitest.expect)(authConfig.writeAuthConfig).toHaveBeenCalledWith({});
|
|
105
106
|
});
|
|
106
|
-
(0, import_vitest.it)("should clear auth if refresh fails with OAuth error", async () => {
|
|
107
|
+
(0, import_vitest.it)("should clear auth and throw RefreshAccessTokenFailedError if refresh fails with OAuth error", async () => {
|
|
107
108
|
const expiredToken = {
|
|
108
109
|
token: "expired-access-token",
|
|
109
110
|
refreshToken: "invalid-refresh-token",
|
|
@@ -120,11 +121,12 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
120
121
|
import_vitest.vi.spyOn(authConfig, "writeAuthConfig").mockImplementation(() => {
|
|
121
122
|
});
|
|
122
123
|
import_vitest.vi.spyOn(oauth, "refreshTokenRequest").mockResolvedValue(mockErrorResponse);
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
await (0, import_vitest.expect)((0, import_token_util.getVercelToken)()).rejects.toThrow(
|
|
125
|
+
import_auth_errors.RefreshAccessTokenFailedError
|
|
126
|
+
);
|
|
125
127
|
(0, import_vitest.expect)(authConfig.writeAuthConfig).toHaveBeenCalledWith({});
|
|
126
128
|
});
|
|
127
|
-
(0, import_vitest.it)("should clear auth if refresh fails with network error", async () => {
|
|
129
|
+
(0, import_vitest.it)("should clear auth and throw RefreshAccessTokenFailedError if refresh fails with network error", async () => {
|
|
128
130
|
const expiredToken = {
|
|
129
131
|
token: "expired-access-token",
|
|
130
132
|
refreshToken: "valid-refresh-token",
|
|
@@ -136,8 +138,9 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
136
138
|
import_vitest.vi.spyOn(oauth, "refreshTokenRequest").mockRejectedValue(
|
|
137
139
|
new Error("Network error")
|
|
138
140
|
);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
await (0, import_vitest.expect)((0, import_token_util.getVercelToken)()).rejects.toThrow(
|
|
142
|
+
import_auth_errors.RefreshAccessTokenFailedError
|
|
143
|
+
);
|
|
141
144
|
(0, import_vitest.expect)(authConfig.writeAuthConfig).toHaveBeenCalledWith({});
|
|
142
145
|
});
|
|
143
146
|
(0, import_vitest.it)("should treat token as valid if expiresAt is missing (--token case)", async () => {
|
|
@@ -147,7 +150,7 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
147
150
|
import_vitest.vi.spyOn(authConfig, "readAuthConfig").mockReturnValue(tokenWithoutExpiry);
|
|
148
151
|
import_vitest.vi.spyOn(authConfig, "writeAuthConfig").mockImplementation(() => {
|
|
149
152
|
});
|
|
150
|
-
const token = await (0, import_token_util.
|
|
153
|
+
const token = await (0, import_token_util.getVercelToken)();
|
|
151
154
|
(0, import_vitest.expect)(token).toBe("cli-provided-token");
|
|
152
155
|
(0, import_vitest.expect)(authConfig.writeAuthConfig).not.toHaveBeenCalled();
|
|
153
156
|
});
|
|
@@ -170,7 +173,7 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
170
173
|
import_vitest.vi.spyOn(authConfig, "writeAuthConfig").mockImplementation(() => {
|
|
171
174
|
});
|
|
172
175
|
import_vitest.vi.spyOn(oauth, "refreshTokenRequest").mockResolvedValue(mockResponse);
|
|
173
|
-
await (0, import_token_util.
|
|
176
|
+
await (0, import_token_util.getVercelToken)();
|
|
174
177
|
(0, import_vitest.expect)(authConfig.writeAuthConfig).toHaveBeenCalledWith(
|
|
175
178
|
import_vitest.expect.objectContaining({
|
|
176
179
|
refreshToken: "new-refresh-token"
|
|
@@ -196,7 +199,7 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
196
199
|
import_vitest.vi.spyOn(authConfig, "writeAuthConfig").mockImplementation(() => {
|
|
197
200
|
});
|
|
198
201
|
import_vitest.vi.spyOn(oauth, "refreshTokenRequest").mockResolvedValue(mockResponse);
|
|
199
|
-
await (0, import_token_util.
|
|
202
|
+
await (0, import_token_util.getVercelToken)();
|
|
200
203
|
const writeCall = import_vitest.vi.mocked(authConfig.writeAuthConfig).mock.calls[0][0];
|
|
201
204
|
(0, import_vitest.expect)(writeCall).not.toHaveProperty("refreshToken");
|
|
202
205
|
});
|
|
@@ -220,7 +223,7 @@ import_vitest.vi.mock("./token-io", () => ({
|
|
|
220
223
|
});
|
|
221
224
|
import_vitest.vi.spyOn(oauth, "refreshTokenRequest").mockResolvedValue(mockResponse);
|
|
222
225
|
const beforeCall = Math.floor(Date.now() / 1e3);
|
|
223
|
-
await (0, import_token_util.
|
|
226
|
+
await (0, import_token_util.getVercelToken)();
|
|
224
227
|
const afterCall = Math.floor(Date.now() / 1e3);
|
|
225
228
|
const writeCall = import_vitest.vi.mocked(authConfig.writeAuthConfig).mock.calls[0][0];
|
|
226
229
|
(0, import_vitest.expect)(writeCall.expiresAt).toBeGreaterThanOrEqual(beforeCall + 7200);
|
package/dist/token.d.ts
CHANGED
|
@@ -1 +1,19 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface RefreshTokenOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Team ID (team_*) or slug to use for token refresh.
|
|
4
|
+
* When provided, this team will be used instead of reading from `.vercel/project.json`.
|
|
5
|
+
*/
|
|
6
|
+
team?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Project ID (prj_*) or slug to use for token refresh.
|
|
9
|
+
* When provided, this project will be used instead of reading from `.vercel/project.json`.
|
|
10
|
+
*/
|
|
11
|
+
project?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Optional time buffer in milliseconds before token expiry to consider it expired.
|
|
14
|
+
* When provided, the token will be refreshed if it expires within this buffer time.
|
|
15
|
+
* @default 0
|
|
16
|
+
*/
|
|
17
|
+
expirationBufferMs?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function refreshToken(options?: RefreshTokenOptions): Promise<void>;
|
package/dist/token.js
CHANGED
|
@@ -23,21 +23,28 @@ __export(token_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(token_exports);
|
|
24
24
|
var import_token_error = require("./token-error");
|
|
25
25
|
var import_token_util = require("./token-util");
|
|
26
|
-
async function refreshToken() {
|
|
27
|
-
|
|
26
|
+
async function refreshToken(options) {
|
|
27
|
+
let projectId = options?.project;
|
|
28
|
+
let teamId = options?.team;
|
|
29
|
+
if (!projectId && !teamId) {
|
|
30
|
+
const projectInfo = (0, import_token_util.findProjectInfo)();
|
|
31
|
+
projectId = projectInfo.projectId;
|
|
32
|
+
teamId = projectInfo.teamId;
|
|
33
|
+
} else if (!projectId || !teamId) {
|
|
34
|
+
const projectInfo = (0, import_token_util.findProjectInfo)();
|
|
35
|
+
projectId = projectId ?? projectInfo.projectId;
|
|
36
|
+
teamId = teamId ?? projectInfo.teamId;
|
|
37
|
+
}
|
|
38
|
+
if (!projectId) {
|
|
39
|
+
throw new import_token_error.VercelOidcTokenError(
|
|
40
|
+
"Failed to refresh OIDC token: No project specified. Try re-linking your project with `vc link`"
|
|
41
|
+
);
|
|
42
|
+
}
|
|
28
43
|
let maybeToken = (0, import_token_util.loadToken)(projectId);
|
|
29
|
-
if (!maybeToken || (0, import_token_util.isExpired)((0, import_token_util.getTokenPayload)(maybeToken.token))) {
|
|
30
|
-
const authToken = await (0, import_token_util.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"Failed to refresh OIDC token: Log in to Vercel CLI and link your project with `vc link`"
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
if (!projectId) {
|
|
37
|
-
throw new import_token_error.VercelOidcTokenError(
|
|
38
|
-
"Failed to refresh OIDC token: Try re-linking your project with `vc link`"
|
|
39
|
-
);
|
|
40
|
-
}
|
|
44
|
+
if (!maybeToken || (0, import_token_util.isExpired)((0, import_token_util.getTokenPayload)(maybeToken.token), options?.expirationBufferMs)) {
|
|
45
|
+
const authToken = await (0, import_token_util.getVercelToken)({
|
|
46
|
+
expirationBufferMs: options?.expirationBufferMs
|
|
47
|
+
});
|
|
41
48
|
maybeToken = await (0, import_token_util.getVercelOidcToken)(authToken, projectId, teamId);
|
|
42
49
|
if (!maybeToken) {
|
|
43
50
|
throw new import_token_error.VercelOidcTokenError("Failed to refresh OIDC token");
|
package/dist/token.test.js
CHANGED
|
@@ -35,7 +35,7 @@ import_vitest.vi.mock("./token-io");
|
|
|
35
35
|
let userDataDir;
|
|
36
36
|
let cliDataDir;
|
|
37
37
|
let tokenDataDir;
|
|
38
|
-
const projectId = "
|
|
38
|
+
const projectId = "prj_test123";
|
|
39
39
|
(0, import_vitest.beforeEach)(() => {
|
|
40
40
|
import_vitest.vi.clearAllMocks();
|
|
41
41
|
process.env.VERCEL_OIDC_TOKEN = void 0;
|
|
@@ -57,7 +57,7 @@ import_vitest.vi.mock("./token-io");
|
|
|
57
57
|
import_vitest.vi.spyOn(process, "cwd").mockReturnValue(rootDir);
|
|
58
58
|
import_vitest.vi.mocked(import_token_io.findRootDir).mockReturnValue(rootDir);
|
|
59
59
|
import_vitest.vi.mocked(import_token_io.getUserDataDir).mockReturnValue(userDataDir);
|
|
60
|
-
import_vitest.vi.spyOn(tokenUtil, "
|
|
60
|
+
import_vitest.vi.spyOn(tokenUtil, "getVercelToken").mockResolvedValue("test");
|
|
61
61
|
import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({
|
|
62
62
|
token: "test-token"
|
|
63
63
|
});
|
|
@@ -81,4 +81,110 @@ import_vitest.vi.mock("./token-io");
|
|
|
81
81
|
const token = JSON.parse(fs.readFileSync(tokenPath, "utf8"));
|
|
82
82
|
(0, import_vitest.expect)(token).toEqual({ token: "test-token" });
|
|
83
83
|
});
|
|
84
|
+
(0, import_vitest.test)("should use provided team and project instead of reading project.json", async () => {
|
|
85
|
+
const customProjectId = "prj_custom123";
|
|
86
|
+
const customTeamId = "team_custom456";
|
|
87
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken");
|
|
88
|
+
const findRootDirSpy = import_vitest.vi.mocked(import_token_io.findRootDir);
|
|
89
|
+
await (0, import_token.refreshToken)({ team: customTeamId, project: customProjectId });
|
|
90
|
+
(0, import_vitest.expect)(findRootDirSpy).not.toHaveBeenCalled();
|
|
91
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).toHaveBeenCalledWith(
|
|
92
|
+
"test",
|
|
93
|
+
customProjectId,
|
|
94
|
+
customTeamId
|
|
95
|
+
);
|
|
96
|
+
const tokenPath = path.join(tokenDataDir, `${customProjectId}.json`);
|
|
97
|
+
(0, import_vitest.expect)(fs.existsSync(tokenPath)).toBe(true);
|
|
98
|
+
const savedToken = JSON.parse(fs.readFileSync(tokenPath, "utf8"));
|
|
99
|
+
(0, import_vitest.expect)(savedToken).toEqual({ token: "test-token" });
|
|
100
|
+
});
|
|
101
|
+
(0, import_vitest.test)("should merge provided project with team from project.json", async () => {
|
|
102
|
+
const customProjectId = "prj_custom234";
|
|
103
|
+
const projectTeamId = "team_fromproject567";
|
|
104
|
+
fs.writeFileSync(
|
|
105
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
106
|
+
JSON.stringify({ projectId, orgId: projectTeamId })
|
|
107
|
+
);
|
|
108
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken");
|
|
109
|
+
await (0, import_token.refreshToken)({ project: customProjectId });
|
|
110
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).toHaveBeenCalledWith(
|
|
111
|
+
"test",
|
|
112
|
+
customProjectId,
|
|
113
|
+
projectTeamId
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
(0, import_vitest.test)("should merge provided team with project from project.json", async () => {
|
|
117
|
+
const customTeamId = "team_custom789";
|
|
118
|
+
const projectProjectId = "prj_fromjson123";
|
|
119
|
+
fs.writeFileSync(
|
|
120
|
+
path.join(rootDir, ".vercel", "project.json"),
|
|
121
|
+
JSON.stringify({ projectId: projectProjectId, orgId: "original-team" })
|
|
122
|
+
);
|
|
123
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken");
|
|
124
|
+
await (0, import_token.refreshToken)({ team: customTeamId });
|
|
125
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).toHaveBeenCalledWith(
|
|
126
|
+
"test",
|
|
127
|
+
projectProjectId,
|
|
128
|
+
customTeamId
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
(0, import_vitest.test)("should use cached token when valid with custom project", async () => {
|
|
132
|
+
const customProjectId = "prj_customcached123";
|
|
133
|
+
const customTeamId = "team_customcached456";
|
|
134
|
+
const cachedToken = { token: "cached-valid-token" };
|
|
135
|
+
const tokenPath = path.join(tokenDataDir, `${customProjectId}.json`);
|
|
136
|
+
fs.writeFileSync(tokenPath, JSON.stringify(cachedToken));
|
|
137
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken");
|
|
138
|
+
await (0, import_token.refreshToken)({ team: customTeamId, project: customProjectId });
|
|
139
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).not.toHaveBeenCalled();
|
|
140
|
+
(0, import_vitest.expect)(process.env.VERCEL_OIDC_TOKEN).toBe("cached-valid-token");
|
|
141
|
+
});
|
|
142
|
+
(0, import_vitest.test)("should refresh token when cached token expires within buffer", async () => {
|
|
143
|
+
const customProjectId = "prj_buffertest123";
|
|
144
|
+
const customTeamId = "team_buffertest456";
|
|
145
|
+
const cachedToken = { token: "expiring-soon-token" };
|
|
146
|
+
const tokenPath = path.join(tokenDataDir, `${customProjectId}.json`);
|
|
147
|
+
fs.writeFileSync(tokenPath, JSON.stringify(cachedToken));
|
|
148
|
+
const expiresIn3Minutes = Math.floor((Date.now() + 18e4) / 1e3);
|
|
149
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValue({
|
|
150
|
+
sub: "test-sub",
|
|
151
|
+
name: "test-name",
|
|
152
|
+
exp: expiresIn3Minutes
|
|
153
|
+
});
|
|
154
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({ token: "fresh-token" });
|
|
155
|
+
await (0, import_token.refreshToken)({
|
|
156
|
+
team: customTeamId,
|
|
157
|
+
project: customProjectId,
|
|
158
|
+
expirationBufferMs: 3e5
|
|
159
|
+
});
|
|
160
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).toHaveBeenCalledWith(
|
|
161
|
+
"test",
|
|
162
|
+
customProjectId,
|
|
163
|
+
customTeamId
|
|
164
|
+
);
|
|
165
|
+
(0, import_vitest.expect)(process.env.VERCEL_OIDC_TOKEN).toBe("fresh-token");
|
|
166
|
+
const savedToken = JSON.parse(fs.readFileSync(tokenPath, "utf8"));
|
|
167
|
+
(0, import_vitest.expect)(savedToken).toEqual({ token: "fresh-token" });
|
|
168
|
+
});
|
|
169
|
+
(0, import_vitest.test)("should use cached token when it does not expire within buffer", async () => {
|
|
170
|
+
const customProjectId = "prj_buffervalid123";
|
|
171
|
+
const customTeamId = "team_buffervalid456";
|
|
172
|
+
const cachedToken = { token: "valid-cached-token" };
|
|
173
|
+
const tokenPath = path.join(tokenDataDir, `${customProjectId}.json`);
|
|
174
|
+
fs.writeFileSync(tokenPath, JSON.stringify(cachedToken));
|
|
175
|
+
const expiresIn10Minutes = Math.floor((Date.now() + 6e5) / 1e3);
|
|
176
|
+
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValue({
|
|
177
|
+
sub: "test-sub",
|
|
178
|
+
name: "test-name",
|
|
179
|
+
exp: expiresIn10Minutes
|
|
180
|
+
});
|
|
181
|
+
const getVercelOidcTokenSpy = import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken");
|
|
182
|
+
await (0, import_token.refreshToken)({
|
|
183
|
+
team: customTeamId,
|
|
184
|
+
project: customProjectId,
|
|
185
|
+
expirationBufferMs: 3e5
|
|
186
|
+
});
|
|
187
|
+
(0, import_vitest.expect)(getVercelOidcTokenSpy).not.toHaveBeenCalled();
|
|
188
|
+
(0, import_vitest.expect)(process.env.VERCEL_OIDC_TOKEN).toBe("valid-cached-token");
|
|
189
|
+
});
|
|
84
190
|
});
|
package/docs/README.md
CHANGED
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Table of contents
|
|
4
4
|
|
|
5
|
+
### Classes
|
|
6
|
+
|
|
7
|
+
- [AccessTokenMissingError](classes/AccessTokenMissingError.md)
|
|
8
|
+
- [RefreshAccessTokenFailedError](classes/RefreshAccessTokenFailedError.md)
|
|
9
|
+
|
|
5
10
|
### Functions
|
|
6
11
|
|
|
7
12
|
- [getContext](README.md#getcontext)
|
|
8
13
|
- [getVercelOidcToken](README.md#getverceloidctoken)
|
|
9
14
|
- [getVercelOidcTokenSync](README.md#getverceloidctokensync)
|
|
15
|
+
- [getVercelToken](README.md#getverceltoken)
|
|
10
16
|
|
|
11
17
|
## Functions
|
|
12
18
|
|
|
@@ -20,13 +26,13 @@
|
|
|
20
26
|
|
|
21
27
|
#### Defined in
|
|
22
28
|
|
|
23
|
-
[get-context.ts:7](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-context.ts#L7)
|
|
29
|
+
[packages/oidc/src/get-context.ts:7](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-context.ts#L7)
|
|
24
30
|
|
|
25
31
|
---
|
|
26
32
|
|
|
27
33
|
### getVercelOidcToken
|
|
28
34
|
|
|
29
|
-
▸ **getVercelOidcToken**(): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`string`\>
|
|
35
|
+
▸ **getVercelOidcToken**(`options?`): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`string`\>
|
|
30
36
|
|
|
31
37
|
Gets the current OIDC token from the request context or the environment variable.
|
|
32
38
|
|
|
@@ -56,6 +62,25 @@ getVercelOidcToken()
|
|
|
56
62
|
});
|
|
57
63
|
```
|
|
58
64
|
|
|
65
|
+
**`Example`**
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
// Using the OIDC token with explicit team and project (supports IDs and slugs)
|
|
69
|
+
getVercelOidcToken({ team: 'my-team', project: 'my-project' })
|
|
70
|
+
.then(token => {
|
|
71
|
+
console.log('OIDC Token:', token);
|
|
72
|
+
})
|
|
73
|
+
.catch(error => {
|
|
74
|
+
console.error('Error:', error.message);
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### Parameters
|
|
79
|
+
|
|
80
|
+
| Name | Type | Description |
|
|
81
|
+
| :--------- | :-------------------------- | :------------------------------------------ |
|
|
82
|
+
| `options?` | `GetVercelOidcTokenOptions` | Optional configuration for token retrieval. |
|
|
83
|
+
|
|
59
84
|
#### Returns
|
|
60
85
|
|
|
61
86
|
[`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`string`\>
|
|
@@ -64,7 +89,7 @@ A promise that resolves to the OIDC token.
|
|
|
64
89
|
|
|
65
90
|
#### Defined in
|
|
66
91
|
|
|
67
|
-
[get-vercel-oidc-token.ts:
|
|
92
|
+
[packages/oidc/src/get-vercel-oidc-token.ts:64](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-vercel-oidc-token.ts#L64)
|
|
68
93
|
|
|
69
94
|
---
|
|
70
95
|
|
|
@@ -101,4 +126,24 @@ The OIDC token.
|
|
|
101
126
|
|
|
102
127
|
#### Defined in
|
|
103
128
|
|
|
104
|
-
[get-vercel-oidc-token.ts:
|
|
129
|
+
[packages/oidc/src/get-vercel-oidc-token.ts:124](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-vercel-oidc-token.ts#L124)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### getVercelToken
|
|
134
|
+
|
|
135
|
+
▸ **getVercelToken**(`options?`): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`string`\>
|
|
136
|
+
|
|
137
|
+
#### Parameters
|
|
138
|
+
|
|
139
|
+
| Name | Type |
|
|
140
|
+
| :--------- | :---------------------- |
|
|
141
|
+
| `options?` | `GetVercelTokenOptions` |
|
|
142
|
+
|
|
143
|
+
#### Returns
|
|
144
|
+
|
|
145
|
+
[`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`string`\>
|
|
146
|
+
|
|
147
|
+
#### Defined in
|
|
148
|
+
|
|
149
|
+
[packages/oidc/src/token-util.ts:35](https://github.com/vercel/vercel/blob/main/packages/oidc/src/token-util.ts#L35)
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Class: AccessTokenMissingError
|
|
2
|
+
|
|
3
|
+
Error thrown when no authentication configuration is found.
|
|
4
|
+
This typically means the user needs to log in.
|
|
5
|
+
|
|
6
|
+
## Hierarchy
|
|
7
|
+
|
|
8
|
+
- [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
|
9
|
+
|
|
10
|
+
↳ **`AccessTokenMissingError`**
|
|
11
|
+
|
|
12
|
+
## Table of contents
|
|
13
|
+
|
|
14
|
+
### Constructors
|
|
15
|
+
|
|
16
|
+
- [constructor](AccessTokenMissingError.md#constructor)
|
|
17
|
+
|
|
18
|
+
### Properties
|
|
19
|
+
|
|
20
|
+
- [message](AccessTokenMissingError.md#message)
|
|
21
|
+
- [name](AccessTokenMissingError.md#name)
|
|
22
|
+
- [stack](AccessTokenMissingError.md#stack)
|
|
23
|
+
- [prepareStackTrace](AccessTokenMissingError.md#preparestacktrace)
|
|
24
|
+
- [stackTraceLimit](AccessTokenMissingError.md#stacktracelimit)
|
|
25
|
+
|
|
26
|
+
### Methods
|
|
27
|
+
|
|
28
|
+
- [captureStackTrace](AccessTokenMissingError.md#capturestacktrace)
|
|
29
|
+
|
|
30
|
+
## Constructors
|
|
31
|
+
|
|
32
|
+
### constructor
|
|
33
|
+
|
|
34
|
+
• **new AccessTokenMissingError**()
|
|
35
|
+
|
|
36
|
+
#### Overrides
|
|
37
|
+
|
|
38
|
+
Error.constructor
|
|
39
|
+
|
|
40
|
+
#### Defined in
|
|
41
|
+
|
|
42
|
+
[packages/oidc/src/auth-errors.ts:7](https://github.com/vercel/vercel/blob/main/packages/oidc/src/auth-errors.ts#L7)
|
|
43
|
+
|
|
44
|
+
## Properties
|
|
45
|
+
|
|
46
|
+
### message
|
|
47
|
+
|
|
48
|
+
• **message**: `string`
|
|
49
|
+
|
|
50
|
+
#### Inherited from
|
|
51
|
+
|
|
52
|
+
Error.message
|
|
53
|
+
|
|
54
|
+
#### Defined in
|
|
55
|
+
|
|
56
|
+
node_modules/.pnpm/typescript@4.9.5/node_modules/typescript/lib/lib.es5.d.ts:1054
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### name
|
|
61
|
+
|
|
62
|
+
• **name**: `string` = `'AccessTokenMissingError'`
|
|
63
|
+
|
|
64
|
+
#### Overrides
|
|
65
|
+
|
|
66
|
+
Error.name
|
|
67
|
+
|
|
68
|
+
#### Defined in
|
|
69
|
+
|
|
70
|
+
[packages/oidc/src/auth-errors.ts:6](https://github.com/vercel/vercel/blob/main/packages/oidc/src/auth-errors.ts#L6)
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### stack
|
|
75
|
+
|
|
76
|
+
• `Optional` **stack**: `string`
|
|
77
|
+
|
|
78
|
+
#### Inherited from
|
|
79
|
+
|
|
80
|
+
Error.stack
|
|
81
|
+
|
|
82
|
+
#### Defined in
|
|
83
|
+
|
|
84
|
+
node_modules/.pnpm/typescript@4.9.5/node_modules/typescript/lib/lib.es5.d.ts:1055
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### prepareStackTrace
|
|
89
|
+
|
|
90
|
+
▪ `Static` `Optional` **prepareStackTrace**: (`err`: [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error), `stackTraces`: `CallSite`[]) => `any`
|
|
91
|
+
|
|
92
|
+
#### Type declaration
|
|
93
|
+
|
|
94
|
+
▸ (`err`, `stackTraces`): `any`
|
|
95
|
+
|
|
96
|
+
Optional override for formatting stack traces
|
|
97
|
+
|
|
98
|
+
**`See`**
|
|
99
|
+
|
|
100
|
+
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
|
|
101
|
+
|
|
102
|
+
##### Parameters
|
|
103
|
+
|
|
104
|
+
| Name | Type |
|
|
105
|
+
| :------------ | :------------------------------------------------------------------------------------------------ |
|
|
106
|
+
| `err` | [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) |
|
|
107
|
+
| `stackTraces` | `CallSite`[] |
|
|
108
|
+
|
|
109
|
+
##### Returns
|
|
110
|
+
|
|
111
|
+
`any`
|
|
112
|
+
|
|
113
|
+
#### Inherited from
|
|
114
|
+
|
|
115
|
+
Error.prepareStackTrace
|
|
116
|
+
|
|
117
|
+
#### Defined in
|
|
118
|
+
|
|
119
|
+
node_modules/.pnpm/@types+node@20.11.0/node_modules/@types/node/globals.d.ts:28
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### stackTraceLimit
|
|
124
|
+
|
|
125
|
+
▪ `Static` **stackTraceLimit**: `number`
|
|
126
|
+
|
|
127
|
+
#### Inherited from
|
|
128
|
+
|
|
129
|
+
Error.stackTraceLimit
|
|
130
|
+
|
|
131
|
+
#### Defined in
|
|
132
|
+
|
|
133
|
+
node_modules/.pnpm/@types+node@20.11.0/node_modules/@types/node/globals.d.ts:30
|
|
134
|
+
|
|
135
|
+
## Methods
|
|
136
|
+
|
|
137
|
+
### captureStackTrace
|
|
138
|
+
|
|
139
|
+
▸ `Static` **captureStackTrace**(`targetObject`, `constructorOpt?`): `void`
|
|
140
|
+
|
|
141
|
+
Create .stack property on a target object
|
|
142
|
+
|
|
143
|
+
#### Parameters
|
|
144
|
+
|
|
145
|
+
| Name | Type |
|
|
146
|
+
| :---------------- | :------------------------------------------------------------------------------------------------------ |
|
|
147
|
+
| `targetObject` | `object` |
|
|
148
|
+
| `constructorOpt?` | [`Function`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function) |
|
|
149
|
+
|
|
150
|
+
#### Returns
|
|
151
|
+
|
|
152
|
+
`void`
|
|
153
|
+
|
|
154
|
+
#### Inherited from
|
|
155
|
+
|
|
156
|
+
Error.captureStackTrace
|
|
157
|
+
|
|
158
|
+
#### Defined in
|
|
159
|
+
|
|
160
|
+
node_modules/.pnpm/@types+node@20.11.0/node_modules/@types/node/globals.d.ts:21
|