Skip to content

Commit

Permalink
Removed custom fields from various JWTs, so that only the 'nats' head…
Browse files Browse the repository at this point in the history
…er is exposed. This avoids polluting the namespace
  • Loading branch information
aricart committed Jan 27, 2020
1 parent 0b6d1dc commit ddd1bb0
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 30 deletions.
5 changes: 3 additions & 2 deletions account_claims.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand Down Expand Up @@ -61,6 +61,7 @@ type Account struct {
Limits OperatorLimits `json:"limits,omitempty"`
SigningKeys StringList `json:"signing_keys,omitempty"`
Revocations RevocationList `json:"revocations,omitempty"`
NatsStandard
}

// Validate checks if the account is valid, based on the wrapper
Expand Down Expand Up @@ -130,7 +131,7 @@ func (a *AccountClaims) Encode(pair nkeys.KeyPair) (string, error) {
}
sort.Sort(a.Exports)
sort.Sort(a.Imports)
a.ClaimsData.Type = AccountClaim
a.Type = AccountClaim
return a.ClaimsData.Encode(pair, a)
}

Expand Down
5 changes: 3 additions & 2 deletions activation_claims.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand Down Expand Up @@ -30,6 +30,7 @@ type Activation struct {
ImportSubject Subject `json:"subject,omitempty"`
ImportType ExportType `json:"type,omitempty"`
Limits
NatsStandard
}

// IsService returns true if an Activation is for a service
Expand Down Expand Up @@ -82,7 +83,7 @@ func (a *ActivationClaims) Encode(pair nkeys.KeyPair) (string, error) {
if !nkeys.IsValidPublicAccountKey(a.ClaimsData.Subject) {
return "", errors.New("expected subject to be an account")
}
a.ClaimsData.Type = ActivationClaim
a.Type = ActivationClaim
return a.ClaimsData.Encode(pair, a)
}

