in src/jwk.ts [239:281]
public async getJwk(
jwksUri: string,
decomposedJwt: DecomposedJwt
): Promise<Jwk> {
if (typeof decomposedJwt.header.kid !== "string") {
throw new JwtWithoutValidKidError(
"JWT header does not have valid kid claim"
);
}
// Try to get JWK from cache:
let jwk = this.jwksCache
.get(jwksUri)
?.keys.find((key) => key.kid === decomposedJwt.header.kid);
if (jwk) {
return jwk;
}
// Await any wait period that is currently in effect
// This prevents us from flooding the JWKS URI with requests
await this.penaltyBox.wait(jwksUri, decomposedJwt.header.kid);
// Fetch the JWKS and (try to) locate the JWK
const jwks = await this.getJwks(jwksUri);
jwk = jwks.keys.find((key) => key.kid === decomposedJwt.header.kid);
// If the JWK could not be located, someone might be messing around with us
// Register the failed attempt with the penaltyBox, so it can enforce a wait period
// before trying again next time (instead of flooding the JWKS URI with requests)
if (!jwk) {
this.penaltyBox.registerFailedAttempt(jwksUri, decomposedJwt.header.kid);
throw new KidNotFoundInJwksError(
`JWK for kid "${decomposedJwt.header.kid}" not found in the JWKS`
);
} else {
this.penaltyBox.registerSuccessfulAttempt(
jwksUri,
decomposedJwt.header.kid
);
}
return jwk;
}