54 lines
1.4 KiB
Go
54 lines
1.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"time"
|
|
|
|
"gardomatic.kleiax.de/internal/platform/validate"
|
|
)
|
|
|
|
const (
|
|
// ScopeActivation identifies account activation tokens.
|
|
ScopeActivation = "activation"
|
|
// ScopeAuthentication identifies bearer authentication tokens.
|
|
ScopeAuthentication = "authentication"
|
|
// ScopePasswordReset identifies password reset tokens.
|
|
ScopePasswordReset = "password-reset"
|
|
)
|
|
|
|
// Token carries a one-time plaintext token and the hash persisted by storage.
|
|
type Token struct {
|
|
Plaintext string `json:"token"`
|
|
Hash []byte `json:"-"`
|
|
UserID int `json:"-"`
|
|
Expiry time.Time `json:"expiry"`
|
|
Scope string `json:"-"`
|
|
}
|
|
|
|
// NewToken creates a cryptographically random token for a user and scope.
|
|
func NewToken(userID int, ttl time.Duration, scope string) Token {
|
|
token := Token{
|
|
Plaintext: rand.Text(),
|
|
UserID: userID,
|
|
Expiry: time.Now().Add(ttl),
|
|
Scope: scope,
|
|
}
|
|
|
|
hash := sha256.Sum256([]byte(token.Plaintext))
|
|
token.Hash = hash[:]
|
|
|
|
return token
|
|
}
|
|
|
|
// Validate adds token consistency errors to v.
|
|
func (tk Token) Validate(v *validate.Validator) {
|
|
ValidateTokenPlaintext(v, tk.Plaintext)
|
|
}
|
|
|
|
// ValidateTokenPlaintext checks the expected format of a user-supplied token.
|
|
func ValidateTokenPlaintext(v *validate.Validator, tokenPlaintext string) {
|
|
v.Check(tokenPlaintext != "", "token", "must be provided")
|
|
v.Check(len(tokenPlaintext) == 26, "token", "must be 26 bytes long")
|
|
}
|