mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-29 18:19:07 +02:00
76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
usedTokenKeyPrefix = "jwt-used:"
|
|
usedTokenMarker = "1"
|
|
)
|
|
|
|
var (
|
|
ErrTokenAlreadyUsed = errors.New("JWT already used")
|
|
ErrTokenExpired = errors.New("JWT expired")
|
|
)
|
|
|
|
// TokenCache atomically records used JWTs until their expiration.
|
|
type TokenCache interface {
|
|
SetNX(ctx context.Context, key, value string, ttl time.Duration) (bool, error)
|
|
}
|
|
|
|
type SessionStore struct {
|
|
cache TokenCache
|
|
}
|
|
|
|
func NewSessionStore(cacheStore TokenCache) *SessionStore {
|
|
return &SessionStore{cache: cacheStore}
|
|
}
|
|
|
|
// RegisterToken records a JWT until its exp time and rejects reuse.
|
|
func (s *SessionStore) RegisterToken(ctx context.Context, token string, expiresAt time.Time) error {
|
|
ttl := time.Until(expiresAt)
|
|
if ttl <= 0 {
|
|
return ErrTokenExpired
|
|
}
|
|
|
|
key := usedTokenKeyPrefix + hashToken(token)
|
|
created, err := s.cache.SetNX(ctx, key, usedTokenMarker, ttl)
|
|
if err != nil {
|
|
return fmt.Errorf("store used token entry: %w", err)
|
|
}
|
|
if !created {
|
|
return ErrTokenAlreadyUsed
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func hashToken(token string) string {
|
|
sum := sha256.Sum256([]byte(canonicalizeToken(token)))
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
// canonicalizeToken re-encodes the JWT signature segment so noncanonical
|
|
// spellings of the same signature map to one stable cache key.
|
|
func canonicalizeToken(token string) string {
|
|
parts := strings.Split(token, ".")
|
|
if len(parts) != 3 {
|
|
return token
|
|
}
|
|
|
|
sig, err := base64.RawURLEncoding.DecodeString(parts[2])
|
|
if err != nil {
|
|
return token
|
|
}
|
|
|
|
return parts[0] + "." + parts[1] + "." + base64.RawURLEncoding.EncodeToString(sig)
|
|
}
|