Documentation
¶
Overview ¶
Package gouncer provides composable authentication primitives for Go.
Index ¶
Examples ¶
Constants ¶
const DefaultSessionDuration = 30 * 24 * time.Hour
DefaultSessionDuration is the lifetime NewSession applies.
Variables ¶
var ErrEmailTaken = errors.New("gouncer: email already taken")
ErrEmailTaken reports that another user already owns the email.
var ErrEmptyName = errors.New("gouncer: empty name")
ErrEmptyName reports that a user name is empty or only whitespace.
var ErrInvalidEmail = errors.New("gouncer: invalid email")
ErrInvalidEmail reports that an email address is not a plain valid address.
var ErrNameTooLong = errors.New("gouncer: name longer than 256 characters")
ErrNameTooLong reports that a name exceeds the maximum length.
var ErrPasswordTooLong = errors.New("gouncer: password longer than 1024 characters")
ErrPasswordTooLong reports that a password exceeds the maximum length.
var ErrSessionNotFound = errors.New("gouncer: session not found")
ErrSessionNotFound reports that no usable session exists for a token: it is unknown, expired, or its user is disabled.
var ErrUserNotFound = errors.New("gouncer: user not found")
ErrUserNotFound reports that no user exists for the requested email.
var ErrWeakPassword = errors.New("gouncer: password shorter than 12 characters")
ErrWeakPassword reports that a password is shorter than the minimum length.
Functions ¶
func HashToken ¶
HashToken returns the digest under which a session token is persisted and looked up.
func VerifyPassword ¶
VerifyPassword reports whether password matches the argon2id PHC hash. It never panics, a malformed or out-of-envelope hash never matches.
Example ¶
package main
import (
"fmt"
"github.com/gopherium/gouncer"
)
func main() {
u, err := gouncer.NewUser("ada@example.com", "Ada Lovelace", "correct horse battery")
if err != nil {
return
}
fmt.Println(gouncer.VerifyPassword(u.PasswordHash, "correct horse battery"))
fmt.Println(gouncer.VerifyPassword(u.PasswordHash, "wrong password entirely"))
}
Output: true false
Types ¶
type Session ¶
type Session struct {
Token string
TokenHash []byte
UserID uuid.UUID
CreatedAt time.Time
ExpiresAt time.Time
}
Session is a login session. Build one with NewSession. Token is handed to the client once, only TokenHash is persisted.
func NewSession ¶
NewSession issues a session for the user with a fresh random token.
Example ¶
package main
import (
"fmt"
"github.com/google/uuid"
"github.com/gopherium/gouncer"
)
func main() {
s, err := gouncer.NewSession(uuid.Must(uuid.NewV7()))
if err != nil {
return
}
_ = s.Token
fmt.Println(len(s.TokenHash))
}
Output: 32
type Store ¶
type Store interface {
// CreateUser stores u, or returns [ErrEmailTaken].
CreateUser(ctx context.Context, u User) error
// UserByEmail returns the user with the normalized email, or [ErrUserNotFound].
UserByEmail(ctx context.Context, email string) (User, error)
// CreateSession stores s.
CreateSession(ctx context.Context, s Session) error
// UserBySession returns the user owning the session, or [ErrSessionNotFound].
UserBySession(ctx context.Context, tokenHash []byte, now time.Time) (User, error)
// DeleteSession removes the session. Removing an absent one is not an error.
DeleteSession(ctx context.Context, tokenHash []byte) error
}
Store persists users and their login sessions, returning the package's Err* sentinels so callers can branch with errors.Is.
type User ¶
type User struct {
ID uuid.UUID
Email string
Name string
PasswordHash string
Disabled bool
CreatedAt time.Time
}
User is an account holder with password credentials. Build one with NewUser.
func NewUser ¶
NewUser returns a validated User with a normalized email, a trimmed name, and the password stored as an argon2id hash. Invalid input returns one of the package's Err* sentinels.
Example ¶
package main
import (
"fmt"
"github.com/gopherium/gouncer"
)
func main() {
u, err := gouncer.NewUser("ada@example.com", "Ada Lovelace", "correct horse battery")
if err != nil {
return
}
fmt.Println(u.Email)
}
Output: ada@example.com