1
- import { decodeBase64UrlBytes } from "./base64" ;
1
+ import { decodeBase64Url } from "./base64" ;
2
2
import { JwtError , JwtErrorCode } from "./errors" ;
3
+ import { utf8Decoder , utf8Encoder } from "./utf8" ;
3
4
import { isNonEmptyString , isNumber , isString } from "./validator" ;
4
5
5
6
export interface TokenDecoder {
@@ -10,7 +11,7 @@ export interface JsonWebKeyWithKid extends JsonWebKey {
10
11
kid : string ;
11
12
}
12
13
13
- type DecodedHeader = { kid : string ; alg : "RS256" } & Record < string , any > ;
14
+ export type DecodedHeader = { kid : string ; alg : "RS256" } & Record < string , any > ;
14
15
15
16
export type DecodedPayload = {
16
17
aud : string ;
@@ -52,7 +53,7 @@ export class RS256Token {
52
53
return new RS256Token ( token , {
53
54
header,
54
55
payload,
55
- signature : decodeBase64UrlBytes ( tokenParts [ 2 ] ) ,
56
+ signature : decodeBase64Url ( tokenParts [ 2 ] ) ,
56
57
} ) ;
57
58
}
58
59
@@ -61,7 +62,7 @@ export class RS256Token {
61
62
62
63
// `${token.header}.${token.payload}`
63
64
const trimmedSignature = rawToken . substring ( 0 , rawToken . lastIndexOf ( "." ) ) ;
64
- return new TextEncoder ( ) . encode ( trimmedSignature ) ;
65
+ return utf8Encoder . encode ( trimmedSignature ) ;
65
66
}
66
67
}
67
68
@@ -93,42 +94,42 @@ const decodePayload = (
93
94
if ( ! isNonEmptyString ( payload . aud ) ) {
94
95
throw new JwtError (
95
96
JwtErrorCode . INVALID_ARGUMENT ,
96
- `"aud" claim must be a string but got ${ payload . aud } } `
97
+ `"aud" claim must be a string but got " ${ payload . aud } " `
97
98
) ;
98
99
}
99
100
100
101
if ( ! isNonEmptyString ( payload . sub ) ) {
101
102
throw new JwtError (
102
103
JwtErrorCode . INVALID_ARGUMENT ,
103
- `"sub" claim must be a string but got ${ payload . sub } }`
104
+ `"sub" claim must be a string but got " ${ payload . sub } }" `
104
105
) ;
105
106
}
106
107
107
108
if ( ! isNonEmptyString ( payload . iss ) ) {
108
109
throw new JwtError (
109
110
JwtErrorCode . INVALID_ARGUMENT ,
110
- `"iss" claim must be a string but got ${ payload . iss } }`
111
+ `"iss" claim must be a string but got " ${ payload . iss } }" `
111
112
) ;
112
113
}
113
114
114
115
if ( ! isNumber ( payload . iat ) ) {
115
116
throw new JwtError (
116
117
JwtErrorCode . INVALID_ARGUMENT ,
117
- `"iat" claim must be a number but got ${ payload . iat } }`
118
+ `"iat" claim must be a number but got " ${ payload . iat } }" `
118
119
) ;
119
120
}
120
121
121
122
if ( currentTimestamp < payload . iat ) {
122
123
throw new JwtError (
123
124
JwtErrorCode . INVALID_ARGUMENT ,
124
- `Incorrect "iat" claim must be a newer than "${ currentTimestamp } " (iat: ${ payload . iat } )`
125
+ `Incorrect "iat" claim must be a newer than "${ currentTimestamp } " (iat: " ${ payload . iat } " )`
125
126
) ;
126
127
}
127
128
128
129
if ( ! isNumber ( payload . exp ) ) {
129
130
throw new JwtError (
130
131
JwtErrorCode . INVALID_ARGUMENT ,
131
- `"exp" claim must be a number but got ${ payload . exp } }`
132
+ `"exp" claim must be a number but got " ${ payload . exp } " }`
132
133
) ;
133
134
}
134
135
@@ -143,21 +144,9 @@ const decodePayload = (
143
144
} ;
144
145
145
146
const decodeBase64JSON = ( b64Url : string ) : any => {
146
- let b64 = b64Url . replace ( / - / g, "+" ) . replace ( / _ / g, "/" ) ;
147
- switch ( b64 . length % 4 ) {
148
- case 0 :
149
- break ;
150
- case 2 :
151
- b64 += "==" ;
152
- break ;
153
- case 3 :
154
- b64 += "=" ;
155
- break ;
156
- default :
157
- throw new Error ( "Illegal base64url string." ) ;
158
- }
147
+ const decoded = decodeBase64Url ( b64Url )
159
148
try {
160
- return JSON . parse ( decodeURIComponent ( atob ( b64 ) ) ) ;
149
+ return JSON . parse ( utf8Decoder . decode ( decoded ) ) ;
161
150
} catch {
162
151
return null ;
163
152
}
0 commit comments