diff options
Diffstat (limited to 'auth')
| -rw-r--r-- | auth/auth.go | 33 | ||||
| -rw-r--r-- | auth/session.go | 112 | 
2 files changed, 145 insertions, 0 deletions
| diff --git a/auth/auth.go b/auth/auth.go new file mode 100644 index 0000000..ac908ab --- /dev/null +++ b/auth/auth.go @@ -0,0 +1,33 @@ +package auth + +import ( +	"golang.org/x/crypto/argon2" +	"crypto/rand" +	"sanine.net/git/phlox/config" +) + + +func GenerateSalt() ([]byte, error) { +	salt := make([]byte, 10) +	_, err := rand.Read(salt) +	return salt, err +} + + +func HashPassword(password string, salt []byte) []byte { +	return argon2.IDKey( +		[]byte(password), salt, +		1, 64*1024, 4, 32, +	) +} + + +func AuthenticateUser(user config.User, password string) bool { +	hash := HashPassword(password, user.Salt) +	for i, v := range user.PasswordHash { +		if v != hash[i] { +			return false; +		} +	} +	return true +} diff --git a/auth/session.go b/auth/session.go new file mode 100644 index 0000000..1524e6b --- /dev/null +++ b/auth/session.go @@ -0,0 +1,112 @@ +package auth + +import ( +	"fmt" +	"time" +	"sync" +	"crypto/rand" +	"encoding/base64" +) + + +type Session struct { +	Created time.Time +	Modified time.Time +} + + +type Sessions struct { +	s map[string]Session +	lock sync.Mutex +} + + +func NewSessionContainer() *Sessions { +	return &Sessions{ +		s: make(map[string]Session), +	} +} + + +func createSessionId() (string, error) { +	bytes := make([]byte, 32) +	_, err := rand.Read(bytes) +	if err != nil { +		return "", err +	} + +	return base64.StdEncoding.EncodeToString(bytes), nil +} + + +func (s *Sessions) NewSession() (string, error) { +	s.lock.Lock() +	defer s.lock.Unlock() + +	id, err := createSessionId() +	if err != nil { +		return "", err +	} + +	session := Session{ +		Created: time.Now(), +		Modified: time.Now(), +	} + +	s.s[id] = session +	return id, nil +} + + +func (s *Sessions) IsSessionValid(id string) bool { +	s.lock.Lock() +	defer s.lock.Unlock() + +	_, ok := s.s[id] +	return ok +} + + +func (s *Sessions) GetSession(id string) (Session, error) { +	s.lock.Lock() +	defer s.lock.Unlock() + +	session, ok := s.s[id] +	if !ok { +		return Session{}, fmt.Errorf("invalid session id: %v", id) +	} +	return session, nil +} + + +func (s *Sessions) TouchSession(id string) { +	s.lock.Lock() +	defer s.lock.Unlock() + +	session := s.s[id] +	session.Modified = time.Now() +	s.s[id] = session +} + + +func (s *Sessions) DeleteSession(id string) { +	s.lock.Lock() +	defer s.lock.Unlock() + +	delete(s.s, id) +} + + +func (s *Sessions) CleanSessions(maxIdle time.Duration) { +	s.lock.Lock() +	defer s.lock.Unlock() + +	expire := time.Now().Add(-maxIdle) +	for id, session := range s.s { +		if session.Modified.Before(expire) { +			// last modified before the expiration time +			// so this session is expired +			delete(s.s, id) +		} +	} +} | 
