GraphQL API and utilities for the rpdata project
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
package auth
import ( "crypto/rand" "encoding/binary" "errors" "strconv"
"git.aiterp.net/rpdata/api/internal/store" "github.com/globalsign/mgo" )
var keyCollection *mgo.Collection
// A Key contains a JWT secret and the limitations of it. There are two types of
// keys, single-user keys and wildcard keys. The former is used to authenticate
// a single user (e.g. the logbot) through an API while the latter is only for
// services that can be trusted to perform its own authentication (a frontend).
type Key struct { ID string `bson:"_id"` Name string `bson:"name"` User string `bson:"user"` Secret string `bson:"secret"` }
// ValidForUser returns true if the key's user is the same as
// the user, or it's a wildcard key.
func (key *Key) ValidForUser(user string) bool { return key.User == user || key.User == "*" }
// FindKey finds a key by kid (key ID)
func FindKey(kid string) (Key, error) { key := Key{} err := keyCollection.FindId(kid).One(&key)
return key, err }
// NewKey generates a new key for the user and name. This
// does not allow generating wildcard keys, they have to be
// manually inserted into the DB.
func NewKey(name, user string) (*Key, error) { if user == "*" { return nil, errors.New("auth: wildcard keys not allowed") }
secret, err := makeKeySecret() if err != nil { return nil, err }
key := &Key{ ID: makeKeyID(), Name: name, User: user, Secret: secret, }
if err := keyCollection.Insert(key); err != nil { return nil, err }
return key, nil }
func init() { store.HandleInit(func(db *mgo.Database) { keyCollection = db.C("auth.keys")
keyCollection.EnsureIndexKey("user") }) }
// makeKeyID makes a random story ID that's 16 characters long
func makeKeyID() string { result := "K" offset := 0 data := make([]byte, 32)
rand.Read(data) for len(result) < 16 { result += strconv.FormatUint(binary.LittleEndian.Uint64(data[offset:]), 36) offset += 8
if offset >= 32 { rand.Read(data) offset = 0 } }
return result[:16] }
func makeKeySecret() (string, error) { data := make([]byte, 64) alphabet := "0123456789abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSUTVWXYZ-_"
_, err := rand.Read(data) if err != nil { return "", err }
for i := range data { data[i] = alphabet[data[i]%64] }
return string(data), nil }
|