@vercel/oidc
Advanced tools
| import { type JWTVerifyOptions, type JWTVerifyResult, type JWTPayload } from 'jose'; | ||
| export type VercelOidcPayload = JWTPayload & { | ||
| owner_id: string; | ||
| project_id: string; | ||
| environment: string; | ||
| external_sub?: string; | ||
| sub: string; | ||
| aud: string; | ||
| iss: string; | ||
| }; | ||
| /** | ||
| * Verifies a Vercel OIDC token against Vercel's remote JWKS. | ||
| * | ||
| * The issuer must be `https://oidc.vercel.com` or start with | ||
| * `https://oidc.vercel.com/`. The JWKS is always | ||
| * `https://oidc.vercel.com/.well-known/jwks`. | ||
| * | ||
| * Options: | ||
| * | ||
| * - `issuer`: Expected `iss` claim verified by Jose. The verified issuer must | ||
| * still be `https://oidc.vercel.com` or start with | ||
| * `https://oidc.vercel.com/`. | ||
| * - `projectId`: Expected `project_id` claim or claims. Defaults to | ||
| * `process.env.VERCEL_PROJECT_ID`. Pass an array to allow any matching | ||
| * project ID. Pass `'*'` to allow any project ID. When `projectId` is `'*'`, | ||
| * either `ownerId` or `audience` is required. | ||
| * - `environment`: Expected `environment` claim or claims. Defaults to | ||
| * `process.env.VERCEL_TARGET_ENV || process.env.VERCEL_ENV`. Pass an array | ||
| * to allow any matching environment. Pass `'*'` to allow any environment. | ||
| * - `ownerId`: Expected `owner_id` claim. When omitted, the claim is not | ||
| * checked. | ||
| * - Any other Jose JWT verification option. | ||
| * | ||
| * @param token The Vercel OIDC token to verify. | ||
| * @param options Optional Jose JWT verification options. | ||
| * @returns Jose's verified JWT result. | ||
| */ | ||
| export declare function verifyVercelOidcToken<PayloadType = VercelOidcPayload>(token: string, options?: { | ||
| projectId?: string | string[] | '*'; | ||
| environment?: string | string[] | '*'; | ||
| ownerId?: string; | ||
| } & JWTVerifyOptions): Promise<JWTVerifyResult<PayloadType>>; |
| "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 verify_vercel_oidc_token_exports = {}; | ||
| __export(verify_vercel_oidc_token_exports, { | ||
| verifyVercelOidcToken: () => verifyVercelOidcToken | ||
| }); | ||
| module.exports = __toCommonJS(verify_vercel_oidc_token_exports); | ||
| var import_jose = require("jose"); | ||
| const VERCEL_OIDC_ISSUER = "https://oidc.vercel.com"; | ||
| const VERCEL_OIDC_JWKS_URL = new URL( | ||
| "https://oidc.vercel.com/.well-known/jwks" | ||
| ); | ||
| const DEFAULT_ALGORITHMS = ["RS256"]; | ||
| const VERCEL_OIDC_JWKS = (0, import_jose.createRemoteJWKSet)(VERCEL_OIDC_JWKS_URL); | ||
| async function verifyVercelOidcToken(token, options) { | ||
| const { | ||
| algorithms, | ||
| projectId = process.env.VERCEL_PROJECT_ID, | ||
| environment = process.env.VERCEL_TARGET_ENV || process.env.VERCEL_ENV, | ||
| ownerId, | ||
| ...verifyOptions | ||
| } = options ?? {}; | ||
| if (projectId === "*" && ownerId === void 0 && !hasAudienceVerification(verifyOptions.audience)) { | ||
| throw new TypeError( | ||
| "Expected ownerId or audience to be provided when projectId is '*'." | ||
| ); | ||
| } | ||
| const result = await (0, import_jose.jwtVerify)(token, VERCEL_OIDC_JWKS, { | ||
| ...verifyOptions, | ||
| algorithms: algorithms ?? DEFAULT_ALGORITHMS | ||
| }); | ||
| validateIssuer(result.payload.iss); | ||
| validateClaim({ | ||
| actual: result.payload.project_id, | ||
| claim: "project_id", | ||
| env: "VERCEL_PROJECT_ID", | ||
| expected: projectId, | ||
| option: "projectId" | ||
| }); | ||
| validateClaim({ | ||
| actual: result.payload.environment, | ||
| claim: "environment", | ||
| env: "VERCEL_TARGET_ENV or VERCEL_ENV", | ||
| expected: environment, | ||
| option: "environment" | ||
| }); | ||
| validateOptionalClaim({ | ||
| actual: result.payload.owner_id, | ||
| claim: "owner_id", | ||
| expected: ownerId | ||
| }); | ||
| return result; | ||
| } | ||
| function hasAudienceVerification(audience) { | ||
| return Array.isArray(audience) ? audience.length > 0 : audience !== void 0; | ||
| } | ||
| function validateIssuer(actual) { | ||
| if (actual !== VERCEL_OIDC_ISSUER && (typeof actual !== "string" || !actual.startsWith(`${VERCEL_OIDC_ISSUER}/`))) { | ||
| throw new TypeError( | ||
| `Expected Vercel OIDC token iss claim to be "${VERCEL_OIDC_ISSUER}" or to start with "${VERCEL_OIDC_ISSUER}/".` | ||
| ); | ||
| } | ||
| } | ||
| function validateClaim({ | ||
| actual, | ||
| claim, | ||
| env, | ||
| expected, | ||
| option | ||
| }) { | ||
| if (expected === "*") { | ||
| return; | ||
| } | ||
| if (expected === void 0 || expected.length === 0) { | ||
| throw new TypeError( | ||
| `Expected ${env} to be set or ${option} to be provided. Pass ${option}: '*' to allow any ${claim} claim.` | ||
| ); | ||
| } | ||
| if (Array.isArray(expected) && typeof actual === "string" && expected.includes(actual)) { | ||
| return; | ||
| } | ||
| if (actual !== expected) { | ||
| throw new TypeError( | ||
| Array.isArray(expected) ? `Expected Vercel OIDC token ${claim} claim to be one of: ${expected.map((value) => `"${value}"`).join(", ")}.` : `Expected Vercel OIDC token ${claim} claim to be "${expected}".` | ||
| ); | ||
| } | ||
| } | ||
| function validateOptionalClaim({ | ||
| actual, | ||
| claim, | ||
| expected | ||
| }) { | ||
| if (expected === void 0) { | ||
| return; | ||
| } | ||
| if (actual !== expected) { | ||
| throw new TypeError( | ||
| `Expected Vercel OIDC token ${claim} claim to be "${expected}".` | ||
| ); | ||
| } | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| verifyVercelOidcToken | ||
| }); |
| export {}; |
| "use strict"; | ||
| var import_vitest = require("vitest"); | ||
| var import_jose = require("jose"); | ||
| var import_verify_vercel_oidc_token = require("./verify-vercel-oidc-token"); | ||
| const mocks = import_vitest.vi.hoisted(() => { | ||
| const remoteJwks = import_vitest.vi.fn(); | ||
| return { | ||
| remoteJwks, | ||
| createRemoteJWKSet: import_vitest.vi.fn(() => remoteJwks), | ||
| jwtVerify: import_vitest.vi.fn() | ||
| }; | ||
| }); | ||
| import_vitest.vi.mock("jose", () => ({ | ||
| createRemoteJWKSet: mocks.createRemoteJWKSet, | ||
| jwtVerify: mocks.jwtVerify | ||
| })); | ||
| (0, import_vitest.describe)("verifyVercelOidcToken", () => { | ||
| const verifyResult = { | ||
| payload: { | ||
| sub: "owner:team1:project:site:environment:production", | ||
| iss: "https://oidc.vercel.com/team1", | ||
| aud: "https://oidc.vercel.com/team1", | ||
| project_id: "prj_test", | ||
| environment: "production", | ||
| owner_id: "team_team1" | ||
| }, | ||
| protectedHeader: { | ||
| alg: "RS256" | ||
| } | ||
| }; | ||
| (0, import_vitest.beforeEach)(() => { | ||
| process.env.VERCEL_PROJECT_ID = "prj_test"; | ||
| process.env.VERCEL_TARGET_ENV = "production"; | ||
| delete process.env.VERCEL_ENV; | ||
| import_vitest.vi.mocked(import_jose.jwtVerify).mockClear(); | ||
| mockVerifiedPayload(); | ||
| }); | ||
| (0, import_vitest.afterEach)(() => { | ||
| delete process.env.VERCEL_PROJECT_ID; | ||
| delete process.env.VERCEL_TARGET_ENV; | ||
| delete process.env.VERCEL_ENV; | ||
| }); | ||
| (0, import_vitest.test)("verifies a token using the Vercel issuer and JWKS", async () => { | ||
| const result = await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| audience: "https://oidc.vercel.com/team1", | ||
| subject: "owner:team1:project:site:environment:production" | ||
| }); | ||
| (0, import_vitest.expect)(result).toStrictEqual(verifyResult); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledWith("token", mocks.remoteJwks, { | ||
| algorithms: ["RS256"], | ||
| audience: "https://oidc.vercel.com/team1", | ||
| subject: "owner:team1:project:site:environment:production" | ||
| }); | ||
| }); | ||
| (0, import_vitest.test)("verifies a token without additional options", async () => { | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token"); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledWith("token", mocks.remoteJwks, { | ||
| algorithms: ["RS256"] | ||
| }); | ||
| }); | ||
| (0, import_vitest.test)("reuses the Vercel remote JWKS resolver", async () => { | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("first-token"); | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("second-token"); | ||
| (0, import_vitest.expect)(mocks.createRemoteJWKSet).toHaveBeenCalledTimes(1); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledTimes(2); | ||
| }); | ||
| (0, import_vitest.test)("passes custom algorithms to Jose verification", async () => { | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| algorithms: ["RS512"] | ||
| }); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledWith("token", mocks.remoteJwks, { | ||
| algorithms: ["RS512"] | ||
| }); | ||
| }); | ||
| (0, import_vitest.test)("accepts a team issuer by default", async () => { | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token"); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledTimes(1); | ||
| }); | ||
| (0, import_vitest.test)("accepts the global issuer", async () => { | ||
| mockVerifiedPayload({ | ||
| iss: "https://oidc.vercel.com" | ||
| }); | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token"); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledTimes(1); | ||
| }); | ||
| (0, import_vitest.test)("accepts a matching explicit issuer option", async () => { | ||
| mockVerifiedPayload({ | ||
| iss: "https://oidc.vercel.com/acme" | ||
| }); | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| issuer: "https://oidc.vercel.com/acme" | ||
| }); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledTimes(1); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledWith("token", mocks.remoteJwks, { | ||
| algorithms: ["RS256"], | ||
| issuer: "https://oidc.vercel.com/acme" | ||
| }); | ||
| }); | ||
| (0, import_vitest.test)("uses VERCEL_ENV when VERCEL_TARGET_ENV is missing", async () => { | ||
| delete process.env.VERCEL_TARGET_ENV; | ||
| process.env.VERCEL_ENV = "production"; | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token"); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledTimes(1); | ||
| }); | ||
| (0, import_vitest.test)("accepts custom projectId and environment options", async () => { | ||
| mockVerifiedPayload({ | ||
| project_id: "prj_custom", | ||
| environment: "preview" | ||
| }); | ||
| const result = await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| projectId: "prj_custom", | ||
| environment: "preview" | ||
| }); | ||
| (0, import_vitest.expect)(result.payload.project_id).toBe("prj_custom"); | ||
| (0, import_vitest.expect)(result.payload.environment).toBe("preview"); | ||
| }); | ||
| (0, import_vitest.test)("accepts a matching projectId array option", async () => { | ||
| mockVerifiedPayload({ | ||
| project_id: "prj_allowed" | ||
| }); | ||
| const result = await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| projectId: ["prj_first", "prj_allowed"] | ||
| }); | ||
| (0, import_vitest.expect)(result.payload.project_id).toBe("prj_allowed"); | ||
| }); | ||
| (0, import_vitest.test)("accepts a matching ownerId option", async () => { | ||
| const result = await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| ownerId: "team_team1" | ||
| }); | ||
| (0, import_vitest.expect)(result.payload.owner_id).toBe("team_team1"); | ||
| }); | ||
| (0, import_vitest.test)("does not require ownerId by default", async () => { | ||
| mockVerifiedPayload({ | ||
| owner_id: "team_other" | ||
| }); | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token"); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledTimes(1); | ||
| }); | ||
| (0, import_vitest.test)("allows any project_id claim with projectId wildcard", async () => { | ||
| mockVerifiedPayload({ | ||
| project_id: "prj_other" | ||
| }); | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| projectId: "*", | ||
| ownerId: "team_team1" | ||
| }); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledTimes(1); | ||
| }); | ||
| (0, import_vitest.test)("allows projectId wildcard with audience verification", async () => { | ||
| mockVerifiedPayload({ | ||
| project_id: "prj_other" | ||
| }); | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| projectId: "*", | ||
| audience: "https://oidc.vercel.com/team1" | ||
| }); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledWith("token", mocks.remoteJwks, { | ||
| algorithms: ["RS256"], | ||
| audience: "https://oidc.vercel.com/team1" | ||
| }); | ||
| }); | ||
| (0, import_vitest.test)("requires ownerId or audience when projectId wildcard is used", async () => { | ||
| await (0, import_vitest.expect)( | ||
| (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| projectId: "*" | ||
| }) | ||
| ).rejects.toThrow( | ||
| "Expected ownerId or audience to be provided when projectId is '*'." | ||
| ); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).not.toHaveBeenCalled(); | ||
| }); | ||
| (0, import_vitest.test)("requires ownerId or a non-empty audience when projectId wildcard is used", async () => { | ||
| await (0, import_vitest.expect)( | ||
| (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| projectId: "*", | ||
| audience: [] | ||
| }) | ||
| ).rejects.toThrow( | ||
| "Expected ownerId or audience to be provided when projectId is '*'." | ||
| ); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).not.toHaveBeenCalled(); | ||
| }); | ||
| (0, import_vitest.test)("allows any environment claim with environment wildcard", async () => { | ||
| mockVerifiedPayload({ | ||
| environment: "preview" | ||
| }); | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| environment: "*" | ||
| }); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledTimes(1); | ||
| }); | ||
| (0, import_vitest.test)("accepts a matching environment array option", async () => { | ||
| mockVerifiedPayload({ | ||
| environment: "preview" | ||
| }); | ||
| const result = await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| environment: ["production", "preview"] | ||
| }); | ||
| (0, import_vitest.expect)(result.payload.environment).toBe("preview"); | ||
| }); | ||
| (0, import_vitest.test)("rejects a token from a different project", async () => { | ||
| mockVerifiedPayload({ | ||
| project_id: "prj_other" | ||
| }); | ||
| await (0, import_vitest.expect)((0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token")).rejects.toThrow( | ||
| 'Expected Vercel OIDC token project_id claim to be "prj_test".' | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("rejects a token from a project outside the projectId array", async () => { | ||
| mockVerifiedPayload({ | ||
| project_id: "prj_other" | ||
| }); | ||
| await (0, import_vitest.expect)( | ||
| (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| projectId: ["prj_first", "prj_second"] | ||
| }) | ||
| ).rejects.toThrow( | ||
| 'Expected Vercel OIDC token project_id claim to be one of: "prj_first", "prj_second".' | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("requires a non-empty projectId array", async () => { | ||
| await (0, import_vitest.expect)( | ||
| (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| projectId: [] | ||
| }) | ||
| ).rejects.toThrow( | ||
| "Expected VERCEL_PROJECT_ID to be set or projectId to be provided. Pass projectId: '*' to allow any project_id claim." | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("rejects a token from a different owner", async () => { | ||
| mockVerifiedPayload({ | ||
| owner_id: "team_other" | ||
| }); | ||
| await (0, import_vitest.expect)( | ||
| (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| ownerId: "team_team1" | ||
| }) | ||
| ).rejects.toThrow( | ||
| 'Expected Vercel OIDC token owner_id claim to be "team_team1".' | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("rejects a token from a non-Vercel issuer", async () => { | ||
| mockVerifiedPayload({ | ||
| iss: "https://example.com" | ||
| }); | ||
| await (0, import_vitest.expect)((0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token")).rejects.toThrow( | ||
| 'Expected Vercel OIDC token iss claim to be "https://oidc.vercel.com" or to start with "https://oidc.vercel.com/".' | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("passes explicit issuer option to Jose verification", async () => { | ||
| await (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| issuer: "https://oidc.vercel.com/other-team" | ||
| }); | ||
| (0, import_vitest.expect)(import_jose.jwtVerify).toHaveBeenCalledWith("token", mocks.remoteJwks, { | ||
| algorithms: ["RS256"], | ||
| issuer: "https://oidc.vercel.com/other-team" | ||
| }); | ||
| }); | ||
| (0, import_vitest.test)("rejects a token from an issuer that only shares the prefix text", async () => { | ||
| mockVerifiedPayload({ | ||
| iss: "https://oidc.vercel.com.evil.example" | ||
| }); | ||
| await (0, import_vitest.expect)((0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token")).rejects.toThrow( | ||
| 'Expected Vercel OIDC token iss claim to be "https://oidc.vercel.com" or to start with "https://oidc.vercel.com/".' | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("rejects a token from a different environment", async () => { | ||
| mockVerifiedPayload({ | ||
| environment: "preview" | ||
| }); | ||
| await (0, import_vitest.expect)((0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token")).rejects.toThrow( | ||
| 'Expected Vercel OIDC token environment claim to be "production".' | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("rejects a token from an environment outside the environment array", async () => { | ||
| mockVerifiedPayload({ | ||
| environment: "preview" | ||
| }); | ||
| await (0, import_vitest.expect)( | ||
| (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| environment: ["production", "development"] | ||
| }) | ||
| ).rejects.toThrow( | ||
| 'Expected Vercel OIDC token environment claim to be one of: "production", "development".' | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("requires a projectId default or wildcard", async () => { | ||
| delete process.env.VERCEL_PROJECT_ID; | ||
| await (0, import_vitest.expect)((0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token")).rejects.toThrow( | ||
| "Expected VERCEL_PROJECT_ID to be set or projectId to be provided. Pass projectId: '*' to allow any project_id claim." | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("requires an environment default or wildcard", async () => { | ||
| delete process.env.VERCEL_TARGET_ENV; | ||
| delete process.env.VERCEL_ENV; | ||
| await (0, import_vitest.expect)((0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token")).rejects.toThrow( | ||
| "Expected VERCEL_TARGET_ENV or VERCEL_ENV to be set or environment to be provided. Pass environment: '*' to allow any environment claim." | ||
| ); | ||
| }); | ||
| (0, import_vitest.test)("requires a non-empty environment array", async () => { | ||
| await (0, import_vitest.expect)( | ||
| (0, import_verify_vercel_oidc_token.verifyVercelOidcToken)("token", { | ||
| environment: [] | ||
| }) | ||
| ).rejects.toThrow( | ||
| "Expected VERCEL_TARGET_ENV or VERCEL_ENV to be set or environment to be provided. Pass environment: '*' to allow any environment claim." | ||
| ); | ||
| }); | ||
| function mockVerifiedPayload(payload) { | ||
| import_vitest.vi.mocked(import_jose.jwtVerify).mockResolvedValue({ | ||
| ...verifyResult, | ||
| payload: { | ||
| ...verifyResult.payload, | ||
| ...payload | ||
| } | ||
| }); | ||
| } | ||
| }); |
| [**@vercel/oidc**](../README.md) | ||
| --- | ||
| # Function: verifyVercelOidcToken() | ||
| > **verifyVercelOidcToken**\<`PayloadType`\>(`token`, `options?`): [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`JWTVerifyResult`\<`PayloadType`\>\> | ||
| Defined in: [packages/oidc/src/verify-vercel-oidc-token.ts:53](https://github.com/vercel/vercel/blob/main/packages/oidc/src/verify-vercel-oidc-token.ts#L53) | ||
| Verifies a Vercel OIDC token against Vercel's remote JWKS. | ||
| The issuer must be `https://oidc.vercel.com` or start with | ||
| `https://oidc.vercel.com/`. The JWKS is always | ||
| `https://oidc.vercel.com/.well-known/jwks`. | ||
| Options: | ||
| - `issuer`: Expected `iss` claim verified by Jose. The verified issuer must | ||
| still be `https://oidc.vercel.com` or start with | ||
| `https://oidc.vercel.com/`. | ||
| - `projectId`: Expected `project_id` claim or claims. Defaults to | ||
| `process.env.VERCEL_PROJECT_ID`. Pass an array to allow any matching | ||
| project ID. Pass `'*'` to allow any project ID. When `projectId` is `'*'`, | ||
| either `ownerId` or `audience` is required. | ||
| - `environment`: Expected `environment` claim or claims. Defaults to | ||
| `process.env.VERCEL_TARGET_ENV || process.env.VERCEL_ENV`. Pass an array | ||
| to allow any matching environment. Pass `'*'` to allow any environment. | ||
| - `ownerId`: Expected `owner_id` claim. When omitted, the claim is not | ||
| checked. | ||
| - Any other Jose JWT verification option. | ||
| ## Type Parameters | ||
| ### PayloadType | ||
| `PayloadType` = [`VercelOidcPayload`](../type-aliases/VercelOidcPayload.md) | ||
| ## Parameters | ||
| ### token | ||
| `string` | ||
| The Vercel OIDC token to verify. | ||
| ### options? | ||
| `object` & `JWTVerifyOptions` | ||
| Optional Jose JWT verification options. | ||
| ## Returns | ||
| [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<`JWTVerifyResult`\<`PayloadType`\>\> | ||
| Jose's verified JWT result. |
| [**@vercel/oidc**](../README.md) | ||
| --- | ||
| # Type Alias: VercelOidcPayload | ||
| > **VercelOidcPayload** = `JWTPayload` & `object` | ||
| Defined in: [packages/oidc/src/verify-vercel-oidc-token.ts:16](https://github.com/vercel/vercel/blob/main/packages/oidc/src/verify-vercel-oidc-token.ts#L16) | ||
| ## Type Declaration | ||
| ### aud | ||
| > **aud**: `string` | ||
| ### environment | ||
| > **environment**: `string` | ||
| ### external_sub? | ||
| > `optional` **external_sub?**: `string` | ||
| ### iss | ||
| > **iss**: `string` | ||
| ### owner_id | ||
| > **owner_id**: `string` | ||
| ### project_id | ||
| > **project_id**: `string` | ||
| ### sub | ||
| > **sub**: `string` |
+6
-0
| # @vercel/oidc | ||
| ## 3.6.1 | ||
| ### Patch Changes | ||
| - 01cf6c2: Add `verifyVercelOidcToken` for verifying Vercel OIDC tokens against Vercel's remote JWKS. | ||
| ## 3.6.0 | ||
@@ -4,0 +10,0 @@ |
| export { getContext } from './get-context'; | ||
| export { verifyVercelOidcToken, type VercelOidcPayload, } from './verify-vercel-oidc-token'; | ||
| export { AccessTokenMissingError, RefreshAccessTokenFailedError, } from './auth-errors'; | ||
@@ -3,0 +4,0 @@ export declare function getVercelOidcToken(): Promise<string>; |
@@ -26,6 +26,8 @@ "use strict"; | ||
| getVercelOidcTokenSync: () => getVercelOidcTokenSync, | ||
| getVercelToken: () => getVercelToken | ||
| getVercelToken: () => getVercelToken, | ||
| verifyVercelOidcToken: () => import_verify_vercel_oidc_token.verifyVercelOidcToken | ||
| }); | ||
| module.exports = __toCommonJS(index_browser_exports); | ||
| var import_get_context = require("./get-context"); | ||
| var import_verify_vercel_oidc_token = require("./verify-vercel-oidc-token"); | ||
| var import_auth_errors = require("./auth-errors"); | ||
@@ -48,3 +50,4 @@ async function getVercelOidcToken() { | ||
| getVercelOidcTokenSync, | ||
| getVercelToken | ||
| getVercelToken, | ||
| verifyVercelOidcToken | ||
| }); |
| export { getContext } from './get-context'; | ||
| export { verifyVercelOidcToken, type VercelOidcPayload, } from './verify-vercel-oidc-token'; | ||
| export { AccessTokenMissingError, RefreshAccessTokenFailedError, } from './auth-errors'; | ||
@@ -3,0 +4,0 @@ export { getVercelOidcTokenSync } from './get-vercel-oidc-token-sync'; |
@@ -26,3 +26,4 @@ "use strict"; | ||
| getVercelOidcTokenSync: () => import_get_vercel_oidc_token_sync2.getVercelOidcTokenSync, | ||
| getVercelToken: () => getVercelToken | ||
| getVercelToken: () => getVercelToken, | ||
| verifyVercelOidcToken: () => import_verify_vercel_oidc_token.verifyVercelOidcToken | ||
| }); | ||
@@ -32,2 +33,3 @@ module.exports = __toCommonJS(index_edge_light_exports); | ||
| var import_get_context = require("./get-context"); | ||
| var import_verify_vercel_oidc_token = require("./verify-vercel-oidc-token"); | ||
| var import_auth_errors = require("./auth-errors"); | ||
@@ -48,3 +50,4 @@ var import_get_vercel_oidc_token_sync2 = require("./get-vercel-oidc-token-sync"); | ||
| getVercelOidcTokenSync, | ||
| getVercelToken | ||
| getVercelToken, | ||
| verifyVercelOidcToken | ||
| }); |
+1
-0
| export { getVercelOidcToken } from './get-vercel-oidc-token-with-refresh'; | ||
| export { getVercelOidcTokenSync } from './get-vercel-oidc-token-sync'; | ||
| export { getContext } from './get-context'; | ||
| export { verifyVercelOidcToken, type VercelOidcPayload, } from './verify-vercel-oidc-token'; | ||
| export { AccessTokenMissingError, RefreshAccessTokenFailedError, } from './auth-errors'; | ||
| export { getVercelToken } from './token-util'; |
+5
-2
@@ -26,3 +26,4 @@ "use strict"; | ||
| getVercelOidcTokenSync: () => import_get_vercel_oidc_token_sync.getVercelOidcTokenSync, | ||
| getVercelToken: () => import_token_util.getVercelToken | ||
| getVercelToken: () => import_token_util.getVercelToken, | ||
| verifyVercelOidcToken: () => import_verify_vercel_oidc_token.verifyVercelOidcToken | ||
| }); | ||
@@ -33,2 +34,3 @@ module.exports = __toCommonJS(src_exports); | ||
| var import_get_context = require("./get-context"); | ||
| var import_verify_vercel_oidc_token = require("./verify-vercel-oidc-token"); | ||
| var import_auth_errors = require("./auth-errors"); | ||
@@ -43,3 +45,4 @@ var import_token_util = require("./token-util"); | ||
| getVercelOidcTokenSync, | ||
| getVercelToken | ||
| getVercelToken, | ||
| verifyVercelOidcToken | ||
| }); |
+5
-0
@@ -12,2 +12,6 @@ **@vercel/oidc** | ||
| ## Type Aliases | ||
| - [VercelOidcPayload](type-aliases/VercelOidcPayload.md) | ||
| ## Functions | ||
@@ -19,1 +23,2 @@ | ||
| - [getVercelToken](functions/getVercelToken.md) | ||
| - [verifyVercelOidcToken](functions/verifyVercelOidcToken.md) |
+2
-1
@@ -21,3 +21,3 @@ { | ||
| }, | ||
| "version": "3.6.0", | ||
| "version": "3.6.1", | ||
| "repository": { | ||
@@ -32,2 +32,3 @@ "directory": "packages/oidc", | ||
| "dependencies": { | ||
| "jose": "^5.9.6", | ||
| "@vercel/cli-config": "0.2.0", | ||
@@ -34,0 +35,0 @@ "@vercel/cli-exec": "0.1.1" |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
134226
20.72%49
13.95%2470
25%3
50%49
40%+ Added
+ Added