summaryrefslogtreecommitdiff
path: root/player-server/internal
diff options
context:
space:
mode:
Diffstat (limited to 'player-server/internal')
-rw-r--r--player-server/internal/auth/interfaces.go4
-rw-r--r--player-server/internal/auth/token.go9
-rw-r--r--player-server/internal/auth/token_test.go5
-rw-r--r--player-server/internal/service/auth.go7
-rw-r--r--player-server/internal/service/auth_test.go4
5 files changed, 21 insertions, 8 deletions
diff --git a/player-server/internal/auth/interfaces.go b/player-server/internal/auth/interfaces.go
index 790c534..e167a60 100644
--- a/player-server/internal/auth/interfaces.go
+++ b/player-server/internal/auth/interfaces.go
@@ -15,7 +15,9 @@ type SessionManager interface {
}
// TokenManager is the abstraction for API token generation and hashing.
+// Generate returns an error when the system random source fails so callers
+// can surface the failure (e.g. via HTTP 500) instead of panicking.
type TokenManager interface {
- Generate() (plaintext, hash string)
+ Generate() (plaintext, hash string, err error)
Hash(plaintext string) string
}
diff --git a/player-server/internal/auth/token.go b/player-server/internal/auth/token.go
index bdb7e6b..bcb696f 100644
--- a/player-server/internal/auth/token.go
+++ b/player-server/internal/auth/token.go
@@ -20,14 +20,17 @@ func NewTokenManager() TokenManager {
}
// Generate creates a plaintext API token and its stored hash.
-func (m *tokenManager) Generate() (plaintext, hash string) {
+// Returns an error if the system random source fails. A crypto/rand.Read
+// failure indicates a process-level emergency, so callers should propagate
+// the error upward rather than masking it.
+func (m *tokenManager) Generate() (plaintext, hash string, err error) {
b := make([]byte, tokenByteLength)
if _, err := rand.Read(b); err != nil {
- panic(fmt.Sprintf("generate token: %v", err))
+ return "", "", fmt.Errorf("generate token: %w", err)
}
plaintext = hex.EncodeToString(b)
- return plaintext, m.Hash(plaintext)
+ return plaintext, m.Hash(plaintext), nil
}
// Hash returns the SHA-256 hash of a plaintext API token.
diff --git a/player-server/internal/auth/token_test.go b/player-server/internal/auth/token_test.go
index bf18aa5..a9bddf8 100644
--- a/player-server/internal/auth/token_test.go
+++ b/player-server/internal/auth/token_test.go
@@ -11,7 +11,10 @@ func TestTokenManager_Generate(t *testing.T) {
seen := make(map[string]string)
for i := 0; i < 1000; i++ {
- plaintext, hash := tm.Generate()
+ plaintext, hash, err := tm.Generate()
+ if err != nil {
+ t.Fatalf("generate token: %v", err)
+ }
if len(plaintext) != tokenByteLength*2 {
t.Fatalf("expected plaintext length %d, got %d", tokenByteLength*2, len(plaintext))
}
diff --git a/player-server/internal/service/auth.go b/player-server/internal/service/auth.go
index 6bd2055..1fe468b 100644
--- a/player-server/internal/service/auth.go
+++ b/player-server/internal/service/auth.go
@@ -92,8 +92,13 @@ func (s *authService) Login(ctx context.Context, username, password string) (*Au
}
// CreateAPIToken creates a hashed API token and returns the one-time plaintext value.
+// A token generation failure (e.g. crypto/rand.Read returning an error) is
+// surfaced to the caller; the HTTP layer translates it into a 500 response.
func (s *authService) CreateAPIToken(ctx context.Context, userID int64, name string, expiresAt *time.Time) (*CreateAPITokenResult, error) {
- plaintext, hash := s.tm.Generate()
+ plaintext, hash, err := s.tm.Generate()
+ if err != nil {
+ return nil, fmt.Errorf("generate api token: %w", err)
+ }
now := s.clock.Now()
token := &model.APIToken{
UserID: userID,
diff --git a/player-server/internal/service/auth_test.go b/player-server/internal/service/auth_test.go
index 213f6e5..b01a2b3 100644
--- a/player-server/internal/service/auth_test.go
+++ b/player-server/internal/service/auth_test.go
@@ -16,8 +16,8 @@ type fixedTokenManager struct {
hash string
}
-func (m fixedTokenManager) Generate() (string, string) {
- return m.plaintext, m.hash
+func (m fixedTokenManager) Generate() (string, string, error) {
+ return m.plaintext, m.hash, nil
}
func (m fixedTokenManager) Hash(plaintext string) string {