mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2025-10-29 09:15:33 +00:00
SECURITY: store hashed session tokens
This commit is contained in:
@@ -135,13 +135,13 @@ func (p *LoginPage) POST(engine *templating.Engine, app core.App) HandleFunc {
|
|||||||
return Unauthorized(engine, e, fmt.Errorf("Ihr Benutzerkonto ist deaktiviert. Bitte kontaktieren Sie den Administrator."), data)
|
return Unauthorized(engine, e, fmt.Errorf("Ihr Benutzerkonto ist deaktiviert. Bitte kontaktieren Sie den Administrator."), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
duration := time.Minute * 60
|
duration := time.Hour * 2
|
||||||
if formdata.Persistent == "on" {
|
if formdata.Persistent == "on" {
|
||||||
duration = time.Hour * 24 * 90
|
duration = time.Hour * 24 * 90
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := dbmodels.CreateSessionToken(app, record.Id, e.RealIP(), e.Request.UserAgent(), formdata.Persistent == "on", duration)
|
token, err := dbmodels.CreateSessionToken(app, record.Id, e.RealIP(), e.Request.UserAgent(), formdata.Persistent == "on", duration)
|
||||||
if err != nil {
|
if err != nil || token == nil || token.SessionTokenClear == "" {
|
||||||
return engine.Response500(e, err, data)
|
return engine.Response500(e, err, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ func (p *LoginPage) POST(engine *templating.Engine, app core.App) HandleFunc {
|
|||||||
Name: dbmodels.SESSION_COOKIE_NAME,
|
Name: dbmodels.SESSION_COOKIE_NAME,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
MaxAge: int(duration.Seconds()),
|
MaxAge: int(duration.Seconds()),
|
||||||
Value: token.Token(),
|
Value: token.SessionTokenClear,
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: true,
|
||||||
@@ -159,7 +159,7 @@ func (p *LoginPage) POST(engine *templating.Engine, app core.App) HandleFunc {
|
|||||||
e.SetCookie(&http.Cookie{
|
e.SetCookie(&http.Cookie{
|
||||||
Name: dbmodels.SESSION_COOKIE_NAME,
|
Name: dbmodels.SESSION_COOKIE_NAME,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Value: token.Token(),
|
Value: token.SessionTokenClear,
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: true,
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package dbmodels
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -14,6 +16,13 @@ const (
|
|||||||
secureTokenByteLength = 64
|
secureTokenByteLength = 64
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func HashStringSHA256(data string) string {
|
||||||
|
hasher := sha256.New()
|
||||||
|
hasher.Write([]byte(data))
|
||||||
|
hashedBytes := hasher.Sum(nil)
|
||||||
|
return hex.EncodeToString(hashedBytes)
|
||||||
|
}
|
||||||
|
|
||||||
func generateSecureRandomToken(length int) (string, error) {
|
func generateSecureRandomToken(length int) (string, error) {
|
||||||
if length <= 0 {
|
if length <= 0 {
|
||||||
length = secureTokenByteLength
|
length = secureTokenByteLength
|
||||||
@@ -55,7 +64,8 @@ func CreateSessionToken(
|
|||||||
session := NewSession(record)
|
session := NewSession(record)
|
||||||
|
|
||||||
// Set required fields with hashed tokens
|
// Set required fields with hashed tokens
|
||||||
session.SetToken(sessionTokenClear)
|
session.SessionTokenClear = sessionTokenClear
|
||||||
|
session.SetToken(HashStringSHA256(sessionTokenClear))
|
||||||
session.SetCSRF(csrfTokenClear)
|
session.SetCSRF(csrfTokenClear)
|
||||||
session.SetUser(userID)
|
session.SetUser(userID)
|
||||||
|
|
||||||
@@ -67,7 +77,7 @@ func CreateSessionToken(
|
|||||||
session.SetLastAccess(types.NowDateTime())
|
session.SetLastAccess(types.NowDateTime())
|
||||||
session.SetUserAgent(userAgent)
|
session.SetUserAgent(userAgent)
|
||||||
session.SetIP(ipAddress)
|
session.SetIP(ipAddress)
|
||||||
session.SetStatus(TOKEN_STATUS_VALUES[0]) // Active
|
session.SetStatus(TOKEN_STATUS_VALUES[0])
|
||||||
|
|
||||||
if errSave := app.Save(session); errSave != nil {
|
if errSave := app.Save(session); errSave != nil {
|
||||||
app.Logger().Error("Failed to save session token record", "error", errSave, "userID", userID)
|
app.Logger().Error("Failed to save session token record", "error", errSave, "userID", userID)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ func (s *FixedSession) IsExpired() bool {
|
|||||||
var _ core.RecordProxy = (*Place)(nil)
|
var _ core.RecordProxy = (*Place)(nil)
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
|
SessionTokenClear string `json:"-"`
|
||||||
core.BaseRecordProxy
|
core.BaseRecordProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ func Authenticated(app core.App) func(*core.RequestEvent) error {
|
|||||||
|
|
||||||
user, session, loaded := SESSION_CACHE.Get(cookie.Value)
|
user, session, loaded := SESSION_CACHE.Get(cookie.Value)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
record, err := app.FindFirstRecordByData(dbmodels.SESSIONS_TABLE, dbmodels.SESSIONS_TOKEN_FIELD, cookie.Value)
|
hashedsession := dbmodels.HashStringSHA256(cookie.Value)
|
||||||
|
record, err := app.FindFirstRecordByData(dbmodels.SESSIONS_TABLE, dbmodels.SESSIONS_TOKEN_FIELD, hashedsession)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.SetCookie(deact_cookie)
|
e.SetCookie(deact_cookie)
|
||||||
e.Response.Header().Set("Clear-Site-Data", "\"cookies\"")
|
e.Response.Header().Set("Clear-Site-Data", "\"cookies\"")
|
||||||
|
|||||||
Reference in New Issue
Block a user