github.com/nats-io/jwt/v2@v2.5.6/decoder.go (about) 1 /* 2 * Copyright 2020-2022 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 "encoding/json" 20 "errors" 21 "fmt" 22 "strings" 23 24 "github.com/nats-io/nkeys" 25 ) 26 27 const libVersion = 2 28 29 type identifier struct { 30 Type ClaimType `json:"type,omitempty"` 31 GenericFields `json:"nats,omitempty"` 32 } 33 34 func (i *identifier) Kind() ClaimType { 35 if i.Type != "" { 36 return i.Type 37 } 38 return i.GenericFields.Type 39 } 40 41 func (i *identifier) Version() int { 42 if i.Type != "" { 43 return 1 44 } 45 return i.GenericFields.Version 46 } 47 48 type v1ClaimsDataDeletedFields struct { 49 Tags TagList `json:"tags,omitempty"` 50 Type ClaimType `json:"type,omitempty"` 51 IssuerAccount string `json:"issuer_account,omitempty"` 52 } 53 54 // Decode takes a JWT string decodes it and validates it 55 // and return the embedded Claims. If the token header 56 // doesn't match the expected algorithm, or the claim is 57 // not valid or verification fails an error is returned. 58 func Decode(token string) (Claims, error) { 59 // must have 3 chunks 60 chunks := strings.Split(token, ".") 61 if len(chunks) != 3 { 62 return nil, errors.New("expected 3 chunks") 63 } 64 65 // header 66 if _, err := parseHeaders(chunks[0]); err != nil { 67 return nil, err 68 } 69 // claim 70 data, err := decodeString(chunks[1]) 71 if err != nil { 72 return nil, err 73 } 74 ver, claim, err := loadClaims(data) 75 if err != nil { 76 return nil, err 77 } 78 79 // sig 80 sig, err := decodeString(chunks[2]) 81 if err != nil { 82 return nil, err 83 } 84 85 if ver <= 1 { 86 if !claim.verify(chunks[1], sig) { 87 return nil, errors.New("claim failed V1 signature verification") 88 } 89 } else { 90 if !claim.verify(token[:len(chunks[0])+len(chunks[1])+1], sig) { 91 return nil, errors.New("claim failed V2 signature verification") 92 } 93 } 94 95 prefixes := claim.ExpectedPrefixes() 96 if prefixes != nil { 97 ok := false 98 issuer := claim.Claims().Issuer 99 for _, p := range prefixes { 100 switch p { 101 case nkeys.PrefixByteAccount: 102 if nkeys.IsValidPublicAccountKey(issuer) { 103 ok = true 104 } 105 case nkeys.PrefixByteOperator: 106 if nkeys.IsValidPublicOperatorKey(issuer) { 107 ok = true 108 } 109 case nkeys.PrefixByteUser: 110 if nkeys.IsValidPublicUserKey(issuer) { 111 ok = true 112 } 113 case nkeys.PrefixByteServer: 114 if nkeys.IsValidPublicServerKey(issuer) { 115 ok = true 116 } 117 } 118 } 119 if !ok { 120 return nil, fmt.Errorf("unable to validate expected prefixes - %v", prefixes) 121 } 122 } 123 return claim, nil 124 } 125 126 func loadClaims(data []byte) (int, Claims, error) { 127 var id identifier 128 if err := json.Unmarshal(data, &id); err != nil { 129 return -1, nil, err 130 } 131 132 if id.Version() > libVersion { 133 return -1, nil, errors.New("JWT was generated by a newer version ") 134 } 135 136 var claim Claims 137 var err error 138 switch id.Kind() { 139 case OperatorClaim: 140 claim, err = loadOperator(data, id.Version()) 141 case AccountClaim: 142 claim, err = loadAccount(data, id.Version()) 143 case UserClaim: 144 claim, err = loadUser(data, id.Version()) 145 case ActivationClaim: 146 claim, err = loadActivation(data, id.Version()) 147 case AuthorizationRequestClaim: 148 claim, err = loadAuthorizationRequest(data, id.Version()) 149 case AuthorizationResponseClaim: 150 claim, err = loadAuthorizationResponse(data, id.Version()) 151 case "cluster": 152 return -1, nil, errors.New("ClusterClaims are not supported") 153 case "server": 154 return -1, nil, errors.New("ServerClaims are not supported") 155 default: 156 var gc GenericClaims 157 if err := json.Unmarshal(data, &gc); err != nil { 158 return -1, nil, err 159 } 160 return -1, &gc, nil 161 } 162 163 return id.Version(), claim, err 164 }