Files
QSfera/Server/vendor/github.com/nats-io/jwt/v2/signingkeys.go
T
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

214 lines
4.4 KiB
Go

/*
* Copyright 2020-2024 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"encoding/json"
"errors"
"fmt"
"sort"
"github.com/nats-io/nkeys"
)
type Scope interface {
SigningKey() string
ValidateScopedSigner(claim Claims) error
Validate(vr *ValidationResults)
}
type ScopeType int
const (
UserScopeType ScopeType = iota + 1
)
func (t ScopeType) String() string {
switch t {
case UserScopeType:
return "user_scope"
}
return "unknown"
}
func (t *ScopeType) MarshalJSON() ([]byte, error) {
switch *t {
case UserScopeType:
return []byte("\"user_scope\""), nil
}
return nil, fmt.Errorf("unknown scope type %q", t)
}
func (t *ScopeType) UnmarshalJSON(b []byte) error {
var s string
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
switch s {
case "user_scope":
*t = UserScopeType
return nil
}
return fmt.Errorf("unknown scope type %q", t)
}
type UserScope struct {
Kind ScopeType `json:"kind"`
Key string `json:"key"`
Role string `json:"role"`
Template UserPermissionLimits `json:"template"`
Description string `json:"description"`
}
func NewUserScope() *UserScope {
var s UserScope
s.Kind = UserScopeType
s.Template.NatsLimits = NatsLimits{NoLimit, NoLimit, NoLimit}
return &s
}
func (us UserScope) SigningKey() string {
return us.Key
}
func (us UserScope) Validate(vr *ValidationResults) {
if !nkeys.IsValidPublicAccountKey(us.Key) {
vr.AddError("%s is not an account public key", us.Key)
}
}
func (us UserScope) ValidateScopedSigner(c Claims) error {
uc, ok := c.(*UserClaims)
if !ok {
return fmt.Errorf("not an user claim - scoped signing key requires user claim")
}
if uc.Claims().Issuer != us.Key {
return errors.New("issuer not the scoped signer")
}
if !uc.HasEmptyPermissions() {
return errors.New("scoped users require no permissions or limits set")
}
return nil
}
// SigningKeys is a map keyed by a public account key
type SigningKeys map[string]Scope
func (sk SigningKeys) Validate(vr *ValidationResults) {
for k, v := range sk {
// regular signing keys won't have a scope
if v != nil {
v.Validate(vr)
} else {
if !nkeys.IsValidPublicAccountKey(k) {
vr.AddError("%q is not a valid account signing key", k)
}
}
}
}
// MarshalJSON serializes the scoped signing keys as an array
func (sk *SigningKeys) MarshalJSON() ([]byte, error) {
if sk == nil {
return nil, nil
}
keys := sk.Keys()
sort.Strings(keys)
var a []interface{}
for _, k := range keys {
if (*sk)[k] != nil {
a = append(a, (*sk)[k])
} else {
a = append(a, k)
}
}
return json.Marshal(a)
}
func (sk *SigningKeys) UnmarshalJSON(data []byte) error {
if *sk == nil {
*sk = make(SigningKeys)
}
// read an array - we can have a string or an map
var a []interface{}
if err := json.Unmarshal(data, &a); err != nil {
return err
}
for _, i := range a {
switch v := i.(type) {
case string:
(*sk)[v] = nil
case map[string]interface{}:
d, err := json.Marshal(v)
if err != nil {
return err
}
switch v["kind"] {
case UserScopeType.String():
us := NewUserScope()
if err := json.Unmarshal(d, &us); err != nil {
return err
}
(*sk)[us.Key] = us
default:
return fmt.Errorf("unknown signing key scope %q", v["type"])
}
}
}
return nil
}
func (sk SigningKeys) Keys() []string {
var keys []string
for k := range sk {
keys = append(keys, k)
}
return keys
}
// GetScope returns nil if the key is not associated
func (sk SigningKeys) GetScope(k string) (Scope, bool) {
v, ok := sk[k]
if !ok {
return nil, false
}
return v, true
}
func (sk SigningKeys) Contains(k string) bool {
_, ok := sk[k]
return ok
}
func (sk SigningKeys) Add(keys ...string) {
for _, k := range keys {
sk[k] = nil
}
}
func (sk SigningKeys) AddScopedSigner(s Scope) {
sk[s.SigningKey()] = s
}
func (sk SigningKeys) Remove(keys ...string) {
for _, k := range keys {
delete(sk, k)
}
}