Add user session management and auditing

This commit is contained in:
Eric Lesiuta committed 2026-03-20 21:26:30 -04:00
1 parent 455dd20365
commit 0b354c8048
25 files changed
+1299 -11

No files matched your search

+48 -1
View File
@@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"html/template"
"net"
"net/http"
"net/url"
"strings"
@@ -126,6 +127,24 @@ func autoSignIn(ctx *context.Context) (bool, error) {
return false, fmt.Errorf("unable to updateSession: %w", err)
}
// Create tracked user session record for remember-me login
ip := ctx.RemoteAddr()
if host, _, err := net.SplitHostPort(ip); err == nil {
ip = host
}
if err := auth.CreateUserSession(ctx, &auth.UserSession{
ID: ctx.Session.ID(),
UserID: u.ID,
LoginIP: ip,
LastIP: ip,
UserAgent: ctx.Req.UserAgent(),
LoginMethod: "remember_me",
AuthTokenID: nt.ID,
LastAccessUnix: timeutil.TimeStampNow(),
}); err != nil {
log.Error("Failed to create user session record: %v", err)
}
if err := resetLocale(ctx, u); err != nil {
return false, err
}
@@ -326,6 +345,7 @@ func SignInPost(ctx *context.Context) {
// User will need to use 2FA TOTP or WebAuthn, save data
"twofaUid": u.ID,
"twofaRemember": form.Remember,
"_loginMethod": "password",
}
if hasTOTPtwofa {
// User will need to use WebAuthn, save data
@@ -356,13 +376,14 @@ func handleSignIn(ctx *context.Context, u *user_model.User, remember bool) {
}
func handleSignInFull(ctx *context.Context, u *user_model.User, remember bool) {
var authTokenID string
if remember {
nt, token, err := auth_service.CreateAuthTokenForUserID(ctx, u.ID)
if err != nil {
ctx.ServerError("CreateAuthTokenForUserID", err)
return
}
authTokenID = nt.ID
ctx.SetSiteCookie(setting.CookieRememberName, nt.ID+":"+token, setting.LogInRememberDays*timeutil.Day)
}
@@ -391,6 +412,29 @@ func handleSignInFull(ctx *context.Context, u *user_model.User, remember bool) {
return
}
// Create tracked user session record
loginMethod := "password"
if method, ok := ctx.Session.Get("_loginMethod").(string); ok && method != "" {
loginMethod = method
}
_ = ctx.Session.Delete("_loginMethod")
ip := ctx.RemoteAddr()
if host, _, err := net.SplitHostPort(ip); err == nil {
ip = host
}
if err := auth.CreateUserSession(ctx, &auth.UserSession{
ID: ctx.Session.ID(),
UserID: u.ID,
LoginIP: ip,
LastIP: ip,
UserAgent: ctx.Req.UserAgent(),
LoginMethod: loginMethod,
AuthTokenID: authTokenID,
LastAccessUnix: timeutil.TimeStampNow(),
}); err != nil {
log.Error("Failed to create user session record: %v", err)
}
// Language setting of the user overwrites the one previously set
// If the user does not have a locale set, we save the current one.
if u.Language == "" {
@@ -436,6 +480,9 @@ func extractUserNameFromOAuth2(gothUser *goth.User) (string, error) {
// HandleSignOut resets the session and sets the cookies
func HandleSignOut(ctx *context.Context) {
if err := auth.InvalidateUserSession(ctx, ctx.Session.ID()); err != nil {
log.Error("Failed to invalidate user session: %v", err)
}
_ = ctx.Session.Flush()
_ = ctx.Session.Destroy(ctx.Resp, ctx.Req)
ctx.DeleteSiteCookie(setting.CookieRememberName)
+20
View File
@@ -9,6 +9,7 @@ import (
"fmt"
"html"
"io"
"net"
"net/http"
"net/url"
"sort"
@@ -23,6 +24,7 @@ import (
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/session"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
source_service "code.gitea.io/gitea/services/auth/source"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/context"
@@ -391,6 +393,23 @@ func handleOAuth2SignIn(ctx *context.Context, authSource *auth.Source, u *user_m
return
}
// Create tracked user session record for OAuth2 login
ip := ctx.RemoteAddr()
if host, _, err := net.SplitHostPort(ip); err == nil {
ip = host
}
if err := auth.CreateUserSession(ctx, &auth.UserSession{
ID: ctx.Session.ID(),
UserID: u.ID,
LoginIP: ip,
LastIP: ip,
UserAgent: ctx.Req.UserAgent(),
LoginMethod: "oauth2:" + authSource.Name,
LastAccessUnix: timeutil.TimeStampNow(),
}); err != nil {
log.Error("Failed to create user session record: %v", err)
}
if err := resetLocale(ctx, u); err != nil {
ctx.ServerError("resetLocale", err)
return
@@ -411,6 +430,7 @@ func handleOAuth2SignIn(ctx *context.Context, authSource *auth.Source, u *user_m
// User needs to use 2FA, save data and redirect to 2FA page.
"twofaUid": u.ID,
"twofaRemember": false,
"_loginMethod": "oauth2:" + authSource.Name,
}); err != nil {
ctx.ServerError("updateSession", err)
return