github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/jwt/parser_test.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package jwt 19 20 // This file is a re-implementation of the original code here with some 21 // additional allocation tweaks reproduced using GODEBUG=allocfreetrace=1 22 // original file https://github.com/golang-jwt/jwt/blob/main/parser.go 23 // borrowed under MIT License https://github.com/golang-jwt/jwt/blob/main/LICENSE 24 25 import ( 26 "fmt" 27 "testing" 28 "time" 29 30 "github.com/golang-jwt/jwt/v4" 31 ) 32 33 var ( 34 defaultKeyFunc = func(claim *MapClaims) ([]byte, error) { return []byte("HelloSecret"), nil } 35 emptyKeyFunc = func(claim *MapClaims) ([]byte, error) { return nil, nil } 36 errorKeyFunc = func(claim *MapClaims) ([]byte, error) { return nil, fmt.Errorf("error loading key") } 37 ) 38 39 var jwtTestData = []struct { 40 name string 41 tokenString string 42 keyfunc func(*MapClaims) ([]byte, error) 43 claims jwt.Claims 44 valid bool 45 errors int32 46 }{ 47 { 48 "basic", 49 "", 50 defaultKeyFunc, 51 &MapClaims{ 52 MapClaims: jwt.MapClaims{ 53 "foo": "bar", 54 }, 55 }, 56 true, 57 0, 58 }, 59 { 60 "basic expired", 61 "", // autogen 62 defaultKeyFunc, 63 &MapClaims{ 64 MapClaims: jwt.MapClaims{ 65 "foo": "bar", 66 "exp": float64(time.Now().Unix() - 100), 67 }, 68 }, 69 false, 70 -1, 71 }, 72 { 73 "basic nbf", 74 "", // autogen 75 defaultKeyFunc, 76 &MapClaims{ 77 MapClaims: jwt.MapClaims{ 78 "foo": "bar", 79 "nbf": float64(time.Now().Unix() + 100), 80 }, 81 }, 82 false, 83 -1, 84 }, 85 { 86 "expired and nbf", 87 "", // autogen 88 defaultKeyFunc, 89 &MapClaims{ 90 MapClaims: jwt.MapClaims{ 91 "foo": "bar", 92 "nbf": float64(time.Now().Unix() + 100), 93 "exp": float64(time.Now().Unix() - 100), 94 }, 95 }, 96 false, 97 -1, 98 }, 99 { 100 "basic invalid", 101 "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", 102 defaultKeyFunc, 103 &MapClaims{ 104 MapClaims: jwt.MapClaims{ 105 "foo": "bar", 106 }, 107 }, 108 false, 109 -1, 110 }, 111 { 112 "basic nokeyfunc", 113 "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", 114 nil, 115 &MapClaims{ 116 MapClaims: jwt.MapClaims{ 117 "foo": "bar", 118 }, 119 }, 120 false, 121 -1, 122 }, 123 { 124 "basic nokey", 125 "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", 126 emptyKeyFunc, 127 &MapClaims{ 128 MapClaims: jwt.MapClaims{ 129 "foo": "bar", 130 }, 131 }, 132 false, 133 -1, 134 }, 135 { 136 "basic errorkey", 137 "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", 138 errorKeyFunc, 139 &MapClaims{ 140 MapClaims: jwt.MapClaims{ 141 "foo": "bar", 142 }, 143 }, 144 false, 145 -1, 146 }, 147 { 148 "Standard Claims", 149 "", 150 defaultKeyFunc, 151 &StandardClaims{ 152 StandardClaims: jwt.StandardClaims{ 153 ExpiresAt: time.Now().Add(time.Second * 10).Unix(), 154 }, 155 }, 156 true, 157 0, 158 }, 159 } 160 161 func mapClaimsToken(claims *MapClaims) string { 162 claims.SetAccessKey("test") 163 j := jwt.NewWithClaims(jwt.SigningMethodHS512, claims) 164 tk, _ := j.SignedString([]byte("HelloSecret")) 165 return tk 166 } 167 168 func standardClaimsToken(claims *StandardClaims) string { 169 claims.AccessKey = "test" 170 claims.Subject = "test" 171 j := jwt.NewWithClaims(jwt.SigningMethodHS512, claims) 172 tk, _ := j.SignedString([]byte("HelloSecret")) 173 return tk 174 } 175 176 func TestParserParse(t *testing.T) { 177 // Iterate over test data set and run tests 178 for _, data := range jwtTestData { 179 data := data 180 t.Run(data.name, func(t *testing.T) { 181 // Parse the token 182 var err error 183 184 // Figure out correct claims type 185 switch claims := data.claims.(type) { 186 case *MapClaims: 187 if data.tokenString == "" { 188 data.tokenString = mapClaimsToken(claims) 189 } 190 err = ParseWithClaims(data.tokenString, &MapClaims{}, data.keyfunc) 191 case *StandardClaims: 192 if data.tokenString == "" { 193 data.tokenString = standardClaimsToken(claims) 194 } 195 err = ParseWithStandardClaims(data.tokenString, &StandardClaims{}, []byte("HelloSecret")) 196 } 197 198 if data.valid && err != nil { 199 t.Errorf("Error while verifying token: %T:%v", err, err) 200 } 201 202 if !data.valid && err == nil { 203 t.Errorf("Invalid token passed validation") 204 } 205 206 if data.errors != 0 { 207 _, ok := err.(*jwt.ValidationError) 208 if !ok { 209 t.Errorf("Expected *jwt.ValidationError, but got %#v instead", err) 210 } 211 } 212 }) 213 } 214 }