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  }