package auth import ( "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/hex" "fmt" ) // GenerateAPIToken returns a full plaintext token (shown once to the user), // its sha256 hash (stored in the DB), and a short prefix (stored alongside // the hash so the UI can display "vp_ab12..." without ever re-showing the // secret). func GenerateAPIToken() (plaintext, hash, prefix string, err error) { b := make([]byte, 32) if _, err = rand.Read(b); err != nil { return } secret := base64.RawURLEncoding.EncodeToString(b) plaintext = "vp_" + secret hash = HashAPIToken(plaintext) prefix = plaintext[:8] return } func HashAPIToken(token string) string { sum := sha256.Sum256([]byte(token)) return hex.EncodeToString(sum[:]) } func FormatTokenPreview(prefix string) string { return fmt.Sprintf("%s%s", prefix, "…") }