@@ -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