🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@vercel/oidc

Package Overview
Dependencies
Maintainers
8
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vercel/oidc - npm Package Compare versions

Comparing version
2.0.0
to
2.0.1
+5
dist/token-error.d.ts
export declare class VercelOidcTokenError extends Error {
cause?: unknown;
constructor(message: string, cause?: unknown);
toString(): string;
}
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var token_error_exports = {};
__export(token_error_exports, {
VercelOidcTokenError: () => VercelOidcTokenError
});
module.exports = __toCommonJS(token_error_exports);
class VercelOidcTokenError extends Error {
constructor(message, cause) {
super(message);
this.name = "VercelOidcTokenError";
this.cause = cause;
}
toString() {
if (this.cause) {
return `${this.name}: ${this.message}: ${this.cause}`;
}
return `${this.name}: ${this.message}`;
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
VercelOidcTokenError
});
export declare function findRootDir(): string;
export declare function getUserDataDir(): string | null;
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var token_io_exports = {};
__export(token_io_exports, {
findRootDir: () => findRootDir,
getUserDataDir: () => getUserDataDir
});
module.exports = __toCommonJS(token_io_exports);
var import_path = __toESM(require("path"));
var import_fs = __toESM(require("fs"));
var import_os = __toESM(require("os"));
var import_token_error = require("./token-error");
function findRootDir() {
try {
let dir = process.cwd();
while (dir !== import_path.default.dirname(dir)) {
const pkgPath = import_path.default.join(dir, ".vercel");
if (import_fs.default.existsSync(pkgPath)) {
return dir;
}
dir = import_path.default.dirname(dir);
}
} catch (e) {
throw new import_token_error.VercelOidcTokenError(
"Token refresh only supported in node server environments"
);
}
throw new import_token_error.VercelOidcTokenError("Unable to find root directory");
}
function getUserDataDir() {
if (process.env.XDG_DATA_HOME) {
return process.env.XDG_DATA_HOME;
}
switch (import_os.default.platform()) {
case "darwin":
return import_path.default.join(import_os.default.homedir(), "Library/Application Support");
case "linux":
return import_path.default.join(import_os.default.homedir(), ".local/share");
case "win32":
if (process.env.LOCALAPPDATA) {
return process.env.LOCALAPPDATA;
}
return null;
default:
return null;
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
findRootDir,
getUserDataDir
});
export declare function getVercelDataDir(): string | null;
export declare function getVercelCliToken(): string | null;
interface VercelTokenResponse {
token: string;
}
export declare function getVercelOidcToken(authToken: string, projectId: string, teamId?: string): Promise<VercelTokenResponse | null>;
export declare function assertVercelOidcTokenResponse(res: unknown): asserts res is VercelTokenResponse;
export declare function findProjectInfo(): {
projectId: string;
teamId: string;
};
export declare function saveToken(token: VercelTokenResponse, projectId: string): void;
export declare function loadToken(projectId: string): VercelTokenResponse | null;
interface TokenPayload {
sub: string;
name: string;
exp: number;
}
export declare function getTokenPayload(token: string): TokenPayload;
export declare function isExpired(token: TokenPayload): boolean;
export {};
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var token_util_exports = {};
__export(token_util_exports, {
assertVercelOidcTokenResponse: () => assertVercelOidcTokenResponse,
findProjectInfo: () => findProjectInfo,
getTokenPayload: () => getTokenPayload,
getVercelCliToken: () => getVercelCliToken,
getVercelDataDir: () => getVercelDataDir,
getVercelOidcToken: () => getVercelOidcToken,
isExpired: () => isExpired,
loadToken: () => loadToken,
saveToken: () => saveToken
});
module.exports = __toCommonJS(token_util_exports);
var path = __toESM(require("path"));
var fs = __toESM(require("fs"));
var import_token_error = require("./token-error");
var import_token_io = require("./token-io");
var import_ms = __toESM(require("ms"));
function getVercelDataDir() {
const vercelFolder = "com.vercel.cli";
const dataDir = (0, import_token_io.getUserDataDir)();
if (!dataDir) {
return null;
}
return path.join(dataDir, vercelFolder);
}
function getVercelCliToken() {
const dataDir = getVercelDataDir();
if (!dataDir) {
return null;
}
const tokenPath = path.join(dataDir, "auth.json");
if (!fs.existsSync(tokenPath)) {
return null;
}
const token = fs.readFileSync(tokenPath, "utf8");
if (!token) {
return null;
}
return JSON.parse(token).token;
}
async function getVercelOidcToken(authToken, projectId, teamId) {
try {
const url = `https://api.vercel.com/v1/projects/${projectId}/token?source=vercel-oidc-refresh${teamId ? `&teamId=${teamId}` : ""}`;
const res = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${authToken}`
}
});
if (!res.ok) {
throw new import_token_error.VercelOidcTokenError(
`Failed to refresh OIDC token: ${res.statusText}`
);
}
const tokenRes = await res.json();
assertVercelOidcTokenResponse(tokenRes);
return tokenRes;
} catch (e) {
throw new import_token_error.VercelOidcTokenError(`Failed to refresh OIDC token`, e);
}
}
function assertVercelOidcTokenResponse(res) {
if (!res || typeof res !== "object") {
throw new TypeError("Expected an object");
}
if (!("token" in res) || typeof res.token !== "string") {
throw new TypeError("Expected a string-valued token property");
}
}
function findProjectInfo() {
const dir = (0, import_token_io.findRootDir)();
if (!dir) {
throw new import_token_error.VercelOidcTokenError("Unable to find root directory");
}
try {
const prjPath = path.join(dir, ".vercel", "project.json");
if (!fs.existsSync(prjPath)) {
throw new import_token_error.VercelOidcTokenError("project.json not found");
}
const prj = JSON.parse(fs.readFileSync(prjPath, "utf8"));
if (typeof prj.projectId !== "string" && typeof prj.orgId !== "string") {
throw new TypeError("Expected a string-valued projectId property");
}
return { projectId: prj.projectId, teamId: prj.orgId };
} catch (e) {
throw new import_token_error.VercelOidcTokenError(`Unable to find project ID`, e);
}
}
function saveToken(token, projectId) {
try {
const dir = (0, import_token_io.getUserDataDir)();
if (!dir) {
throw new import_token_error.VercelOidcTokenError("Unable to find user data directory");
}
const tokenPath = path.join(dir, "com.vercel.token", `${projectId}.json`);
const tokenJson = JSON.stringify(token);
fs.mkdirSync(path.dirname(tokenPath), { mode: 432, recursive: true });
fs.writeFileSync(tokenPath, tokenJson);
fs.chmodSync(tokenPath, 432);
return;
} catch (e) {
throw new import_token_error.VercelOidcTokenError(`Failed to save token`, e);
}
}
function loadToken(projectId) {
try {
const dir = (0, import_token_io.getUserDataDir)();
if (!dir) {
return null;
}
const tokenPath = path.join(dir, "com.vercel.token", `${projectId}.json`);
if (!fs.existsSync(tokenPath)) {
return null;
}
const token = JSON.parse(fs.readFileSync(tokenPath, "utf8"));
assertVercelOidcTokenResponse(token);
return token;
} catch (e) {
throw new import_token_error.VercelOidcTokenError(`Failed to load token`, e);
}
}
function getTokenPayload(token) {
const tokenParts = token.split(".");
if (tokenParts.length !== 3) {
throw new import_token_error.VercelOidcTokenError("Invalid token");
}
const base64 = tokenParts[1].replace(/-/g, "+").replace(/_/g, "/");
const padded = base64.padEnd(
base64.length + (4 - base64.length % 4) % 4,
"="
);
return JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
}
function isExpired(token) {
const timeout = (0, import_ms.default)("15m");
return token.exp * 1e3 < Date.now() + timeout;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
assertVercelOidcTokenResponse,
findProjectInfo,
getTokenPayload,
getVercelCliToken,
getVercelDataDir,
getVercelOidcToken,
isExpired,
loadToken,
saveToken
});
export declare function refreshToken(): Promise<void>;
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var token_exports = {};
__export(token_exports, {
refreshToken: () => refreshToken
});
module.exports = __toCommonJS(token_exports);
var import_token_error = require("./token-error");
var import_token_util = require("./token-util");
async function refreshToken() {
const { projectId, teamId } = (0, import_token_util.findProjectInfo)();
let maybeToken = (0, import_token_util.loadToken)(projectId);
if (!maybeToken || (0, import_token_util.isExpired)((0, import_token_util.getTokenPayload)(maybeToken.token))) {
const authToken = (0, import_token_util.getVercelCliToken)();
if (!authToken) {
throw new import_token_error.VercelOidcTokenError(
"Failed to refresh OIDC token: login to vercel cli"
);
}
if (!projectId) {
throw new import_token_error.VercelOidcTokenError(
"Failed to refresh OIDC token: project id not found"
);
}
maybeToken = await (0, import_token_util.getVercelOidcToken)(authToken, projectId, teamId);
if (!maybeToken) {
throw new import_token_error.VercelOidcTokenError("Failed to refresh OIDC token");
}
(0, import_token_util.saveToken)(maybeToken, projectId);
}
process.env.VERCEL_OIDC_TOKEN = maybeToken.token;
return;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
refreshToken
});
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var import_crypto = require("crypto");
var import_vitest = require("vitest");
var os = __toESM(require("os"));
var path = __toESM(require("path"));
var fs = __toESM(require("fs"));
var import_token_io = require("./token-io");
var tokenUtil = __toESM(require("./token-util"));
var import_token = require("./token");
import_vitest.vi.mock("./token-io");
(0, import_vitest.describe)("refreshToken", () => {
let rootDir;
let userDataDir;
let cliDataDir;
let tokenDataDir;
const projectId = "test-project-id";
(0, import_vitest.beforeEach)(() => {
import_vitest.vi.clearAllMocks();
process.env.VERCEL_OIDC_TOKEN = void 0;
const random = `test-${(0, import_crypto.randomUUID)()}`;
rootDir = path.join(os.tmpdir(), random);
userDataDir = path.join(rootDir, "data");
cliDataDir = path.join(userDataDir, "com.vercel.cli");
tokenDataDir = path.join(userDataDir, "com.vercel.token");
fs.mkdirSync(cliDataDir, { recursive: true });
fs.mkdirSync(tokenDataDir, { recursive: true });
fs.mkdirSync(path.join(rootDir, ".vercel"), {
recursive: true
});
fs.writeFileSync(path.join(cliDataDir, "auth.json"), '{token: "test"}');
fs.writeFileSync(
path.join(rootDir, ".vercel", "project.json"),
JSON.stringify({ projectId })
);
import_vitest.vi.spyOn(process, "cwd").mockReturnValue(rootDir);
import_vitest.vi.mocked(import_token_io.findRootDir).mockReturnValue(rootDir);
import_vitest.vi.mocked(import_token_io.getUserDataDir).mockReturnValue(userDataDir);
import_vitest.vi.spyOn(tokenUtil, "getVercelCliToken").mockReturnValue("test");
import_vitest.vi.spyOn(tokenUtil, "getVercelOidcToken").mockResolvedValue({
token: "test-token"
});
import_vitest.vi.spyOn(tokenUtil, "getTokenPayload").mockReturnValue({
sub: "test-sub",
name: "test-name",
exp: Date.now() + 1e5
});
});
(0, import_vitest.test)("should correctly load saved token from file", async () => {
const token = { token: "test-saved" };
const tokenPath = path.join(tokenDataDir, `${projectId}.json`);
fs.writeFileSync(tokenPath, JSON.stringify(token));
await (0, import_token.refreshToken)();
(0, import_vitest.expect)(process.env.VERCEL_OIDC_TOKEN).toBe("test-saved");
});
(0, import_vitest.test)("should correctly save token to file", async () => {
await (0, import_token.refreshToken)();
(0, import_vitest.expect)(process.env.VERCEL_OIDC_TOKEN).toBe("test-token");
const tokenPath = path.join(tokenDataDir, `${projectId}.json`);
const token = JSON.parse(fs.readFileSync(tokenPath, "utf8"));
(0, import_vitest.expect)(token).toEqual({ token: "test-token" });
});
});
+12
-0
# @vercel/oidc
## 2.0.1
### Patch Changes
- Fix package versions for oidc-aws-credentials-provider, vercel/functions, and publish the next version of vercel/oidc ([#13765](https://github.com/vercel/vercel/pull/13765))
## 2.1.0
### Minor Changes
- Add refresh token ability to @vercel/oidc ([#13608](https://github.com/vercel/vercel/pull/13608))
## 2.0.0

@@ -4,0 +16,0 @@

+7
-1

@@ -9,4 +9,8 @@ /**

*
* Unlike the `getVercelOidcTokenSync` function, this function will refresh the token if it is expired in a development environment.
*
* @returns {Promise<string>} A promise that resolves to the OIDC token.
* @throws {Error} If the `x-vercel-oidc-token` header is missing from the request context and the environment variable `VERCEL_OIDC_TOKEN` is not set.
* @throws {Error} If the `x-vercel-oidc-token` header is missing from the request context and the environment variable `VERCEL_OIDC_TOKEN` is not set. If the token
* is expired in a development environment, will also throw an error if the token cannot be refreshed: no CLI credentials are available, CLI credentials are expired, no project configuration is available
* or the token refresh request fails.
*

@@ -33,2 +37,4 @@ * @example

*
* This function will not refresh the token if it is expired. For refreshing the token, use the @{link getVercelOidcToken} function.
*
* @returns {string} The OIDC token.

@@ -35,0 +41,0 @@ * @throws {Error} If the `x-vercel-oidc-token` header is missing from the request context and the environment variable `VERCEL_OIDC_TOKEN` is not set.

"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;

@@ -18,2 +20,10 @@ var __export = (target, all) => {

};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

@@ -27,4 +37,28 @@ var get_vercel_oidc_token_exports = {};

var import_get_context = require("./get-context");
var import_token_error = require("./token-error");
async function getVercelOidcToken() {
return getVercelOidcTokenSync();
let token = "";
let err;
try {
token = getVercelOidcTokenSync();
} catch (error) {
err = error;
}
try {
const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([
await import("./token-util"),
await import("./token")
]);
if (!token || isExpired(getTokenPayload(token))) {
await refreshToken();
token = getVercelOidcTokenSync();
}
} catch (error) {
if (err?.message && error instanceof Error) {
error.message = `${err.message}
${error.message}`;
}
throw new import_token_error.VercelOidcTokenError(`Failed to refresh OIDC token`, error);
}
return token;
}

@@ -31,0 +65,0 @@ function getVercelOidcTokenSync() {

+9
-3

@@ -23,5 +23,9 @@ # @vercel/oidc

Unlike the `getVercelOidcTokenSync` function, this function will refresh the token if it is expired in a development environment.
**`Throws`**
If the `x-vercel-oidc-token` header is missing from the request context and the environment variable `VERCEL_OIDC_TOKEN` is not set.
If the `x-vercel-oidc-token` header is missing from the request context and the environment variable `VERCEL_OIDC_TOKEN` is not set. If the token
is expired in a development environment, will also throw an error if the token cannot be refreshed: no CLI credentials are available, CLI credentials are expired, no project configuration is available
or the token refresh request fails.

@@ -49,3 +53,3 @@ **`Example`**

[get-vercel-oidc-token.ts:24](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-vercel-oidc-token.ts#L24)
[get-vercel-oidc-token.ts:30](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-vercel-oidc-token.ts#L30)

@@ -65,2 +69,4 @@ ---

This function will not refresh the token if it is expired. For refreshing the token, use the @{link getVercelOidcToken} function.
**`Throws`**

@@ -86,2 +92,2 @@

[get-vercel-oidc-token.ts:47](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-vercel-oidc-token.ts#L47)
[get-vercel-oidc-token.ts:81](https://github.com/vercel/vercel/blob/main/packages/oidc/src/get-vercel-oidc-token.ts#L81)

@@ -17,3 +17,3 @@ {

},
"version": "2.0.0",
"version": "2.0.1",
"repository": {

@@ -43,2 +43,6 @@ "directory": "packages/oidc",

},
"dependencies": {
"@types/ms": "2.1.0",
"ms": "2.1.3"
},
"scripts": {

@@ -45,0 +49,0 @@ "pretest": "pnpm run build:code",