authkit: initial shared auth module
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
||||
package authkit
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ExtractAPIKey pulls the API key from r.
|
||||
// Checks X-API-Key first, then "Authorization: Bearer <k>".
|
||||
// Returns "" if neither is present.
|
||||
func ExtractAPIKey(r *http.Request) string {
|
||||
if v := strings.TrimSpace(r.Header.Get("X-API-Key")); v != "" {
|
||||
return v
|
||||
}
|
||||
auth := strings.TrimSpace(r.Header.Get("Authorization"))
|
||||
if strings.HasPrefix(auth, "Bearer ") {
|
||||
return strings.TrimSpace(auth[len("Bearer "):])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ConstantTimeEqualString compares a and b in constant time.
|
||||
func ConstantTimeEqualString(a, b string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
|
||||
}
|
||||
|
||||
// ConstantTimeEqualHashedKey hashes candidatePlain with sha256 and compares
|
||||
// against storedHashHex in constant time. Returns false on bad hex; never panics.
|
||||
func ConstantTimeEqualHashedKey(candidatePlain, storedHashHex string) bool {
|
||||
stored, err := hex.DecodeString(storedHashHex)
|
||||
if err != nil || len(stored) != sha256.Size {
|
||||
return false
|
||||
}
|
||||
sum := sha256.Sum256([]byte(candidatePlain))
|
||||
return subtle.ConstantTimeCompare(sum[:], stored) == 1
|
||||
}
|
||||
Reference in New Issue
Block a user