stillbox/pkg/auth/apikey.go

51 lines
1.3 KiB
Go
Raw Permalink Normal View History

2024-07-29 00:21:07 -04:00
package auth
import (
"context"
2024-08-03 00:05:02 -04:00
"crypto/sha256"
"encoding/base64"
2024-07-29 00:21:07 -04:00
"time"
2024-11-03 07:19:03 -05:00
"dynatron.me/x/stillbox/pkg/database"
2024-07-29 00:21:07 -04:00
"github.com/google/uuid"
"github.com/rs/zerolog/log"
)
2024-07-29 00:58:32 -04:00
type apiKeyAuth interface {
2024-08-01 01:01:08 -04:00
// CheckAPIKey validates the provided key and returns the API owner's UserID.
2024-07-29 00:58:32 -04:00
// An error is returned if validation fails for any reason.
2024-08-01 01:01:08 -04:00
CheckAPIKey(ctx context.Context, key string) (*UserID, error)
2024-07-29 00:58:32 -04:00
}
2024-10-22 08:39:15 -04:00
func (a *Auth) CheckAPIKey(ctx context.Context, key string) (*UserID, error) {
2024-07-29 00:21:07 -04:00
keyUuid, err := uuid.Parse(key)
if err != nil {
log.Error().Str("apikey", key).Msg("cannot parse key")
return nil, ErrBadRequest
}
db := database.FromCtx(ctx)
2024-08-03 00:05:02 -04:00
hash := sha256.Sum256([]byte(keyUuid.String()))
b64hash := base64.StdEncoding.EncodeToString(hash[:])
apik, err := db.GetAPIKey(ctx, b64hash)
2024-07-29 00:21:07 -04:00
if err != nil {
if database.IsNoRows(err) {
log.Error().Str("apikey", keyUuid.String()).Msg("no such key")
return nil, ErrUnauthorized
}
2024-07-29 00:47:58 -04:00
log.Error().Str("apikey", keyUuid.String()).Err(err).Msg("error looking up key")
2024-07-29 00:21:07 -04:00
return nil, ErrInternal
}
if (apik.Disabled != nil && *apik.Disabled) || (apik.Expires.Valid && time.Now().After(apik.Expires.Time)) {
2024-08-03 00:05:02 -04:00
log.Error().Str("key", apik.ApiKey).Msg("key disabled")
2024-07-29 00:21:07 -04:00
return nil, ErrUnauthorized
}
2024-08-01 01:01:08 -04:00
owner := UserID(apik.Owner)
return &owner, nil
2024-07-29 00:21:07 -04:00
}