@@ -31,15 +31,6 @@ export default (
3131 encodedPayload : Uint8Array ,
3232 options : JWTClaimVerificationOptions = { } ,
3333) => {
34- const { typ } = options
35- if (
36- typ &&
37- ( typeof protectedHeader ! . typ !== 'string' ||
38- normalizeTyp ( protectedHeader ! . typ ) !== normalizeTyp ( typ ) )
39- ) {
40- throw new JWTClaimValidationFailed ( 'unexpected "typ" JWT header value' , 'typ' , 'check_failed' )
41- }
42-
4334 let payload ! : { [ propName : string ] : unknown }
4435 try {
4536 payload = JSON . parse ( decoder . decode ( encodedPayload ) )
@@ -51,6 +42,20 @@ export default (
5142 throw new JWTInvalid ( 'JWT Claims Set must be a top-level JSON object' )
5243 }
5344
45+ const { typ } = options
46+ if (
47+ typ &&
48+ ( typeof protectedHeader ! . typ !== 'string' ||
49+ normalizeTyp ( protectedHeader ! . typ ) !== normalizeTyp ( typ ) )
50+ ) {
51+ throw new JWTClaimValidationFailed (
52+ 'unexpected "typ" JWT header value' ,
53+ payload ,
54+ 'typ' ,
55+ 'check_failed' ,
56+ )
57+ }
58+
5459 const { requiredClaims = [ ] , issuer, subject, audience, maxTokenAge } = options
5560
5661 const presenceCheck = [ ...requiredClaims ]
@@ -62,23 +67,43 @@ export default (
6267
6368 for ( const claim of new Set ( presenceCheck . reverse ( ) ) ) {
6469 if ( ! ( claim in payload ) ) {
65- throw new JWTClaimValidationFailed ( `missing required "${ claim } " claim` , claim , 'missing' )
70+ throw new JWTClaimValidationFailed (
71+ `missing required "${ claim } " claim` ,
72+ payload ,
73+ claim ,
74+ 'missing' ,
75+ )
6676 }
6777 }
6878
6979 if ( issuer && ! ( < unknown [ ] > ( Array . isArray ( issuer ) ? issuer : [ issuer ] ) ) . includes ( payload . iss ! ) ) {
70- throw new JWTClaimValidationFailed ( 'unexpected "iss" claim value' , 'iss' , 'check_failed' )
80+ throw new JWTClaimValidationFailed (
81+ 'unexpected "iss" claim value' ,
82+ payload ,
83+ 'iss' ,
84+ 'check_failed' ,
85+ )
7186 }
7287
7388 if ( subject && payload . sub !== subject ) {
74- throw new JWTClaimValidationFailed ( 'unexpected "sub" claim value' , 'sub' , 'check_failed' )
89+ throw new JWTClaimValidationFailed (
90+ 'unexpected "sub" claim value' ,
91+ payload ,
92+ 'sub' ,
93+ 'check_failed' ,
94+ )
7595 }
7696
7797 if (
7898 audience &&
7999 ! checkAudiencePresence ( payload . aud , typeof audience === 'string' ? [ audience ] : audience )
80100 ) {
81- throw new JWTClaimValidationFailed ( 'unexpected "aud" claim value' , 'aud' , 'check_failed' )
101+ throw new JWTClaimValidationFailed (
102+ 'unexpected "aud" claim value' ,
103+ payload ,
104+ 'aud' ,
105+ 'check_failed' ,
106+ )
82107 }
83108
84109 let tolerance : number
@@ -100,16 +125,17 @@ export default (
100125 const now = epoch ( currentDate || new Date ( ) )
101126
102127 if ( ( payload . iat !== undefined || maxTokenAge ) && typeof payload . iat !== 'number' ) {
103- throw new JWTClaimValidationFailed ( '"iat" claim must be a number' , 'iat' , 'invalid' )
128+ throw new JWTClaimValidationFailed ( '"iat" claim must be a number' , payload , 'iat' , 'invalid' )
104129 }
105130
106131 if ( payload . nbf !== undefined ) {
107132 if ( typeof payload . nbf !== 'number' ) {
108- throw new JWTClaimValidationFailed ( '"nbf" claim must be a number' , 'nbf' , 'invalid' )
133+ throw new JWTClaimValidationFailed ( '"nbf" claim must be a number' , payload , 'nbf' , 'invalid' )
109134 }
110135 if ( payload . nbf > now + tolerance ) {
111136 throw new JWTClaimValidationFailed (
112137 '"nbf" claim timestamp check failed' ,
138+ payload ,
113139 'nbf' ,
114140 'check_failed' ,
115141 )
@@ -118,10 +144,10 @@ export default (
118144
119145 if ( payload . exp !== undefined ) {
120146 if ( typeof payload . exp !== 'number' ) {
121- throw new JWTClaimValidationFailed ( '"exp" claim must be a number' , 'exp' , 'invalid' )
147+ throw new JWTClaimValidationFailed ( '"exp" claim must be a number' , payload , 'exp' , 'invalid' )
122148 }
123149 if ( payload . exp <= now - tolerance ) {
124- throw new JWTExpired ( '"exp" claim timestamp check failed' , 'exp' , 'check_failed' )
150+ throw new JWTExpired ( '"exp" claim timestamp check failed' , payload , 'exp' , 'check_failed' )
125151 }
126152 }
127153
@@ -132,6 +158,7 @@ export default (
132158 if ( age - tolerance > max ) {
133159 throw new JWTExpired (
134160 '"iat" claim timestamp check failed (too far in the past)' ,
161+ payload ,
135162 'iat' ,
136163 'check_failed' ,
137164 )
@@ -140,6 +167,7 @@ export default (
140167 if ( age < 0 - tolerance ) {
141168 throw new JWTClaimValidationFailed (
142169 '"iat" claim timestamp check failed (it should be in the past)' ,
170+ payload ,
143171 'iat' ,
144172 'check_failed' ,
145173 )
0 commit comments