@vercel/oidc 4.0.4 → 4.0.5-snapshot-dd15927e8ded

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @vercel/oidc
2
2
 
3
+ ## 4.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - dc2c86d: With a DPoP login (`__VERCEL_FF_DPOP=1`), refresh the OIDC token with `vercel project token`, which signs the request, instead of sending the CLI's token as `Bearer`.
8
+ - dc2c86d: Refuse to refresh the OIDC token through `vercel project token` when the project or team ID from `.vercel/project.json` is not a valid ID or name, so a value such as `--api=...` can't be read by the CLI as an option.
9
+ - Updated dependencies [dc2c86d]
10
+ - Updated dependencies [dc2c86d]
11
+ - Updated dependencies [dc2c86d]
12
+ - Updated dependencies [dc2c86d]
13
+ - @vercel/cli-config@0.3.5
14
+
3
15
  ## 4.0.4
4
16
 
5
17
  ### Patch Changes
@@ -93,7 +93,19 @@ function isValidAccessToken(authConfig, expirationBufferMs = 0) {
93
93
  const bufferInSeconds = expirationBufferMs / 1e3;
94
94
  return authConfig.expiresAt >= nowInSeconds + bufferInSeconds;
95
95
  }
96
+ const CLI_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
97
+ function assertCliId(value, kind) {
98
+ if (!CLI_ID_PATTERN.test(value)) {
99
+ throw new import_token_error.VercelOidcTokenError(
100
+ `Failed to refresh OIDC token: ${JSON.stringify(value)} is not a valid ${kind} ID or name. Try re-linking your project with \`vc link\``
101
+ );
102
+ }
103
+ }
96
104
  async function getVercelOidcTokenFromCli(projectId, teamId) {
105
+ assertCliId(projectId, "project");
106
+ if (teamId) {
107
+ assertCliId(teamId, "team");
108
+ }
97
109
  const args = ["project", "token", projectId, "--format=json"];
98
110
  if (teamId) {
99
111
  args.push("--scope", teamId);
package/dist/token.js CHANGED
@@ -44,7 +44,7 @@ async function refreshToken(options) {
44
44
  let maybeToken = (0, import_token_util.loadToken)(projectId);
45
45
  if (!maybeToken || (0, import_token_util.isExpired)((0, import_token_util.getTokenPayload)(maybeToken.token), options?.expirationBufferMs)) {
46
46
  const configDir = (0, import_cli_config.getGlobalPathConfig)();
47
- if ((0, import_cli_config.getLikelyEffectiveCredStorage)(configDir) === "keyring") {
47
+ if ((0, import_cli_config.getLikelyEffectiveCredStorage)(configDir) === "keyring" || isDpopLoginEnabled()) {
48
48
  maybeToken = await (0, import_token_util.getVercelOidcTokenFromCli)(projectId, teamId);
49
49
  } else {
50
50
  const authToken = await (0, import_token_util.getVercelToken)({
@@ -60,6 +60,9 @@ async function refreshToken(options) {
60
60
  process.env.VERCEL_OIDC_TOKEN = maybeToken.token;
61
61
  return;
62
62
  }
63
+ function isDpopLoginEnabled() {
64
+ return process.env.__VERCEL_FF_DPOP === "1";
65
+ }
63
66
  // Annotate the CommonJS export names for ESM import in node:
64
67
  0 && (module.exports = {
65
68
  refreshToken
@@ -55,6 +55,7 @@ import_vitest.vi.mock("./token-io");
55
55
  (0, import_vitest.beforeEach)(() => {
56
56
  import_vitest.vi.clearAllMocks();
57
57
  import_vitest.vi.mocked(import_cli_config.getLikelyEffectiveCredStorage).mockReturnValue("file");
58
+ import_vitest.vi.stubEnv("__VERCEL_FF_DPOP", void 0);
58
59
  process.env.VERCEL_OIDC_TOKEN = void 0;
59
60
  const random = `test-${(0, import_crypto.randomUUID)()}`;
60
61
  rootDir = path.join(os.tmpdir(), random);
@@ -137,6 +138,66 @@ import_vitest.vi.mock("./token-io");
137
138
  customTeamId
138
139
  ]);
139
140
  });
141
+ (0, import_vitest.test)("should use cli-exec with a DPoP login", async () => {
142
+ import_vitest.vi.stubEnv("__VERCEL_FF_DPOP", "1");
143
+ await (0, import_token.refreshToken)();
144
+ (0, import_vitest.expect)(import_cli_exec.execVercelCli).toHaveBeenCalledWith([
145
+ "project",
146
+ "token",
147
+ projectId,
148
+ "--format=json"
149
+ ]);
150
+ (0, import_vitest.expect)(tokenUtil.getVercelToken).not.toHaveBeenCalled();
151
+ (0, import_vitest.expect)(tokenUtil.getVercelOidcToken).not.toHaveBeenCalled();
152
+ (0, import_vitest.expect)(process.env.VERCEL_OIDC_TOKEN).toBe("cli-token");
153
+ });
154
+ (0, import_vitest.test)("should read auth.json directly unless __VERCEL_FF_DPOP is exactly 1", async () => {
155
+ import_vitest.vi.stubEnv("__VERCEL_FF_DPOP", "0");
156
+ await (0, import_token.refreshToken)();
157
+ (0, import_vitest.expect)(import_cli_exec.execVercelCli).not.toHaveBeenCalled();
158
+ (0, import_vitest.expect)(tokenUtil.getVercelToken).toHaveBeenCalled();
159
+ (0, import_vitest.expect)(process.env.VERCEL_OIDC_TOKEN).toBe("test-token");
160
+ });
161
+ import_vitest.test.each([
162
+ [
163
+ "keyring storage",
164
+ () => {
165
+ import_vitest.vi.mocked(import_cli_config.getLikelyEffectiveCredStorage).mockReturnValue("keyring");
166
+ }
167
+ ],
168
+ [
169
+ "a DPoP login",
170
+ () => {
171
+ import_vitest.vi.stubEnv("__VERCEL_FF_DPOP", "1");
172
+ }
173
+ ]
174
+ ])("with %s, should not pass an option-shaped project.json value to the cli", async (_, setup) => {
175
+ setup();
176
+ for (const prj of [
177
+ { projectId: "--api=https://example.com" },
178
+ { projectId, orgId: "--api=https://example.com" },
179
+ { projectId, orgId: "-A" }
180
+ ]) {
181
+ fs.writeFileSync(
182
+ path.join(rootDir, ".vercel", "project.json"),
183
+ JSON.stringify(prj)
184
+ );
185
+ await (0, import_vitest.expect)((0, import_token.refreshToken)()).rejects.toThrow("is not a valid");
186
+ }
187
+ (0, import_vitest.expect)(import_cli_exec.execVercelCli).not.toHaveBeenCalled();
188
+ });
189
+ (0, import_vitest.test)("should pass a project slug to the cli", async () => {
190
+ import_vitest.vi.stubEnv("__VERCEL_FF_DPOP", "1");
191
+ await (0, import_token.refreshToken)({ project: "my-app.v2", team: "my_team" });
192
+ (0, import_vitest.expect)(import_cli_exec.execVercelCli).toHaveBeenCalledWith([
193
+ "project",
194
+ "token",
195
+ "my-app.v2",
196
+ "--format=json",
197
+ "--scope",
198
+ "my_team"
199
+ ]);
200
+ });
140
201
  (0, import_vitest.test)("should fail with a cli-specific error for malformed cli json output", async () => {
141
202
  import_vitest.vi.mocked(import_cli_config.getLikelyEffectiveCredStorage).mockReturnValue("keyring");
142
203
  import_vitest.vi.mocked(import_cli_exec.execVercelCli).mockResolvedValue({
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "4.0.4";
1
+ export declare const version = "4.0.5-snapshot-dd15927e8ded";
package/dist/version.js CHANGED
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  version: () => version
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const version = "4.0.4";
24
+ const version = "4.0.5-snapshot-dd15927e8ded";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  version
package/package.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "require": "./dist/index.js"
19
19
  }
20
20
  },
21
- "version": "4.0.4",
21
+ "version": "4.0.5-snapshot-dd15927e8ded",
22
22
  "repository": {
23
23
  "directory": "packages/oidc",
24
24
  "type": "git",
@@ -29,8 +29,8 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "jose": "^5.9.6",
32
- "@vercel/cli-exec": "1.0.1",
33
- "@vercel/cli-config": "0.3.4"
32
+ "@vercel/cli-config": "0.3.5-snapshot-dd15927e8ded",
33
+ "@vercel/cli-exec": "1.0.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "prettier": "3.8.3",