github.com/nats-io/jwt/v2@v2.5.6/v1compat/creds_utils_test.go (about) 1 /* 2 * Copyright 2019-2020 The NATS Authors 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package jwt 17 18 import ( 19 "bytes" 20 "fmt" 21 "strings" 22 "testing" 23 24 "github.com/nats-io/nkeys" 25 ) 26 27 func makeJWT(t *testing.T) (string, nkeys.KeyPair) { 28 akp := createAccountNKey(t) 29 kp := createUserNKey(t) 30 pk := publicKey(kp, t) 31 oc := NewUserClaims(pk) 32 token, err := oc.Encode(akp) 33 if err != nil { 34 t.Fatal(err) 35 } 36 return token, kp 37 } 38 39 func Test_DecorateJwt(t *testing.T) { 40 token, _ := makeJWT(t) 41 d, err := DecorateJWT(token) 42 if err != nil { 43 t.Fatal(err) 44 } 45 s := string(d) 46 if !strings.Contains(s, "-BEGIN NATS USER JWT-") { 47 t.Fatal("doesn't contain expected header") 48 } 49 if !strings.Contains(s, "eyJ0") { 50 t.Fatal("doesn't contain public key") 51 } 52 if !strings.Contains(s, "-END NATS USER JWT------\n\n") { 53 t.Fatal("doesn't contain expected footer") 54 } 55 } 56 57 func Test_FormatUserConfig(t *testing.T) { 58 token, kp := makeJWT(t) 59 d, err := FormatUserConfig(token, seedKey(kp, t)) 60 if err != nil { 61 t.Fatal(err) 62 } 63 s := string(d) 64 if !strings.Contains(s, "-BEGIN NATS USER JWT-") { 65 t.Fatal("doesn't contain expected header") 66 } 67 if !strings.Contains(s, "eyJ0") { 68 t.Fatal("doesn't contain public key") 69 } 70 if !strings.Contains(s, "-END NATS USER JWT-") { 71 t.Fatal("doesn't contain expected footer") 72 } 73 74 validateSeed(t, d, kp) 75 } 76 77 func validateSeed(t *testing.T, decorated []byte, nk nkeys.KeyPair) { 78 kind := "" 79 seed := seedKey(nk, t) 80 switch string(seed[0:2]) { 81 case "SO": 82 kind = "operator" 83 case "SA": 84 kind = "account" 85 case "SU": 86 kind = "user" 87 default: 88 kind = "not supported" 89 } 90 kind = strings.ToUpper(kind) 91 92 s := string(decorated) 93 if !strings.Contains(s, fmt.Sprintf("\n\n-----BEGIN %s NKEY SEED-", kind)) { 94 t.Fatal("doesn't contain expected seed header") 95 } 96 if !strings.Contains(s, string(seed)) { 97 t.Fatal("doesn't contain the seed") 98 } 99 if !strings.Contains(s, fmt.Sprintf("-END %s NKEY SEED------\n\n", kind)) { 100 t.Fatal("doesn't contain expected seed footer") 101 } 102 } 103 104 func Test_ParseDecoratedJWT(t *testing.T) { 105 token, _ := makeJWT(t) 106 107 t2, err := ParseDecoratedJWT([]byte(token)) 108 if err != nil { 109 t.Fatal(err) 110 } 111 if token != t2 { 112 t.Fatal("jwt didn't match expected") 113 } 114 115 decorated, err := DecorateJWT(token) 116 if err != nil { 117 t.Fatal(err) 118 } 119 120 t3, err := ParseDecoratedJWT(decorated) 121 if err != nil { 122 t.Fatal(err) 123 } 124 if token != t3 { 125 t.Fatal("parse decorated jwt didn't match expected") 126 } 127 } 128 129 func Test_ParseDecoratedJWTBad(t *testing.T) { 130 v, err := ParseDecoratedJWT([]byte("foo")) 131 if err != nil { 132 t.Fatal(err) 133 } 134 if v != "foo" { 135 t.Fatal("unexpected input was not returned") 136 } 137 } 138 139 func Test_ParseDecoratedSeed(t *testing.T) { 140 token, ukp := makeJWT(t) 141 us := seedKey(ukp, t) 142 decorated, err := FormatUserConfig(token, us) 143 if err != nil { 144 t.Fatal(err) 145 } 146 kp, err := ParseDecoratedUserNKey(decorated) 147 if err != nil { 148 t.Fatal(err) 149 } 150 pu := seedKey(kp, t) 151 if !bytes.Equal(us, pu) { 152 t.Fatal("seeds don't match") 153 } 154 } 155 156 func Test_ParseDecoratedBadKey(t *testing.T) { 157 token, ukp := makeJWT(t) 158 us, err := ukp.Seed() 159 if err != nil { 160 t.Fatal(err) 161 } 162 akp := createAccountNKey(t) 163 as := seedKey(akp, t) 164 165 _, err = FormatUserConfig(token, as) 166 if err == nil { 167 t.Fatal("should have failed to encode with bad seed") 168 } 169 170 sc, err := FormatUserConfig(token, us) 171 if err != nil { 172 t.Fatal(err) 173 } 174 bad := strings.Replace(string(sc), string(us), string(as), -1) 175 _, err = ParseDecoratedUserNKey([]byte(bad)) 176 if err == nil { 177 t.Fatal("parse should have failed for non user nkey") 178 } 179 } 180 181 func Test_FailsOnNonUserJWT(t *testing.T) { 182 akp := createAccountNKey(t) 183 pk := publicKey(akp, t) 184 185 ac := NewAccountClaims(pk) 186 token, err := ac.Encode(akp) 187 if err != nil { 188 t.Fatal(err) 189 } 190 ukp := createUserNKey(t) 191 us := seedKey(ukp, t) 192 _, err = FormatUserConfig(token, us) 193 if err == nil { 194 t.Fatal("should have failed with account claims") 195 } 196 } 197 198 func Test_DecorateNKeys(t *testing.T) { 199 var kps []nkeys.KeyPair 200 kps = append(kps, createOperatorNKey(t)) 201 kps = append(kps, createAccountNKey(t)) 202 kps = append(kps, createUserNKey(t)) 203 204 for _, kp := range kps { 205 seed := seedKey(kp, t) 206 d, err := DecorateSeed(seed) 207 if err != nil { 208 t.Fatal(err, string(seed)) 209 } 210 validateSeed(t, d, kp) 211 212 kp2, err := ParseDecoratedNKey(d) 213 if err != nil { 214 t.Fatal(string(seed), err) 215 } 216 seed2 := seedKey(kp2, t) 217 if !bytes.Equal(seed, seed2) { 218 t.Fatalf("seeds dont match %q != %q", string(seed), string(seed2)) 219 } 220 } 221 222 _, err := ParseDecoratedNKey([]byte("bad")) 223 if err == nil { 224 t.Fatal("required error parsing bad nkey") 225 } 226 }