Skip to content

Commit 2c2c3d8

Browse files
committed
add id_token validation logic for code flow
1 parent 10b58d7 commit 2c2c3d8

File tree

2 files changed

+49
-15
lines changed

2 files changed

+49
-15
lines changed

src/JoseUtil.js

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class JoseUtil {
6262
}
6363
}
6464

65-
static _validateJwt(jwt, key, issuer, audience, clockSkew, now) {
65+
static validateJwtAttributes(jwt, issuer, audience, clockSkew, now) {
6666
if (!clockSkew) {
6767
clockSkew = 0;
6868
}
@@ -91,6 +91,10 @@ export class JoseUtil {
9191
Log.error("JoseUtil._validateJwt: Invalid audience in token", payload.aud);
9292
return Promise.reject(new Error("Invalid audience in token: " + payload.aud));
9393
}
94+
if (payload.azp && payload.azp !== audience) {
95+
Log.error("JoseUtil._validateJwt: Invalid azp in token", payload.azp);
96+
return Promise.reject(new Error("Invalid azp in token: " + payload.azp));
97+
}
9498

9599
var lowerNow = now + clockSkew;
96100
var upperNow = now - clockSkew;
@@ -118,18 +122,25 @@ export class JoseUtil {
118122
return Promise.reject(new Error("exp is in the past:" + payload.exp));
119123
}
120124

121-
try {
122-
if (!jws.JWS.verify(jwt, key, AllowedSigningAlgs)) {
123-
Log.error("JoseUtil._validateJwt: signature validation failed");
125+
return Promise.resolve(payload);
126+
}
127+
128+
static _validateJwt(jwt, key, issuer, audience, clockSkew, now) {
129+
130+
return JoseUtil.validateJwtAttributes(jwt, issuer, audience, clockSkew, now).then(payload => {
131+
try {
132+
if (!jws.JWS.verify(jwt, key, AllowedSigningAlgs)) {
133+
Log.error("JoseUtil._validateJwt: signature validation failed");
134+
return Promise.reject(new Error("signature validation failed"));
135+
}
136+
137+
return payload;
138+
}
139+
catch (e) {
140+
Log.error(e && e.message || e);
124141
return Promise.reject(new Error("signature validation failed"));
125142
}
126-
}
127-
catch (e) {
128-
Log.error(e && e.message || e);
129-
return Promise.reject(new Error("signature validation failed"));
130-
}
131-
132-
return Promise.resolve();
143+
});
133144
}
134145

135146
static hashString(value, alg) {

src/ResponseValidator.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,8 @@ export class ResponseValidator {
249249
}
250250

251251
if (response.id_token) {
252-
Log.debug("ResponseValidator._processCode: token response successful, parsing id_token");
253-
var jwt = this._joseUtil.parseJwt(response.id_token);
254-
response.profile = jwt.payload;
255-
//return this._validateIdToken(state, response);
252+
Log.debug("ResponseValidator._processCode: token response successful, processing id_token");
253+
return this._validateIdTokenAttributes(state, response);
256254
}
257255
else {
258256
Log.debug("ResponseValidator._processCode: token response successful, returning response");
@@ -262,6 +260,31 @@ export class ResponseValidator {
262260
});
263261
}
264262

263+
_validateIdTokenAttributes(state, response) {
264+
return this._metadataService.getIssuer().then(issuer => {
265+
266+
let audience = state.client_id;
267+
let clockSkewInSeconds = this._settings.clockSkew;
268+
Log.debug("ResponseValidator._validateIdTokenAttributes: Validaing JWT attributes; using clock skew (in seconds) of: ", clockSkewInSeconds);
269+
270+
return this._joseUtil.validateJwtAttributes(response.id_token, issuer, audience, clockSkewInSeconds).then(payload => {
271+
272+
if (state.nonce && state.nonce !== payload.nonce) {
273+
Log.error("ResponseValidator._validateIdTokenAttributes: Invalid nonce in id_token");
274+
return Promise.reject(new Error("Invalid nonce in id_token"));
275+
}
276+
277+
if (!payload.sub) {
278+
Log.error("ResponseValidator._validateIdTokenAttributes: No sub present in id_token");
279+
return Promise.reject(new Error("No sub present in id_token"));
280+
}
281+
282+
response.profile = payload;
283+
return response;
284+
});
285+
});
286+
}
287+
265288
_validateIdTokenAndAccessToken(state, response) {
266289
return this._validateIdToken(state, response).then(response => {
267290
return this._validateAccessToken(response);

0 commit comments

Comments
 (0)