fix(revocation): avoid revoking expired tokens and fail gracefully (#95)

Fixes #72

If an Actions job is long enough, more than an hour can pass between
creating and revoking the App token in the post-job clean up step. Since
the token itself is used to authenticate with the revoke API, an expired
token will fail to be revoked.

This PR saves the token expiration in the actions state and uses that in
the post step to determine if the token can be revoked. I've also added
error handling to the revoke token API call, as it's unlikely that users
would want their job to fail if the token can't be revoked.
This commit is contained in:
Josh Gross
2024-01-19 10:45:12 -05:00
committed by GitHub
parent f04aa94d10
commit 0c014070f9
10 changed files with 155 additions and 21 deletions
+1
View File
@@ -10420,6 +10420,7 @@ async function main(appId2, privateKey2, owner2, repositories2, core2, createApp
core2.setOutput("token", authentication.token);
if (!skipTokenRevoke2) {
core2.saveState("token", authentication.token);
core2.setOutput("expiresAt", authentication.expiresAt);
}
}
async function getTokenFromOwner(request2, auth, parsedOwner) {
+22 -6
View File
@@ -3003,12 +3003,28 @@ async function post(core2, request2) {
core2.info("Token is not set");
return;
}
await request2("DELETE /installation/token", {
headers: {
authorization: `token ${token}`
}
});
core2.info("Token revoked");
const expiresAt = core2.getState("expiresAt");
if (expiresAt && tokenExpiresIn(expiresAt) < 0) {
core2.info("Token already expired");
return;
}
try {
await request2("DELETE /installation/token", {
headers: {
authorization: `token ${token}`
}
});
core2.info("Token revoked");
} catch (error) {
core2.warning(
`Token revocation failed: ${error.message}`
);
}
}
function tokenExpiresIn(expiresAt) {
const now = /* @__PURE__ */ new Date();
const expiresAtDate = new Date(expiresAt);
return Math.round((expiresAtDate.getTime() - now.getTime()) / 1e3);
}
// lib/request.js