fix(auth): recover refresh rotations and configure session lifetime
This commit is contained in:
+24
-6
@@ -4,7 +4,9 @@ import (
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
_ "modernc.org/sqlite"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@@ -27,12 +29,17 @@ type Instance struct {
|
||||
Created time.Time `json:"created_at"`
|
||||
}
|
||||
type Store struct {
|
||||
DB *sql.DB
|
||||
closed chan struct{}
|
||||
closeOnce sync.Once
|
||||
DB *sql.DB
|
||||
sessionTTL time.Duration
|
||||
closed chan struct{}
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
func Open(path string) (*Store, error) {
|
||||
ttl, err := sessionLifetime(os.Getenv("SESSION_TTL"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db, e := sql.Open("sqlite", path)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
@@ -47,7 +54,18 @@ func Open(path string) (*Store, error) {
|
||||
db.Close()
|
||||
return nil, e
|
||||
}
|
||||
return &Store{DB: db, closed: make(chan struct{})}, nil
|
||||
return &Store{DB: db, sessionTTL: ttl, closed: make(chan struct{})}, nil
|
||||
}
|
||||
|
||||
func sessionLifetime(value string) (time.Duration, error) {
|
||||
if value == "" {
|
||||
return 24 * time.Hour, nil
|
||||
}
|
||||
ttl, err := time.ParseDuration(value)
|
||||
if err != nil || ttl < time.Second || ttl%time.Second != 0 {
|
||||
return 0, fmt.Errorf("SESSION_TTL must be a positive whole-second duration, e.g. 24h or 168h")
|
||||
}
|
||||
return ttl, nil
|
||||
}
|
||||
func (s *Store) Close() { s.closeOnce.Do(func() { close(s.closed); s.DB.Close() }) }
|
||||
func (s *Store) Done() <-chan struct{} { return s.closed }
|
||||
@@ -85,14 +103,14 @@ func (s *Store) Password(name string) (string, error) {
|
||||
}
|
||||
func (s *Store) Session(uid string) (string, string, error) {
|
||||
id, csrf := ID(), ID()
|
||||
_, e := s.DB.Exec("INSERT INTO sessions VALUES(?,?,?,?)", id, uid, csrf, time.Now().Add(24*time.Hour).Unix())
|
||||
_, e := s.DB.Exec("INSERT INTO sessions VALUES(?,?,?,?)", id, uid, csrf, time.Now().Add(s.sessionTTL).Unix())
|
||||
return id, csrf, e
|
||||
}
|
||||
func (s *Store) SessionUser(id string) (User, string, error) {
|
||||
var uid, csrf string
|
||||
var exp int64
|
||||
e := s.DB.QueryRow("SELECT uid,csrf,expires FROM sessions WHERE id=?", id).Scan(&uid, &csrf, &exp)
|
||||
if e != nil || exp < time.Now().Unix() {
|
||||
if e != nil || exp <= time.Now().Unix() {
|
||||
return User{}, "", sql.ErrNoRows
|
||||
}
|
||||
u, e := s.UserByID(uid)
|
||||
|
||||
Reference in New Issue
Block a user