diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-17 21:24:34 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-17 21:24:34 +0300 |
| commit | a44aab26ae83d35d7bf83a4531c6c7fa77702b0d (patch) | |
| tree | 7bf4c922c12e268e9563090ff0fa4fdbc0f3f563 /player-server/internal/auth/token.go | |
| parent | a7fbe6d5008decde1e2402b422300d83d3a3de0e (diff) | |
Add TokenManager for API token generation and hashing
Diffstat (limited to 'player-server/internal/auth/token.go')
| -rw-r--r-- | player-server/internal/auth/token.go | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/player-server/internal/auth/token.go b/player-server/internal/auth/token.go new file mode 100644 index 0000000..bdb7e6b --- /dev/null +++ b/player-server/internal/auth/token.go @@ -0,0 +1,39 @@ +package auth + +import ( + "crypto/rand" + "crypto/sha256" + "encoding/hex" + "fmt" +) + +const tokenByteLength = 32 + +// Compile-time check that *tokenManager satisfies the TokenManager interface. +var _ TokenManager = (*tokenManager)(nil) + +type tokenManager struct{} + +// NewTokenManager creates a TokenManager. +func NewTokenManager() TokenManager { + return &tokenManager{} +} + +// Generate creates a plaintext API token and its stored hash. +func (m *tokenManager) Generate() (plaintext, hash string) { + b := make([]byte, tokenByteLength) + if _, err := rand.Read(b); err != nil { + panic(fmt.Sprintf("generate token: %v", err)) + } + + plaintext = hex.EncodeToString(b) + return plaintext, m.Hash(plaintext) +} + +// Hash returns the SHA-256 hash of a plaintext API token. +func (m *tokenManager) Hash(plaintext string) string { + // SHA-256 is used instead of bcrypt because API tokens are high-entropy + // random bytes; bcrypt adds CPU cost without meaningful security benefit. + sum := sha256.Sum256([]byte(plaintext)) + return hex.EncodeToString(sum[:]) +} |
