Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 30 additions & 24 deletions lib/utils/oidc.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ async function oidc ({ packageName, registry, opts, config }) {
/** @see https://github.com/watson/ci-info/blob/v4.2.0/vendors.json#L161C13-L161C22 */
ciInfo.GITLAB
)) {
log.silly('oidc', 'Not running OIDC, not in a supported CI environment')
return undefined
}

Expand Down Expand Up @@ -67,14 +68,11 @@ async function oidc ({ packageName, registry, opts, config }) {
process.env.ACTIONS_ID_TOKEN_REQUEST_URL &&
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN
) {
log.silly('oidc', '"GITHUB_ACTIONS" detected with "ACTIONS_ID_" envs, fetching id_token')

/**
* The specification for an audience is `npm:registry.npmjs.org`,
* where "registry.npmjs.org" can be any supported registry.
*/
const audience = `npm:${new URL(registry).hostname}`
log.silly('oidc', `Using audience: ${audience}`)
const url = new URL(process.env.ACTIONS_ID_TOKEN_REQUEST_URL)
url.searchParams.append('audience', audience)
const startTime = Date.now()
Expand All @@ -96,17 +94,19 @@ async function oidc ({ packageName, registry, opts, config }) {
const json = await response.json()

if (!response.ok) {
throw new Error(`Failed to fetch id_token from GitHub: received an invalid response`)
log.verbose('oidc', `Failed to fetch id_token from GitHub: received an invalid response`)
return undefined
}

if (!json.value) {
throw new Error(`Failed to fetch id_token from GitHub: missing value`)
log.verbose('oidc', `Failed to fetch id_token from GitHub: missing value`)
return undefined
}

log.silly('oidc', 'GITHUB_ACTIONS valid fetch response for id_token')
idToken = json.value
} else {
throw new Error('GITHUB_ACTIONS detected. If you intend to publish using OIDC, please set workflow permissions for `id-token: write`')
log.silly('oidc', 'GITHUB_ACTIONS detected. If you intend to publish using OIDC, please set workflow permissions for `id-token: write`')
return undefined
}
}
}
Expand All @@ -130,22 +130,31 @@ async function oidc ({ packageName, registry, opts, config }) {
}

const escapedPackageName = npa(packageName).escapedName
const response = await npmFetch.json(new URL(`/-/npm/v1/oidc/token/exchange/package/${escapedPackageName}`, registry), {
...{
...opts,
[authTokenKey]: idToken, // Use the idToken as the auth token for the request
},
method: 'POST',
headers: {
...opts.headers,
'Content-Type': 'application/json',
// this will not work because the existing auth token will replace it.
// authorization: `Bearer ${idToken}`,
},
})
let response
try {
response = await npmFetch.json(new URL(`/-/npm/v1/oidc/token/exchange/package/${escapedPackageName}`, registry), {
...{
...opts,
[authTokenKey]: idToken, // Use the idToken as the auth token for the request
},
method: 'POST',
headers: {
...opts.headers,
'Content-Type': 'application/json',
// this will not work because the existing auth token will replace it.
// authorization: `Bearer ${idToken}`,
},
})
} catch (error) {
if (error?.body?.message) {
log.verbose('oidc', `Registry body response error message "${error.body.message}"`)
}
return undefined
}

if (!response?.token) {
throw new Error('OIDC token exchange failure: missing token in response body')
log.verbose('oidc', 'OIDC token exchange failure: missing token in response body')
return undefined
}
/*
* The "opts" object is a clone of npm.flatOptions and is passed through the `publish` command,
Expand All @@ -158,9 +167,6 @@ async function oidc ({ packageName, registry, opts, config }) {
log.silly('oidc', `OIDC token successfully retrieved`)
} catch (error) {
log.verbose('oidc', error.message)
if (error?.body?.message) {
log.verbose('oidc', `Registry body response error message "${error.body.message}"`)
}
}
return undefined
}
Expand Down
20 changes: 20 additions & 0 deletions test/lib/commands/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -1223,5 +1223,25 @@ t.test('oidc token exchange', t => {
},
}))

t.test('trigger any generic error within the try catch block', oidcPublishTest({
config: {
'//registry.npmjs.org/:_authToken': 'existing-fallback-token',
},
publishOptions: {
token: 'existing-fallback-token',
},
load: {
mocks: {
'ci-info': Object.defineProperty({}, 'GITHUB_ACTIONS', {
get () {
throw new Error('getter error')
},
enumerable: true,
configurable: true,
}),
},
},
}))

t.end()
})
Loading