@@ -12,47 +12,17 @@ const algsSign = {
12
12
13
13
const algsVerify = {
14
14
HS256 : ( message : string , key : string , signature : string ) =>
15
- hash . hmac ( hash . sha256 , key , message , true ) === signature ,
15
+ base64urlEncode ( hash . hmac ( hash . sha256 , key , message , true ) ) === signature ,
16
16
HS384 : ( message : string , key : string , signature : string ) =>
17
- hash . hmac ( hash . sha384 , key , message , true ) === signature ,
17
+ base64urlEncode ( hash . hmac ( hash . sha384 , key , message , true ) ) === signature ,
18
18
HS512 : ( message : string , key : string , signature : string ) =>
19
- hash . hmac ( hash . sha512 , key , message , true ) === signature ,
19
+ base64urlEncode ( hash . hmac ( hash . sha512 , key , message , true ) ) === signature ,
20
20
} as {
21
21
[ key : string ] : ( message : string , key : string , signature : string ) => boolean ;
22
22
} ;
23
23
24
24
function base64urlEncode ( str : string ) {
25
- return encode ( str ) . gsub ( "+" , "-" ) [ 0 ] . gsub ( "/" , "_" ) [ 0 ] . gsub ( "=" , "" ) ;
26
- }
27
-
28
- function base64urlDecode ( str : string ) {
29
- const remainder = str . size ( ) % 4 ;
30
-
31
- if ( remainder > 0 ) {
32
- str = str + string . rep ( "=" , 4 - remainder ) ;
33
- }
34
-
35
- return decode ( str . gsub ( "-" , "+" ) [ 0 ] . gsub ( "_" , "/" ) [ 0 ] . gsub ( "=" , "" ) [ 0 ] ) ;
36
- }
37
-
38
- function tokenize ( str : string , div : string , len : number ) : string [ ] {
39
- const result : string [ ] = [ ] ;
40
- let pos = 0 ;
41
-
42
- while ( len > 1 ) {
43
- const st = str . find ( div , pos , true ) ;
44
- if ( ! st [ 0 ] ) break ;
45
- const sp = st [ 0 ] + div . size ( ) - 1 ;
46
-
47
- result . push ( str . sub ( pos , st [ 0 ] - 1 ) ) ;
48
- pos = sp + 1 ;
49
-
50
- len = len - 1 ;
51
- }
52
-
53
- result . push ( str . sub ( pos ) ) ;
54
-
55
- return result ;
25
+ return encode ( str ) . gsub ( "+" , "-" ) [ 0 ] . gsub ( "/" , "_" ) [ 0 ] . gsub ( "=" , "" ) [ 0 ] ;
56
26
}
57
27
58
28
function encodeJWT ( data : unknown , key : string , alg : string | undefined = "HS256" ) : string {
@@ -73,7 +43,9 @@ function encodeJWT(data: unknown, key: string, alg: string | undefined = "HS256"
73
43
}
74
44
75
45
const header = { typ : "JWT" , alg : alg } ;
76
- const segments = [ base64urlEncode ( HttpService . JSONEncode ( header ) ) , base64urlEncode ( HttpService . JSONEncode ( data ) ) ] ;
46
+
47
+ const segments = [ encode ( HttpService . JSONEncode ( header ) ) , encode ( HttpService . JSONEncode ( data ) ) ] ;
48
+
77
49
const signingInput = segments . join ( "." ) ;
78
50
const signature = base64urlEncode ( algsSign [ alg ] ( signingInput , key ) ) ;
79
51
@@ -89,7 +61,6 @@ function decodeJWT(
89
61
) : {
90
62
header : { alg : string ; typ : string } ;
91
63
body : { exp : number ; iat : number ; nbf : number ; [ key : string ] : unknown } ;
92
- signature : string ;
93
64
} {
94
65
if ( ! key ) {
95
66
verify = false ;
@@ -101,42 +72,36 @@ function decodeJWT(
101
72
error ( "data must be a string" ) ;
102
73
}
103
74
104
- if ( typeOf ( key ) !== "string" || ! key ) {
105
- error ( "key must be a string" ) ;
106
- }
107
-
108
75
if ( typeOf ( verify ) !== "boolean" ) {
109
76
error ( "verify must be a boolean" ) ;
110
77
}
111
78
112
- const segments = tokenize ( data , "." , 3 ) ;
79
+ const segments = data . split ( "." ) ;
113
80
114
81
if ( segments . size ( ) !== 3 ) {
115
82
error ( "not enough or too many segments" ) ;
116
83
}
117
84
118
85
const headerSegment = segments [ 0 ] ;
119
86
const payloadSegment = segments [ 1 ] ;
120
- const signatureSegment = segments [ 2 ] ;
121
87
122
88
const [ success , payload ] = pcall ( ( ) => {
123
89
return {
124
- header : HttpService . JSONDecode ( base64urlDecode ( headerSegment ) ) as { alg : string ; typ : string } ,
125
- body : HttpService . JSONDecode ( base64urlDecode ( payloadSegment ) ) as {
90
+ header : HttpService . JSONDecode ( decode ( headerSegment ) ) as { alg : string ; typ : string } ,
91
+ body : HttpService . JSONDecode ( decode ( payloadSegment ) ) as {
126
92
exp : number ;
127
93
iat : number ;
128
94
nbf : number ;
129
95
[ key : string ] : unknown ;
130
96
} ,
131
- signature : base64urlDecode ( signatureSegment ) ,
132
97
} ;
133
98
} ) ;
134
99
135
100
if ( ! success ) {
136
101
error ( "failed to decode JWT" ) ;
137
102
}
138
103
139
- if ( verify ) {
104
+ if ( verify && key ) {
140
105
verifyJWT ( data , key , true ) ;
141
106
}
142
107
@@ -152,7 +117,7 @@ function verifyJWT(data: string, key: string, throwErrors: boolean | undefined =
152
117
error ( "key must be a string" ) ;
153
118
}
154
119
155
- const segments = tokenize ( data , "." , 3 ) ;
120
+ const segments = data . split ( "." ) ;
156
121
157
122
if ( segments . size ( ) !== 3 ) {
158
123
if ( throwErrors ) error ( "not enough or too many segments" ) ;
@@ -164,8 +129,8 @@ function verifyJWT(data: string, key: string, throwErrors: boolean | undefined =
164
129
const payloadSegment = segments [ 1 ] ;
165
130
const signatureSegment = segments [ 2 ] ;
166
131
167
- const header = HttpService . JSONDecode ( base64urlDecode ( headerSegment ) ) as { alg : string ; typ : string } ;
168
- const body = HttpService . JSONDecode ( base64urlDecode ( payloadSegment ) ) as { exp : number ; iat : number ; nbf : number } ;
132
+ const header = HttpService . JSONDecode ( decode ( headerSegment ) ) as { alg : string ; typ : string } ;
133
+ const body = HttpService . JSONDecode ( decode ( payloadSegment ) ) as { exp : number ; iat : number ; nbf : number } ;
169
134
170
135
if ( ! header . typ || header . typ !== "JWT" ) {
171
136
if ( throwErrors ) error ( "typ must be JWT" ) ;
0 commit comments