91 lines
2.0 KiB
Go
91 lines
2.0 KiB
Go
|
// Copyright (C) 2022 Storj Labs, Inc.
|
||
|
// See LICENSE for copying information.
|
||
|
|
||
|
package consoleauth
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/base64"
|
||
|
"time"
|
||
|
|
||
|
"github.com/spacemonkeygo/monkit/v3"
|
||
|
|
||
|
"storj.io/common/uuid"
|
||
|
)
|
||
|
|
||
|
var mon = monkit.Package()
|
||
|
|
||
|
// Config contains configuration parameters for console auth.
|
||
|
type Config struct {
|
||
|
TokenExpirationTime time.Duration `help:"expiration time for auth tokens, account recovery tokens, and activation tokens" default:"24h"`
|
||
|
}
|
||
|
|
||
|
// Service handles creating, signing, and checking the expiration of auth tokens.
|
||
|
type Service struct {
|
||
|
config Config
|
||
|
Signer
|
||
|
}
|
||
|
|
||
|
// NewService creates a new consoleauth service.
|
||
|
func NewService(config Config, signer Signer) *Service {
|
||
|
return &Service{
|
||
|
config: config,
|
||
|
Signer: signer,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Signer creates signature for provided data.
|
||
|
type Signer interface {
|
||
|
Sign(data []byte) ([]byte, error)
|
||
|
}
|
||
|
|
||
|
// CreateToken creates a new auth token.
|
||
|
func (s *Service) CreateToken(ctx context.Context, id uuid.UUID, email string) (_ string, err error) {
|
||
|
defer mon.Task()(&ctx)(&err)
|
||
|
claims := &Claims{
|
||
|
ID: id,
|
||
|
Expiration: time.Now().Add(s.config.TokenExpirationTime),
|
||
|
}
|
||
|
if email != "" {
|
||
|
claims.Email = email
|
||
|
}
|
||
|
|
||
|
return s.createToken(ctx, claims)
|
||
|
}
|
||
|
|
||
|
// createToken creates string representation.
|
||
|
func (s *Service) createToken(ctx context.Context, claims *Claims) (_ string, err error) {
|
||
|
defer mon.Task()(&ctx)(&err)
|
||
|
|
||
|
json, err := claims.JSON()
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
token := Token{Payload: json}
|
||
|
err = s.SignToken(&token)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
return token.String(), nil
|
||
|
}
|
||
|
|
||
|
// SignToken signs token.
|
||
|
func (s *Service) SignToken(token *Token) error {
|
||
|
encoded := base64.URLEncoding.EncodeToString(token.Payload)
|
||
|
|
||
|
signature, err := s.Signer.Sign([]byte(encoded))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
token.Signature = signature
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// IsExpired returns whether token is expired.
|
||
|
func (s *Service) IsExpired(now, tokenCreatedAt time.Time) bool {
|
||
|
return now.Sub(tokenCreatedAt) > s.config.TokenExpirationTime
|
||
|
}
|