summaryrefslogtreecommitdiff
path: root/player-server/internal/auth/token.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-17 21:24:34 +0300
committerPaul Buetow <paul@buetow.org>2026-05-17 21:24:34 +0300
commita44aab26ae83d35d7bf83a4531c6c7fa77702b0d (patch)
tree7bf4c922c12e268e9563090ff0fa4fdbc0f3f563 /player-server/internal/auth/token.go
parenta7fbe6d5008decde1e2402b422300d83d3a3de0e (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.go39
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[:])
+}