1
+ import type { Jwt } from '@clerk/types' ;
1
2
import type QUnit from 'qunit' ;
2
3
import sinon from 'sinon' ;
3
4
@@ -11,66 +12,72 @@ import {
11
12
signedJwt ,
12
13
someOtherPublicKey ,
13
14
} from '../../fixtures' ;
15
+ import { assertOk } from '../../util/testUtils' ;
14
16
import { decodeJwt , hasValidSignature , verifyJwt } from '../verifyJwt' ;
15
17
16
18
export default ( QUnit : QUnit ) => {
17
19
const { module, test } = QUnit ;
20
+ const invalidTokenError = {
21
+ reason : 'token-invalid' ,
22
+ message : 'Invalid JWT form. A JWT consists of three parts separated by dots.' ,
23
+ } ;
18
24
19
25
module ( 'hasValidSignature(jwt, key)' , ( ) => {
20
26
test ( 'verifies the signature with a JWK formatted key' , async assert => {
21
- assert . true ( await hasValidSignature ( decodeJwt ( signedJwt ) , publicJwks ) ) ;
27
+ const { data : decodedResult } = decodeJwt ( signedJwt ) ;
28
+ assertOk < Jwt > ( assert , decodedResult ) ;
29
+ const { data : signatureResult } = await hasValidSignature ( decodedResult , publicJwks ) ;
30
+ assert . true ( signatureResult ) ;
22
31
} ) ;
23
32
24
33
test ( 'verifies the signature with a PEM formatted key' , async assert => {
25
- assert . true ( await hasValidSignature ( decodeJwt ( signedJwt ) , pemEncodedPublicKey ) ) ;
34
+ const { data : decodedResult } = decodeJwt ( signedJwt ) ;
35
+ assertOk < Jwt > ( assert , decodedResult ) ;
36
+ const { data : signatureResult } = await hasValidSignature ( decodedResult , pemEncodedPublicKey ) ;
37
+ assert . true ( signatureResult ) ;
26
38
} ) ;
27
39
28
40
test ( 'it returns false if the key is not correct' , async assert => {
29
- assert . false ( await hasValidSignature ( decodeJwt ( signedJwt ) , someOtherPublicKey ) ) ;
41
+ const { data : decodedResult } = decodeJwt ( signedJwt ) ;
42
+ assertOk < Jwt > ( assert , decodedResult ) ;
43
+ const { data : signatureResult } = await hasValidSignature ( decodedResult , someOtherPublicKey ) ;
44
+ assert . false ( signatureResult ) ;
30
45
} ) ;
31
46
} ) ;
32
47
33
48
module ( 'decodeJwt(jwt)' , ( ) => {
34
49
test ( 'decodes a valid JWT' , assert => {
35
- const { header, payload } = decodeJwt ( mockJwt ) ;
36
- assert . propEqual ( header , mockJwtHeader ) ;
37
- assert . propEqual ( payload , mockJwtPayload ) ;
38
- // TODO: @dimkl assert signature is instance of Uint8Array
50
+ const { data } = decodeJwt ( mockJwt ) ;
51
+ assertOk < Jwt > ( assert , data ) ;
52
+
53
+ assert . propEqual ( data . header , mockJwtHeader ) ;
54
+ assert . propEqual ( data . payload , mockJwtPayload ) ;
55
+ // TODO(@dimkl): assert signature is instance of Uint8Array
39
56
} ) ;
40
57
41
- test ( 'throws an error if null is given as jwt' , assert => {
42
- assert . throws (
43
- ( ) => decodeJwt ( 'null' ) ,
44
- new Error ( 'Invalid JWT form. A JWT consists of three parts separated by dots.' ) ,
45
- ) ;
58
+ test ( 'returns an error if null is given as jwt' , assert => {
59
+ const { error } = decodeJwt ( 'null' ) ;
60
+ assert . propContains ( error , invalidTokenError ) ;
46
61
} ) ;
47
62
48
- test ( 'throws an error if undefined is given as jwt' , assert => {
49
- assert . throws (
50
- ( ) => decodeJwt ( 'undefined' ) ,
51
- new Error ( 'Invalid JWT form. A JWT consists of three parts separated by dots.' ) ,
52
- ) ;
63
+ test ( 'returns an error if undefined is given as jwt' , assert => {
64
+ const { error } = decodeJwt ( 'undefined' ) ;
65
+ assert . propContains ( error , invalidTokenError ) ;
53
66
} ) ;
54
67
55
- test ( 'throws an error if empty string is given as jwt' , assert => {
56
- assert . throws (
57
- ( ) => decodeJwt ( 'undefined' ) ,
58
- new Error ( 'Invalid JWT form. A JWT consists of three parts separated by dots.' ) ,
59
- ) ;
68
+ test ( 'returns an error if empty string is given as jwt' , assert => {
69
+ const { error } = decodeJwt ( '' ) ;
70
+ assert . propContains ( error , invalidTokenError ) ;
60
71
} ) ;
61
72
62
73
test ( 'throws an error if invalid string is given as jwt' , assert => {
63
- assert . throws (
64
- ( ) => decodeJwt ( 'undefined' ) ,
65
- new Error ( 'Invalid JWT form. A JWT consists of three parts separated by dots.' ) ,
66
- ) ;
74
+ const { error } = decodeJwt ( 'whatever' ) ;
75
+ assert . propContains ( error , invalidTokenError ) ;
67
76
} ) ;
68
77
69
78
test ( 'throws an error if number is given as jwt' , assert => {
70
- assert . throws (
71
- ( ) => decodeJwt ( '42' ) ,
72
- new Error ( 'Invalid JWT form. A JWT consists of three parts separated by dots.' ) ,
73
- ) ;
79
+ const { error } = decodeJwt ( '42' ) ;
80
+ assert . propContains ( error , invalidTokenError ) ;
74
81
} ) ;
75
82
} ) ;
76
83
@@ -90,8 +97,8 @@ export default (QUnit: QUnit) => {
90
97
issuer : mockJwtPayload . iss ,
91
98
authorizedParties : [ 'https://accounts.inspired.puma-74.lcl.dev' ] ,
92
99
} ;
93
- const payload = await verifyJwt ( mockJwt , inputVerifyJwtOptions ) ;
94
- assert . propEqual ( payload , mockJwtPayload ) ;
100
+ const { data } = await verifyJwt ( mockJwt , inputVerifyJwtOptions ) ;
101
+ assert . propEqual ( data , mockJwtPayload ) ;
95
102
} ) ;
96
103
97
104
test ( 'returns the valid JWT payload if valid key & issuer method & azp is given' , async assert => {
@@ -100,8 +107,8 @@ export default (QUnit: QUnit) => {
100
107
issuer : ( iss : string ) => iss . startsWith ( 'https://clerk' ) ,
101
108
authorizedParties : [ 'https://accounts.inspired.puma-74.lcl.dev' ] ,
102
109
} ;
103
- const payload = await verifyJwt ( mockJwt , inputVerifyJwtOptions ) ;
104
- assert . propEqual ( payload , mockJwtPayload ) ;
110
+ const { data } = await verifyJwt ( mockJwt , inputVerifyJwtOptions ) ;
111
+ assert . propEqual ( data , mockJwtPayload ) ;
105
112
} ) ;
106
113
107
114
test ( 'returns the valid JWT payload if valid key & issuer & list of azp (with empty string) is given' , async assert => {
@@ -110,12 +117,18 @@ export default (QUnit: QUnit) => {
110
117
issuer : mockJwtPayload . iss ,
111
118
authorizedParties : [ '' , 'https://accounts.inspired.puma-74.lcl.dev' ] ,
112
119
} ;
113
- const payload = await verifyJwt ( mockJwt , inputVerifyJwtOptions ) ;
114
- assert . propEqual ( payload , mockJwtPayload ) ;
120
+ const { data } = await verifyJwt ( mockJwt , inputVerifyJwtOptions ) ;
121
+ assert . propEqual ( data , mockJwtPayload ) ;
115
122
} ) ;
116
123
117
- // todo('returns the reason of the failure when verifications fail', assert => {
118
- // assert.true(true);
119
- // });
124
+ test ( 'returns the reason of the failure when verifications fail' , async assert => {
125
+ const inputVerifyJwtOptions = {
126
+ key : mockJwks . keys [ 0 ] ,
127
+ issuer : mockJwtPayload . iss ,
128
+ authorizedParties : [ '' , 'https://accounts.inspired.puma-74.lcl.dev' ] ,
129
+ } ;
130
+ const { error } = await verifyJwt ( 'invalid-jwt' , inputVerifyJwtOptions ) ;
131
+ assert . propContains ( error , invalidTokenError ) ;
132
+ } ) ;
120
133
} ) ;
121
134
} ;
0 commit comments