Skip to content

Commit 0acd3ab

Browse files
committed
add missing response validation
1 parent c07c69f commit 0acd3ab

File tree

1 file changed

+53
-9
lines changed

1 file changed

+53
-9
lines changed

src/ResponseValidator.js

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ export default class ResponseValidator {
133133
Log.debug("loading user info");
134134

135135
return this._userInfoService.getClaims(response.access_token).then(claims => {
136+
Log.debug("user info claims received from user info endpoint");
137+
138+
if (claims.sub !== response.profile.sub) {
139+
Log.error("sub from user info endpoint does not match sub in id_token");
140+
return Promise.reject(new Error("sub from user info endpoint does not match sub in id_token"));
141+
}
136142

137143
response.profile = this._mergeClaims(response.profile, claims);
138144
Log.debug("user info claims received, updated profile:", response.profile);
@@ -254,25 +260,29 @@ export default class ResponseValidator {
254260
}
255261

256262
Log.debug("Received signing keys");
263+
let key;
257264
if (!kid) {
265+
keys = this._filterByAlg(keys, jwt.header.alg);
266+
258267
if (keys.length > 1) {
259-
Log.error("No kid found in id_token");
260-
return Promise.reject(new Error("No kid found in id_token"));
268+
Log.error("No kid found in id_token and more than one key found in metadata");
269+
return Promise.reject(new Error("No kid found in id_token and more than one key found in metadata"));
261270
}
262271
else {
263272
// kid is mandatory only when there are multiple keys in the referenced JWK Set document
264273
// see http://openid.net/specs/openid-connect-core-1_0.html#Signing
265-
kid = keys[0].kid;
274+
key = keys[0];
266275
}
267276
}
268-
269-
let key = keys.filter(key => {
270-
return key.kid === kid;
271-
})[0];
277+
else {
278+
key = keys.filter(key => {
279+
return key.kid === kid;
280+
})[0];
281+
}
272282

273283
if (!key) {
274-
Log.error("No key matching kid found in signing keys");
275-
return Promise.reject(new Error("No key matching kid found in signing keys"));
284+
Log.error("No key matching kid or alg found in signing keys");
285+
return Promise.reject(new Error("No key matching kid or alg found in signing keys"));
276286
}
277287

278288
let audience = state.client_id;
@@ -283,6 +293,11 @@ export default class ResponseValidator {
283293
return this._joseUtil.validateJwt(response.id_token, key, issuer, audience, clockSkewInSeconds).then(()=>{
284294
Log.debug("JWT validation successful");
285295

296+
if (!jwt.payload.sub) {
297+
Log.error("No sub present in id_token");
298+
return Promise.reject(new Error("No sub present in id_token"));
299+
}
300+
286301
response.profile = jwt.payload;
287302

288303
return response;
@@ -291,6 +306,35 @@ export default class ResponseValidator {
291306
});
292307
}
293308

309+
_filterByAlg(keys, alg){
310+
Log.debug("ResponseValidator._filterByAlg", alg);
311+
312+
var kty = null;
313+
if (alg.startsWith("RS")) {
314+
kty = "RSA";
315+
}
316+
else if (alg.startsWith("PS")) {
317+
kty = "PS";
318+
}
319+
else if (alg.startsWith("ES")) {
320+
kty = "EC";
321+
}
322+
else {
323+
Log.debug("alg not supported: ", alg);
324+
return [];
325+
}
326+
327+
Log.debug("Looking for keys that match kty: ", kty);
328+
329+
keys = keys.filter(key => {
330+
return key.kty === kty;
331+
});
332+
333+
Log.debug("Number of keys that match kty: ", kty, keys.length);
334+
335+
return keys;
336+
}
337+
294338
_validateAccessToken(response) {
295339
Log.debug("ResponseValidator._validateAccessToken");
296340

0 commit comments

Comments
 (0)