diff --git a/src/TokenHandler.js b/src/TokenHandler.js index fa5cedee..e73cb08f 100644 --- a/src/TokenHandler.js +++ b/src/TokenHandler.js @@ -181,31 +181,33 @@ class TokenHandler extends SMARTHandler { const jwt = this.request.body.client_assertion; const validated = await jose.JWS.createVerify(key).verify(jwt); - // Note: at this point the signature is algorithmically verified. + // Note: at this point the signature is cryptographically verified. - // Inspect the verification for standards compliance. + // Inspect the verification result for standards compliance. const payload = JSON.parse(validated.payload); - if (validated.header.typ !== 'JWT') { + const typ = validated.header['typ']; + if (typ !== 'JWT') { throw Lib.OAuthError.from({ code : 401, error: 'invalid assertion', - msg : `Expected assertion type (${validated.header.type}) to equal "JWT"`, - }, 'JWT', validated.header.type); + 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') { throw Lib.OAuthError.from({ code : 401, error: 'invalid assertion', - msg : `Expected one of the following algorithms ('ES384', 'RS384'), found: ${alg}`, - }, 'ES384 or RS384', alg); + msg : `Expected one of ('ES384', 'RS384'), found: '${alg}'.`, + }, 'expected ES384 or RS384', alg); } - if (key.kid !== validated.header.kid) { + const kid = validated.header['kid']; + if (key.kid !== kid) { throw Lib.OAuthError.from({ code : 403, error: 'invalid key', - msg : `Expected JWT kid (${validated.header.kid}) to match (${key.kid})`, - }, key.kid, validated.header.kid); + msg : `Expected JWT kid (${kid}) to match (${key.kid})`, + }, key.kid, kid); } const fiveMinutesFromNow = Math.floor(Date.now() / 1000) + 300; if (payload.exp > fiveMinutesFromNow) { @@ -222,14 +224,12 @@ class TokenHandler extends SMARTHandler { 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)) { - throw Lib.OAuthError.from({ - code : 403, - error: 'invalid assertion', - msg : `Expected JWT.aud (${payload.aud}) to match the token URI (${tokenUri})`, - }, `ends with '${tokenUri}'`, payload.aud); + // 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. } } }