Stack of changes to get gin, scs, nosurf running.
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
)
|
||||
|
||||
func LoadKeyFromFile(path string) ([]byte, error) {
|
||||
key, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bytes.TrimSpace(key), nil
|
||||
}
|
||||
|
||||
func ZeroBytes(b []byte) {
|
||||
for i := range b {
|
||||
b[i] = 0
|
||||
}
|
||||
}
|
||||
69
internal/helpers/session/remember.go
Normal file
69
internal/helpers/session/remember.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"time"
|
||||
)
|
||||
|
||||
func randomBase64(n int) (string, error) {
|
||||
b := make([]byte, n)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.RawURLEncoding.EncodeToString(b), nil
|
||||
}
|
||||
|
||||
func HashVerifier(verifier string) string {
|
||||
sum := sha256.Sum256([]byte(verifier))
|
||||
return base64.RawURLEncoding.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
// StoreToken inserts a new token row
|
||||
func StoreToken(db *sql.DB, userID int64, selector, verifierHash string, expiresAt time.Time) error {
|
||||
_, err := db.Exec(`
|
||||
INSERT INTO remember_tokens (user_id, selector, verifier_hash, issued_at, expires_at)
|
||||
VALUES ($1,$2,$3,NOW(),$4)`, userID, selector, verifierHash, expiresAt)
|
||||
return err
|
||||
}
|
||||
|
||||
// FindToken fetches selector+hash
|
||||
func FindToken(db *sql.DB, selector string) (userID int64, verifierHash string, expiresAt time.Time, revokedAt *time.Time, err error) {
|
||||
err = db.QueryRow(`SELECT user_id, verifier_hash, expires_at, revoked_at FROM remember_tokens WHERE selector=$1`, selector).
|
||||
Scan(&userID, &verifierHash, &expiresAt, &revokedAt)
|
||||
return
|
||||
}
|
||||
|
||||
// RevokeToken marks token as revoked
|
||||
func RevokeToken(db *sql.DB, selector string) error {
|
||||
_, err := db.Exec(`UPDATE remember_tokens SET revoked_at=NOW() WHERE selector=$1`, selector)
|
||||
return err
|
||||
}
|
||||
|
||||
// GenerateAndStore creates a new remember-me token, stores it server-side,
|
||||
// and returns the cookie-safe plaintext value to set on the client
|
||||
func GenerateAndStore(db *sql.DB, userID int64, duration time.Duration) (string, time.Time, error) {
|
||||
selector, err := randomBase64(16)
|
||||
if err != nil {
|
||||
return "", time.Time{}, err
|
||||
}
|
||||
|
||||
verifier, err := randomBase64(32)
|
||||
if err != nil {
|
||||
return "", time.Time{}, err
|
||||
}
|
||||
|
||||
hash := HashVerifier(verifier)
|
||||
expires := time.Now().Add(duration)
|
||||
|
||||
if err := StoreToken(db, userID, selector, hash, expires); err != nil {
|
||||
return "", time.Time{}, err
|
||||
}
|
||||
|
||||
// The client cookie value contains selector + verifier
|
||||
cookieVal := selector + ":" + verifier
|
||||
|
||||
return cookieVal, expires, nil
|
||||
}
|
||||
Reference in New Issue
Block a user