github.com/nats-io/jwt/v2@v2.5.6/authorization_claims.go (about) 1 /* 2 * Copyright 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 "errors" 20 21 "github.com/nats-io/nkeys" 22 ) 23 24 // ServerID is basic static info for a NATS server. 25 type ServerID struct { 26 Name string `json:"name"` 27 Host string `json:"host"` 28 ID string `json:"id"` 29 Version string `json:"version,omitempty"` 30 Cluster string `json:"cluster,omitempty"` 31 Tags TagList `json:"tags,omitempty"` 32 XKey string `json:"xkey,omitempty"` 33 } 34 35 // ClientInformation is information about a client that is trying to authorize. 36 type ClientInformation struct { 37 Host string `json:"host,omitempty"` 38 ID uint64 `json:"id,omitempty"` 39 User string `json:"user,omitempty"` 40 Name string `json:"name,omitempty"` 41 Tags TagList `json:"tags,omitempty"` 42 NameTag string `json:"name_tag,omitempty"` 43 Kind string `json:"kind,omitempty"` 44 Type string `json:"type,omitempty"` 45 MQTT string `json:"mqtt_id,omitempty"` 46 Nonce string `json:"nonce,omitempty"` 47 } 48 49 // ConnectOptions represents options that were set in the CONNECT protocol from the client 50 // during authorization. 51 type ConnectOptions struct { 52 JWT string `json:"jwt,omitempty"` 53 Nkey string `json:"nkey,omitempty"` 54 SignedNonce string `json:"sig,omitempty"` 55 Token string `json:"auth_token,omitempty"` 56 Username string `json:"user,omitempty"` 57 Password string `json:"pass,omitempty"` 58 Name string `json:"name,omitempty"` 59 Lang string `json:"lang,omitempty"` 60 Version string `json:"version,omitempty"` 61 Protocol int `json:"protocol"` 62 } 63 64 // ClientTLS is information about TLS state if present, including client certs. 65 // If the client certs were present and verified they will be under verified chains 66 // with the client peer cert being VerifiedChains[0]. These are complete and pem encoded. 67 // If they were not verified, they will be under certs. 68 type ClientTLS struct { 69 Version string `json:"version,omitempty"` 70 Cipher string `json:"cipher,omitempty"` 71 Certs StringList `json:"certs,omitempty"` 72 VerifiedChains []StringList `json:"verified_chains,omitempty"` 73 } 74 75 // AuthorizationRequest represents all the information we know about the client that 76 // will be sent to an external authorization service. 77 type AuthorizationRequest struct { 78 Server ServerID `json:"server_id"` 79 UserNkey string `json:"user_nkey"` 80 ClientInformation ClientInformation `json:"client_info"` 81 ConnectOptions ConnectOptions `json:"connect_opts"` 82 TLS *ClientTLS `json:"client_tls,omitempty"` 83 RequestNonce string `json:"request_nonce,omitempty"` 84 GenericFields 85 } 86 87 // AuthorizationRequestClaims defines an external auth request JWT. 88 // These wil be signed by a NATS server. 89 type AuthorizationRequestClaims struct { 90 ClaimsData 91 AuthorizationRequest `json:"nats"` 92 } 93 94 // NewAuthorizationRequestClaims creates an auth request JWT with the specific subject/public key. 95 func NewAuthorizationRequestClaims(subject string) *AuthorizationRequestClaims { 96 if subject == "" { 97 return nil 98 } 99 var ac AuthorizationRequestClaims 100 ac.Subject = subject 101 return &ac 102 } 103 104 // Validate checks the generic and specific parts of the auth request jwt. 105 func (ac *AuthorizationRequestClaims) Validate(vr *ValidationResults) { 106 if ac.UserNkey == "" { 107 vr.AddError("User nkey is required") 108 } else if !nkeys.IsValidPublicUserKey(ac.UserNkey) { 109 vr.AddError("User nkey %q is not a valid user public key", ac.UserNkey) 110 } 111 ac.ClaimsData.Validate(vr) 112 } 113 114 // Encode tries to turn the auth request claims into a JWT string. 115 func (ac *AuthorizationRequestClaims) Encode(pair nkeys.KeyPair) (string, error) { 116 ac.Type = AuthorizationRequestClaim 117 return ac.ClaimsData.encode(pair, ac) 118 } 119 120 // DecodeAuthorizationRequestClaims tries to parse an auth request claims from a JWT string 121 func DecodeAuthorizationRequestClaims(token string) (*AuthorizationRequestClaims, error) { 122 claims, err := Decode(token) 123 if err != nil { 124 return nil, err 125 } 126 ac, ok := claims.(*AuthorizationRequestClaims) 127 if !ok { 128 return nil, errors.New("not an authorization request claim") 129 } 130 return ac, nil 131 } 132 133 // ExpectedPrefixes defines the types that can encode an auth request jwt, servers. 134 func (ac *AuthorizationRequestClaims) ExpectedPrefixes() []nkeys.PrefixByte { 135 return []nkeys.PrefixByte{nkeys.PrefixByteServer} 136 } 137 138 func (ac *AuthorizationRequestClaims) ClaimType() ClaimType { 139 return ac.Type 140 } 141 142 // Claims returns the request claims data. 143 func (ac *AuthorizationRequestClaims) Claims() *ClaimsData { 144 return &ac.ClaimsData 145 } 146 147 // Payload pulls the request specific payload out of the claims. 148 func (ac *AuthorizationRequestClaims) Payload() interface{} { 149 return &ac.AuthorizationRequest 150 } 151 152 func (ac *AuthorizationRequestClaims) String() string { 153 return ac.ClaimsData.String(ac) 154 } 155 156 func (ac *AuthorizationRequestClaims) updateVersion() { 157 ac.GenericFields.Version = libVersion 158 } 159 160 type AuthorizationResponse struct { 161 Jwt string `json:"jwt,omitempty"` 162 Error string `json:"error,omitempty"` 163 // IssuerAccount stores the public key for the account the issuer represents. 164 // When set, the claim was issued by a signing key. 165 IssuerAccount string `json:"issuer_account,omitempty"` 166 GenericFields 167 } 168 169 type AuthorizationResponseClaims struct { 170 ClaimsData 171 AuthorizationResponse `json:"nats"` 172 } 173 174 func NewAuthorizationResponseClaims(subject string) *AuthorizationResponseClaims { 175 if subject == "" { 176 return nil 177 } 178 var ac AuthorizationResponseClaims 179 ac.Subject = subject 180 return &ac 181 } 182 183 // DecodeAuthorizationResponseClaims tries to parse an auth request claims from a JWT string 184 func DecodeAuthorizationResponseClaims(token string) (*AuthorizationResponseClaims, error) { 185 claims, err := Decode(token) 186 if err != nil { 187 return nil, err 188 } 189 ac, ok := claims.(*AuthorizationResponseClaims) 190 if !ok { 191 return nil, errors.New("not an authorization request claim") 192 } 193 return ac, nil 194 } 195 196 // ExpectedPrefixes defines the types that can encode an auth request jwt, servers. 197 func (ar *AuthorizationResponseClaims) ExpectedPrefixes() []nkeys.PrefixByte { 198 return []nkeys.PrefixByte{nkeys.PrefixByteAccount} 199 } 200 201 func (ar *AuthorizationResponseClaims) ClaimType() ClaimType { 202 return ar.Type 203 } 204 205 // Claims returns the request claims data. 206 func (ar *AuthorizationResponseClaims) Claims() *ClaimsData { 207 return &ar.ClaimsData 208 } 209 210 // Payload pulls the request specific payload out of the claims. 211 func (ar *AuthorizationResponseClaims) Payload() interface{} { 212 return &ar.AuthorizationResponse 213 } 214 215 func (ar *AuthorizationResponseClaims) String() string { 216 return ar.ClaimsData.String(ar) 217 } 218 219 func (ar *AuthorizationResponseClaims) updateVersion() { 220 ar.GenericFields.Version = libVersion 221 } 222 223 // Validate checks the generic and specific parts of the auth request jwt. 224 func (ar *AuthorizationResponseClaims) Validate(vr *ValidationResults) { 225 if !nkeys.IsValidPublicUserKey(ar.Subject) { 226 vr.AddError("Subject must be a user public key") 227 } 228 if !nkeys.IsValidPublicServerKey(ar.Audience) { 229 vr.AddError("Audience must be a server public key") 230 } 231 if ar.Error == "" && ar.Jwt == "" { 232 vr.AddError("Error or Jwt is required") 233 } 234 if ar.Error != "" && ar.Jwt != "" { 235 vr.AddError("Only Error or Jwt can be set") 236 } 237 if ar.IssuerAccount != "" && !nkeys.IsValidPublicAccountKey(ar.IssuerAccount) { 238 vr.AddError("issuer_account is not an account public key") 239 } 240 ar.ClaimsData.Validate(vr) 241 } 242 243 // Encode tries to turn the auth request claims into a JWT string. 244 func (ar *AuthorizationResponseClaims) Encode(pair nkeys.KeyPair) (string, error) { 245 ar.Type = AuthorizationResponseClaim 246 return ar.ClaimsData.encode(pair, ar) 247 }