Expand Down
26 changes: 15 additions & 11 deletions claims.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand Down Expand Up @@ -59,16 +59,20 @@ type Claims interface {

// ClaimsData is the base struct for all claims
type ClaimsData struct {
Audience string `json:"aud,omitempty"`
Expires int64 `json:"exp,omitempty"`
ID string `json:"jti,omitempty"`
IssuedAt int64 `json:"iat,omitempty"`
Issuer string `json:"iss,omitempty"`
Name string `json:"name,omitempty"`
NotBefore int64 `json:"nbf,omitempty"`
Subject string `json:"sub,omitempty"`
Tags TagList `json:"tags,omitempty"`
Type ClaimType `json:"type,omitempty"`
Audience string `json:"aud,omitempty"`
Expires int64 `json:"exp,omitempty"`
ID string `json:"jti,omitempty"`
IssuedAt int64 `json:"iat,omitempty"`
Issuer string `json:"iss,omitempty"`
Name string `json:"name,omitempty"`
NotBefore int64 `json:"nbf,omitempty"`
Subject string `json:"sub,omitempty"`
}

// NatsStandard contains fields shared by all NATS JWTs
type NatsStandard struct {
Tags TagList `json:"tags,omitempty"`
Type ClaimType `json:"type,omitempty"`
}

// Prefix holds the prefix byte for an NKey
Expand Down
5 changes: 3 additions & 2 deletions cluster_claims.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand Down Expand Up @@ -27,6 +27,7 @@ type Cluster struct {
Accounts []string `json:"accts,omitempty"`
AccountURL string `json:"accturl,omitempty"`
OperatorURL string `json:"opurl,omitempty"`
NatsStandard
}

// Validate checks the cluster and permissions for a cluster JWT
Expand Down Expand Up @@ -55,7 +56,7 @@ func (c *ClusterClaims) Encode(pair nkeys.KeyPair) (string, error) {
if !nkeys.IsValidPublicClusterKey(c.Subject) {
return "", errors.New("expected subject to be a cluster public key")
}
c.ClaimsData.Type = ClusterClaim
c.Type = ClusterClaim
return c.ClaimsData.Encode(pair, c)
}

Expand Down
12 changes: 11 additions & 1 deletion genericlaims.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -20,6 +20,7 @@ import "github.com/nats-io/nkeys"
// GenericClaims can be used to read a JWT as a map for any non-generic fields
type GenericClaims struct {
ClaimsData
NatsStandard
Data map[string]interface{} `json:"nats,omitempty"`
}

Expand All @@ -40,6 +41,15 @@ func DecodeGeneric(token string) (*GenericClaims, error) {
if err := Decode(token, &v); err != nil {
return nil, err
}
ct, ok := v.Data["type"].(string)
if ok {
v.Type = ClaimType(ct)
}
tl, ok := v.Data["tags"].(TagList)
if ok {
v.Tags = tl
}

return &v, nil
}

Expand Down
11 changes: 6 additions & 5 deletions operator_claims.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -26,6 +26,7 @@ import (

// Operator specific claims
type Operator struct {
NatsStandard
// Slice of real identies (like websites) that can be used to identify the operator.
Identities []Identity `json:"identity,omitempty"`
// Slice of other operator NKeys that can be used to sign on behalf of the main
Expand Down Expand Up @@ -112,15 +113,15 @@ func ValidateOperatorServiceURL(v string) error {
}

func (o *Operator) validateOperatorServiceURLs() []error {
var errors []error
var errs []error
for _, v := range o.OperatorServiceURLs {
if v != "" {
if err := ValidateOperatorServiceURL(v); err != nil {
errors = append(errors, err)
errs = append(errs, err)
}
}
}
return errors
return errs
}

// OperatorClaims define the data for an operator JWT
Expand Down Expand Up @@ -165,7 +166,7 @@ func (oc *OperatorClaims) Encode(pair nkeys.KeyPair) (string, error) {
if err != nil {
return "", err
}
oc.ClaimsData.Type = OperatorClaim
oc.Type = OperatorClaim
return oc.ClaimsData.Encode(pair, oc)
}

Expand Down
21 changes: 18 additions & 3 deletions operator_claims_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func TestSigningKeyValidation(t *testing.T) {

uc := NewOperatorClaims(publicKey(ckp, t))
uc.Expires = time.Now().Add(time.Duration(time.Hour)).Unix()
uc.AddSigningKey(publicKey(ckp2, t))
uc.SigningKeys.Add(publicKey(ckp2, t))
uJwt := encode(uc, ckp, t)

uc2, err := DecodeOperatorClaims(uJwt)
Expand All @@ -152,7 +152,7 @@ func TestSigningKeyValidation(t *testing.T) {
t.Fatal("valid operator key should have no validation issues")
}

uc.AddSigningKey("") // add an invalid one
uc.SigningKeys.Add("") // add an invalid one

vr = &ValidationResults{}
uc.Validate(vr)
Expand Down Expand Up @@ -193,7 +193,7 @@ func TestSignedBy(t *testing.T) {

AssertEquals(uc.DidSign(ac), false, t) // no signing key
AssertEquals(uc2.DidSign(ac), true, t) // actual key
uc.AddSigningKey(publicKey(ckp2, t))
uc.SigningKeys.Add(publicKey(ckp2, t))
AssertEquals(uc.DidSign(ac), true, t) // signing key

clusterKey := createClusterNKey(t)
Expand Down Expand Up @@ -352,3 +352,18 @@ func Test_OperatorServiceURL(t *testing.T) {
errs := vr.Errors()
AssertEquals(len(errs), shouldFail, t)
}

func Test_OperatorCompatibility(t *testing.T) {
token := "eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJhdWQiOiJOR1MiLCJleHAiOjE2MjkwNDEwNTEsImp0aSI6IldWRFpYQ0dMQlVOWjYyWUI1MjRWTVdDNVRBRzJGS0lTWUNDUExLWTJKT0JURkdNMzM0V0EiLCJpYXQiOjE1NjU4ODI2NTEsImlzcyI6Ik9ETEMyMk5JUVE1VTRKNlpEVFZPRktURVg0Rjc3RTdUVk0yUkhXU0c3TjI2NllPVktUUkk0RVdYIiwibmFtZSI6IlN5bmFkaWEgQ29tbXVuaWNhdGlvbnMgSW5jLiIsIm5iZiI6MTU2NTg4MjcxMSwic3ViIjoiT0RMQzIyTklRUTVVNEo2WkRUVk9GS1RFWDRGNzdFN1RWTTJSSFdTRzdOMjY2WU9WS1RSSTRFV1giLCJ0eXBlIjoib3BlcmF0b3IiLCJuYXRzIjp7InNpZ25pbmdfa2V5cyI6WyJPRFNLQVlVNUpSTVhMRlhGSlU3WTczUE5OMjJaVFhDVlRWQTI2VlZMVkgyQ05NNlFWMlZCSk1JTyIsIk9EU0tCTkRJVDNMVFpXRlNSQVdPQlhTQlo3VlpDRFFWVTZUQkpYM1RRR1lYVVdSVTQ2QU5KSlM0IiwiT0RTS0NOSTVNTFNXTlBTNEdJQ0pHMktISk9DTEhaV1BPQlROVUIyNDVBTkNPQlg3VklRNk1BWkQiXSwiYWNjb3VudF9zZXJ2ZXJfdXJsIjoiaHR0cHM6Ly9hcGkuc3luYWRpYS5pby9qd3QvdjEiLCJvcGVyYXRvcl9zZXJ2aWNlX3VybHMiOlsidGxzOi8vY29ubmVjdC5uZ3MuZ2xvYmFsIl19fQ.aMRYSQJ8NEcH0j_7iLLgrtycMA5n1aiUftBe0kO9Ed6A1Jm8cxItDOMqV2qO3EixDDukHuFIhvgMg-fmsd44Ag"
_, err := DecodeOperatorClaims(token)
if err != nil {
t.Fatal(err)
}
gc, err := DecodeGeneric(token)
if err != nil {
t.Fatal(err)
}
if gc.Type != "operator" {
t.Fatalf("expected %q to be 'operator'", gc.Type)
}
}
5 changes: 3 additions & 2 deletions server_claims.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -25,6 +25,7 @@ import (
type Server struct {
Permissions
Cluster string `json:"cluster,omitempty"`
NatsStandard
}

// Validate checks the cluster and permissions for a server JWT
Expand Down Expand Up @@ -55,7 +56,7 @@ func (s *ServerClaims) Encode(pair nkeys.KeyPair) (string, error) {
if !nkeys.IsValidPublicServerKey(s.Subject) {
return "", errors.New("expected subject to be a server public key")
}
s.ClaimsData.Type = ServerClaim
s.Type = ServerClaim
return s.ClaimsData.Encode(pair, s)
}

Expand Down
5 changes: 3 additions & 2 deletions user_claims.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 The NATS Authors
* Copyright 2018-2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -26,6 +26,7 @@ type User struct {
Permissions
Limits
BearerToken bool `json:"bearer_token,omitempty"`
NatsStandard
}

// Validate checks the permissions and limits in a User jwt
Expand Down Expand Up @@ -59,7 +60,7 @@ func (u *UserClaims) Encode(pair nkeys.KeyPair) (string, error) {
if !nkeys.IsValidPublicUserKey(u.Subject) {
return "", errors.New("expected subject to be user public key")
}
u.ClaimsData.Type = UserClaim
u.Type = UserClaim
return u.ClaimsData.Encode(pair, u)
}

Expand Down

0 comments on commit ddd1bb0

Please sign in to comment.