Skip to content

Commit

Permalink
Merge pull request #18 from microsoft-healthcare-madison/throw-auth-e…
Browse files Browse the repository at this point in the history
…rrors

Throw errors instead of logging to server console
  • Loading branch information
barabo authored Sep 10, 2021
2 parents d3ae416 + 9b13c20 commit e18e025
Showing 1 changed file with 40 additions and 14 deletions.
54 changes: 40 additions & 14 deletions src/TokenHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,30 +180,56 @@ class TokenHandler extends SMARTHandler {
// TODO: if multiple keys, try them all.
const jwt = this.request.body.client_assertion;
const validated = await jose.JWS.createVerify(key).verify(jwt);
console.log('JWT signature verified');

// Note: at this point the signature is cryptographically verified.

// Inspect the verification result for standards compliance.
const payload = JSON.parse(validated.payload);
if (validated.header.typ !== 'JWT') {
console.error(`Expected validation type (${validated.header.type}) to equal "JWT"`);
const typ = validated.header['typ'];
if (typ !== 'JWT') {
throw Lib.OAuthError.from({
code : 401,
error: 'invalid assertion',
msg : `Expected assertion type (${typ}) to be "JWT"`,
}, 'JWT', typ);
}
const alg = validated.header.alg;
const alg = validated.header['alg'];
if (alg !== 'RS384' && alg !== 'ES384') {
console.error(`Expected one of the validation algorithms ('ES384', 'RS384'), found: ${alg}`);
throw Lib.OAuthError.from({
code : 401,
error: 'invalid assertion',
msg : `Expected one of ('ES384', 'RS384'), found: '${alg}'.`,
}, 'expected ES384 or RS384', alg);
}
if (key.kid !== validated.header.kid) {
console.error(`Expected JWT kid (${validated.header.kid}) to match (${key.kid})`);
const kid = validated.header['kid'];
if (key.kid !== kid) {
throw Lib.OAuthError.from({
code : 403,
error: 'invalid key',
msg : `Expected JWT kid (${kid}) to match (${key.kid})`,
}, key.kid, kid);
}
const fiveMinutesFromNow = Math.floor(Date.now() / 1000) + 300;
if (payload.exp > fiveMinutesFromNow) {
const error = `JWT expiration (${payload.exp}) is too permissive, should be no greater than 5 minutes.`;
console.error(error);
throw Lib.OAuthError.from({
code : 403,
error: 'invalid assertion',
msg : `JWT expiration (${payload.exp}) is too permissive, should be no greater than 5 minutes.`,
}, `less than ${fiveMinutesFromNow}`, `${payload.exp}`);
}
if (payload.iss !== payload.sub) {
console.error(`Mismatched JWT iss (${payload.iss}) != sub (${payload.sub})`);
throw Lib.OAuthError.from({
code : 401,
error: 'invalid assertion',
msg : `Mismatched JWT iss (${payload.iss}) != sub (${payload.sub})`,
}, `equal iss and sub`, `'${payload.iss}' != '${payload.sub}'`);
}
// TODO: get the scheme in here, too?
const tokenUri = this.request.headers.host + this.request.originalUrl;
if (!payload.aud.endsWith(tokenUri)) {
console.error(`Expected JWT.aud (${payload.aud}) to match the token URI (${tokenUri})`);
// TODO: don't rely on the request headers to get the URI of this handler.
const tokenUri = this.request.get('host') + this.request.originalUrl;
if (!payload.aud.endsWith(`://${tokenUri}`)) {
const message = `Expected JWT.aud (${payload.aud}) to match the token URI (${tokenUri})`;
console.error(message);
// TODO: raise an exception when a more reliable way to determine the handler URI is known.
}
}
}
Expand Down

0 comments on commit e18e025

Please sign in to comment.