[server][core][publinks] Use configurable auth for publinks (pbkdf by default)

This commit is contained in:
Abhishek Shroff
2025-07-13 22:48:51 +05:30
parent 7b7ad24133
commit 4e87878f88
6 changed files with 63 additions and 26 deletions

View File

@@ -10,23 +10,12 @@ import (
"github.com/jackc/pgx/v5"
)
type Auth interface {
SupportsPasswordUpdate() bool
UpdateUserPassword(db db.Handler, email, password string) error
VerifyUserPassword(db db.Handler, email, password string) (bool, error)
type Crypt struct {
generator PasswordHasher
}
type auth struct {
cfg Config
generator interface {
GenerateEncodedHash(password string) (string, error)
}
}
func New(cfg Config) (Auth, error) {
var generator interface {
GenerateEncodedHash(password string) (string, error)
}
func New(cfg Config) (*Crypt, error) {
var generator PasswordHasher
if cfg.Hash == "argon2" {
generator = argon2.New(cfg.Argon2)
} else if cfg.Hash == "pbkdf2" {
@@ -39,17 +28,16 @@ func New(cfg Config) (Auth, error) {
return nil, errors.New("unrecognized hashing algorithm: " + cfg.Hash)
}
return &auth{
cfg: cfg,
return &Crypt{
generator: generator,
}, nil
}
func (a *auth) SupportsPasswordUpdate() bool {
func (a *Crypt) SupportsPasswordUpdate() bool {
return true
}
func (a *auth) UpdateUserPassword(db db.Handler, email, password string) error {
func (a *Crypt) UpdateUserPassword(db db.Handler, email, password string) error {
const q = "UPDATE users SET password_hash = $2::TEXT, modified = NOW() WHERE email = $1::TEXT"
if hash, err := a.generator.GenerateEncodedHash(password); err != nil {
return err
@@ -61,7 +49,7 @@ func (a *auth) UpdateUserPassword(db db.Handler, email, password string) error {
return nil
}
func (a *auth) VerifyUserPassword(db db.Handler, email, password string) (bool, error) {
func (a *Crypt) VerifyUserPassword(db db.Handler, email, password string) (bool, error) {
const q = "SELECT password_hash FROM users WHERE email = $1::TEXT"
row := db.QueryRow(q, strings.ToLower(email))
var encodedHash string

View File

@@ -0,0 +1,26 @@
package crypt
import (
"errors"
"codeberg.org/shroff/phylum/server/internal/auth/crypt/argon2"
"codeberg.org/shroff/phylum/server/internal/auth/crypt/pbkdf2"
)
type PasswordHasher interface {
GenerateEncodedHash(password string) (string, error)
}
func NewPasswordHasher(cfg Config) (PasswordHasher, error) {
if cfg.Hash == "argon2" {
return argon2.New(cfg.Argon2), nil
} else if cfg.Hash == "pbkdf2" {
generator, err := pbkdf2.New(cfg.PBKDF2)
if err != nil {
return nil, errors.New("failed to create PBKDF2 hash generator: " + err.Error())
}
return generator, nil
} else {
return nil, errors.New("unrecognized hashing algorithm: " + cfg.Hash)
}
}

View File

@@ -15,6 +15,15 @@ core:
user: # Config for new users
basedir: /home
permission: 0x10 # Invite users
publinks:
password:
# hash is either argon2 or pbkdf2
hash: pbkdf2
pbkdf2:
function: sha-256
iterations: 100000
salt: 32
key: 32
auth:
auto_create:
@@ -25,7 +34,7 @@ auth:
# backend is one of crypt, ldap, or none
backend: crypt
crypt:
# hash is one of argon2, or pbkdf2
# hash is either argon2 or pbkdf2
hash: argon2
argon2:
memory: 18

View File

@@ -1,7 +1,14 @@
package core
import "codeberg.org/shroff/phylum/server/internal/auth/crypt"
type Config struct {
User UserConfig `koanf:"user"`
User UserConfig `koanf:"users"`
Publinks PublinksConfig `koanf:"publinks"`
}
type PublinksConfig struct {
Password crypt.Config `koanf:"password"`
}
type UserConfig struct {

View File

@@ -3,6 +3,7 @@ package core
import (
"errors"
"codeberg.org/shroff/phylum/server/internal/auth/crypt"
"codeberg.org/shroff/phylum/server/internal/db"
"github.com/doug-martin/goqu/v9"
_ "github.com/doug-martin/goqu/v9/dialect/postgres"
@@ -13,6 +14,7 @@ import (
var pg *goqu.Database
var userConfig UserConfig
var publinksPasswordHasher crypt.PasswordHasher
var fsPathRoot pgtype.UUID
func Initialize(db db.Handler, cfg Config) error {
@@ -25,6 +27,11 @@ func Initialize(db db.Handler, cfg Config) error {
fsPathRoot = pgtype.UUID{Bytes: rootID, Valid: true}
}
userConfig = cfg.User
if c, err := crypt.NewPasswordHasher(cfg.Publinks.Password); err != nil {
return err
} else {
publinksPasswordHasher = c
}
return nil
}

View File

@@ -1,9 +1,9 @@
package core
import (
"errors"
"strings"
"codeberg.org/shroff/phylum/server/internal/auth/crypt"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
)
@@ -25,11 +25,11 @@ func (f txFileSystem) CreatePublink(r Resource, id, password string, expires pgt
passwordHash := ""
if password != "" {
hash, err := crypt.Generate(password)
var err error
passwordHash, err = publinksPasswordHasher.GenerateEncodedHash(password)
if err != nil {
return err
return errors.New("failed to hash password: " + err.Error())
}
passwordHash = hash
}
const q = `INSERT INTO publinks(id, root, password_hash, expires, access_limit) VALUES