git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/jwt/jwt_test.go (about) 1 package jwt_test 2 3 import ( 4 "errors" 5 "strconv" 6 "testing" 7 "time" 8 9 "git.sr.ht/~pingoo/stdx/jwt" 10 ) 11 12 var ( 13 INSECURE_SECRET = []byte("9MfG7mC+dqxXgXZGdiFsxyET1mQRBekiw7K+bIvZEGc=") 14 ) 15 16 func TestVerifyInvalidTokens(t *testing.T) { 17 jwtProvider, _ := jwt.NewProvider(INSECURE_SECRET, jwt.AlgorithmHS256, nil) 18 invalidTokens := []string{ 19 ".", 20 "..", 21 "...", 22 "....", 23 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..", 24 ".eyJtZXNzYWdlIjoiOSJ9.", 25 "..pRVbZ4OC40z7qZsRj0cPpLodPmMAF7-skUqztxeK9iQ=", 26 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiOSJ9.", 27 ".eyJtZXNzYWdlIjoiOSJ9.pRVbZ4OC40z7qZsRj0cPpLodPmMAF7-skUqztxeK9iQ=", 28 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..pRVbZ4OC40z7qZsRj0cPpLodPmMAF7-skUqztxeK9iQ=", 29 } 30 31 for _, invalidToken := range invalidTokens { 32 var decodedPayload struct{} 33 err := jwtProvider.VerifyToken(invalidToken, &decodedPayload) 34 if err == nil { 35 t.Errorf("The invalid token: %s is verifed as valid", invalidToken) 36 } 37 } 38 } 39 40 func TestVerifyKnownJWTs(t *testing.T) { 41 jwts := []struct { 42 Token string 43 Algorithm jwt.Algorithm 44 Secret []byte 45 }{ 46 { 47 Token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiSGVsbG8gV29ybGQifQ.B3yZ_TwtqZGk1ejyUI6QcD-eqrPN0awNEy4L4CiwvL8", 48 Algorithm: jwt.AlgorithmHS256, 49 Secret: []byte("secretsecretsecretsecretsecretsecret"), 50 }, 51 } 52 53 for _, knowJwt := range jwts { 54 var emptyStruct struct{} 55 jwtProvider, _ := jwt.NewProvider(knowJwt.Secret, jwt.AlgorithmHS256, nil) 56 err := jwtProvider.VerifyToken(knowJwt.Token, &emptyStruct) 57 if err != nil { 58 t.Error(err) 59 } 60 } 61 } 62 63 func TestIssueAndVerify(t *testing.T) { 64 type claims struct { 65 Message string `json:"message"` 66 } 67 jwtProvider, _ := jwt.NewProvider(INSECURE_SECRET, jwt.AlgorithmHS256, nil) 68 69 for i := 0; i < 10; i += 1 { 70 payload := claims{Message: strconv.Itoa(i)} 71 token, err := jwtProvider.IssueToken(payload, nil) 72 if err != nil { 73 t.Error(err) 74 } 75 76 var decodedPayload claims 77 err = jwtProvider.VerifyToken(token, &decodedPayload) 78 if err != nil { 79 t.Error(err) 80 } 81 if decodedPayload.Message != payload.Message { 82 t.Errorf("payload.message (%s) != decodedPayload.message(%s)", payload.Message, decodedPayload.Message) 83 } 84 } 85 } 86 87 func TestIssueAndVerifyInvalid(t *testing.T) { 88 type claims struct { 89 Message string `json:"message"` 90 } 91 jwtProvider, _ := jwt.NewProvider(INSECURE_SECRET, jwt.AlgorithmHS256, nil) 92 93 for i := 0; i < 10; i += 1 { 94 payload := claims{Message: strconv.Itoa(i)} 95 token, err := jwtProvider.IssueToken(payload, nil) 96 if err != nil { 97 t.Error(err) 98 } 99 100 var decodedPayload claims 101 102 invalidTokenWithPrefix := "x" + token 103 err = jwtProvider.VerifyToken(invalidTokenWithPrefix, &decodedPayload) 104 if !errors.Is(err, jwt.ErrSignatureIsNotValid) { 105 t.Errorf("expected error: %s. got: %v", jwt.ErrSignatureIsNotValid, err) 106 } 107 108 invalidTokenWithInvalidPrefix := "|" + token 109 err = jwtProvider.VerifyToken(invalidTokenWithInvalidPrefix, &decodedPayload) 110 if !errors.Is(err, jwt.ErrSignatureIsNotValid) { 111 t.Errorf("expected error: %s. got: %v", jwt.ErrSignatureIsNotValid, err) 112 } 113 114 invalidTokenWithSuffix := token + "x" 115 err = jwtProvider.VerifyToken(invalidTokenWithSuffix, &decodedPayload) 116 if !errors.Is(err, jwt.ErrSignatureIsNotValid) { 117 t.Errorf("expected error: %s. got: %v", jwt.ErrSignatureIsNotValid, err) 118 } 119 120 invalidTokenWithInvalidSuffix := token + "|" 121 err = jwtProvider.VerifyToken(invalidTokenWithInvalidSuffix, &decodedPayload) 122 if !errors.Is(err, jwt.ErrTokenIsNotValid) { 123 t.Errorf("expected error: %s. got: %v", jwt.ErrTokenIsNotValid, err) 124 } 125 } 126 } 127 128 func TestIssueAndVerifyExpireIntTheFuture(t *testing.T) { 129 type claims struct { 130 Message string `json:"message"` 131 } 132 jwtProvider, _ := jwt.NewProvider(INSECURE_SECRET, jwt.AlgorithmHS256, nil) 133 134 for i := 0; i < 10; i += 1 { 135 payload := claims{Message: strconv.Itoa(i)} 136 expiresAt := time.Now().Add(1 * time.Hour) 137 token, err := jwtProvider.IssueToken(payload, &jwt.TokenOptions{ExpirationTime: &expiresAt}) 138 if err != nil { 139 t.Error(err) 140 } 141 142 var decodedPayload claims 143 err = jwtProvider.VerifyToken(token, &decodedPayload) 144 if err != nil { 145 t.Error(err) 146 } 147 if decodedPayload.Message != payload.Message { 148 t.Errorf("pyaload.message (%s) != decodedPayload.message(%s)", payload.Message, decodedPayload.Message) 149 } 150 } 151 } 152 153 func TestIssueAndVerifyExpired(t *testing.T) { 154 type emptyClaims struct { 155 } 156 type claims struct { 157 Message string `json:"message"` 158 } 159 jwtProvider, _ := jwt.NewProvider(INSECURE_SECRET, jwt.AlgorithmHS256, nil) 160 161 for i := 0; i < 10; i += 1 { 162 expiresAt := time.Now().Add(-1 * time.Hour) 163 token, err := jwtProvider.IssueToken(emptyClaims{}, &jwt.TokenOptions{ExpirationTime: &expiresAt}) 164 if err != nil { 165 t.Error(err) 166 } 167 168 var decodedPayload emptyClaims 169 err = jwtProvider.VerifyToken(token, &decodedPayload) 170 if !errors.Is(err, jwt.ErrTokenHasExpired) { 171 t.Errorf("expected error: %s. got: %v", jwt.ErrTokenHasExpired, err) 172 } 173 } 174 175 for i := 0; i < 10; i += 1 { 176 payload := claims{Message: strconv.Itoa(i)} 177 expiresAt := time.Now().Add(-1 * time.Hour) 178 token, err := jwtProvider.IssueToken(payload, &jwt.TokenOptions{ExpirationTime: &expiresAt}) 179 if err != nil { 180 t.Error(err) 181 } 182 183 var decodedPayload claims 184 err = jwtProvider.VerifyToken(token, &decodedPayload) 185 if !errors.Is(err, jwt.ErrTokenHasExpired) { 186 t.Errorf("expected error: %s. got: %v", jwt.ErrTokenHasExpired, err) 187 } 188 } 189 }