91 lines
2.3 KiB
Go
91 lines
2.3 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
)
|
|
|
|
var (
|
|
// ErrInvalidAPIKey is returned when the API key is invalid.
|
|
ErrInvalidAPIKey = errors.New("invalid API key")
|
|
)
|
|
|
|
// APIKeyLookup is a function that looks up a user by API key.
|
|
// Returns nil user and no error if the key is not found.
|
|
type APIKeyLookup func(ctx context.Context, key string) (*User, error)
|
|
|
|
// APIKeyValidator validates API keys using a lookup function.
|
|
type APIKeyValidator struct {
|
|
lookup APIKeyLookup
|
|
}
|
|
|
|
// NewAPIKeyValidator creates a new API key validator.
|
|
//
|
|
// Example with database lookup:
|
|
//
|
|
// validator := auth.NewAPIKeyValidator(func(ctx context.Context, key string) (*auth.User, error) {
|
|
// apiKey, err := db.GetAPIKeyByHash(ctx, hashKey(key))
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
// if apiKey == nil {
|
|
// return nil, nil // Key not found
|
|
// }
|
|
// return &auth.User{
|
|
// ID: apiKey.UserID,
|
|
// Scopes: apiKey.Scopes,
|
|
// }, nil
|
|
// })
|
|
func NewAPIKeyValidator(lookup APIKeyLookup) *APIKeyValidator {
|
|
return &APIKeyValidator{lookup: lookup}
|
|
}
|
|
|
|
// Validate validates an API key and returns the associated user.
|
|
func (v *APIKeyValidator) Validate(ctx context.Context, key string) (*User, error) {
|
|
if key == "" {
|
|
return nil, ErrInvalidAPIKey
|
|
}
|
|
|
|
user, err := v.lookup(ctx, key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if user == nil {
|
|
return nil, ErrInvalidAPIKey
|
|
}
|
|
|
|
return user, nil
|
|
}
|
|
|
|
// StaticAPIKeyValidator validates against a static set of API keys.
|
|
// Useful for simple use cases or testing.
|
|
type StaticAPIKeyValidator struct {
|
|
keys map[string]*User
|
|
}
|
|
|
|
// NewStaticAPIKeyValidator creates a validator with static API keys.
|
|
//
|
|
// Example:
|
|
//
|
|
// validator := auth.NewStaticAPIKeyValidator(map[string]*auth.User{
|
|
// "sk-test-123": {ID: "user-1", Scopes: []string{"read", "write"}},
|
|
// "sk-test-456": {ID: "user-2", Scopes: []string{"read"}},
|
|
// })
|
|
func NewStaticAPIKeyValidator(keys map[string]*User) *StaticAPIKeyValidator {
|
|
return &StaticAPIKeyValidator{keys: keys}
|
|
}
|
|
|
|
// Validate validates an API key against the static key map.
|
|
func (v *StaticAPIKeyValidator) Validate(ctx context.Context, key string) (*User, error) {
|
|
if key == "" {
|
|
return nil, ErrInvalidAPIKey
|
|
}
|
|
|
|
user, ok := v.keys[key]
|
|
if !ok {
|
|
return nil, ErrInvalidAPIKey
|
|
}
|
|
|
|
return user, nil
|
|
}
|