Change session from method tracking

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-12-19 15:43:16 +01:00
parent 811bebca48
commit a4964e817c
3 changed files with 57 additions and 30 deletions

View File

@@ -0,0 +1,24 @@
CREATE TYPE session_auth_method AS ENUM (
'PASSWORD',
'SAML'
);
ALTER TABLE sessions ADD COLUMN auth_method session_auth_method;
ALTER TABLE sessions ADD COLUMN authenticated_at TIMESTAMP;
-- Expire all existing sessions as they are not backward compatible
UPDATE sessions SET
expire_reason = 'revoked',
expired_at = NOW(),
updated_at = NOW(),
auth_method = 'PASSWORD',
authenticated_at = created_at
WHERE expire_reason IS NULL;
UPDATE sessions SET
auth_method = 'PASSWORD',
authenticated_at = created_at
WHERE auth_method IS NULL;
ALTER TABLE sessions ALTER COLUMN auth_method SET NOT NULL;
ALTER TABLE sessions ALTER COLUMN authenticated_at SET NOT NULL;

View File

@@ -35,6 +35,8 @@ type (
TenantID *gid.TenantID `db:"tenant_id"`
ParentSessionID *gid.GID `db:"parent_session_id"`
Data SessionData `db:"data"`
AuthMethod AuthMethod `db:"auth_method"`
AuthenticatedAt time.Time `db:"authenticated_at"`
UserAgent string `db:"user_agent"`
IPAddress net.IP `db:"ip_address"`
ExpireReason *ExpireReason `db:"expire_reason"`
@@ -45,25 +47,26 @@ type (
Sessions []*Session
SessionData struct {
PasswordAuthenticated bool `json:"password_authenticated"`
SAMLAuthenticatedOrgs map[string]SAMLAuthInfo `json:"saml_authenticated_orgs,omitempty"`
}
SessionData struct{}
SAMLAuthInfo struct {
AuthenticatedAt time.Time `json:"authenticated_at"`
SAMLConfigID gid.GID `json:"saml_config_id"`
SAMLSubject string `json:"saml_subject"`
}
AuthMethod string
)
func NewRootSession(userID gid.GID, duration time.Duration) *Session {
const (
AuthMethodPassword AuthMethod = "PASSWORD"
AuthMethodSAML AuthMethod = "SAML"
)
func NewRootSession(userID gid.GID, method AuthMethod, duration time.Duration) *Session {
now := time.Now()
return &Session{
ID: gid.New(gid.NilTenant, SessionEntityType),
UserID: userID,
ExpiredAt: time.Now().Add(duration),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
ID: gid.New(gid.NilTenant, SessionEntityType),
UserID: userID,
ExpiredAt: now.Add(duration),
AuthMethod: method,
AuthenticatedAt: now,
CreatedAt: now,
UpdatedAt: now,
}
}
@@ -100,6 +103,8 @@ SELECT
tenant_id,
data,
parent_session_id,
auth_method,
authenticated_at,
expire_reason,
user_agent,
ip_address,
@@ -139,13 +144,15 @@ func (s *Session) Insert(
) error {
q := `
INSERT INTO
sessions (id, user_id, tenant_id, data, parent_session_id, expire_reason, user_agent, ip_address, expired_at, created_at, updated_at)
sessions (id, user_id, tenant_id, data, parent_session_id, auth_method, authenticated_at, expire_reason, user_agent, ip_address, expired_at, created_at, updated_at)
VALUES (
@session_id,
@user_id,
@tenant_id,
@data,
@parent_session_id,
@auth_method,
@authenticated_at,
@expire_reason,
@user_agent,
@ip_address,
@@ -161,6 +168,8 @@ VALUES (
"tenant_id": s.TenantID,
"data": s.Data,
"parent_session_id": s.ParentSessionID,
"auth_method": s.AuthMethod,
"authenticated_at": s.AuthenticatedAt,
"expire_reason": s.ExpireReason,
"user_agent": s.UserAgent,
"ip_address": s.IPAddress,
@@ -220,6 +229,8 @@ SELECT
tenant_id,
data,
parent_session_id,
auth_method,
authenticated_at,
expire_reason,
user_agent,
ip_address,
@@ -309,6 +320,8 @@ SELECT
tenant_id,
data,
parent_session_id,
auth_method,
authenticated_at,
expire_reason,
user_agent,
ip_address,

View File

@@ -172,7 +172,7 @@ func (s *AuthService) CreateIdentityFromInvitation(
return fmt.Errorf("cannot insert user: %w", err)
}
session = coredata.NewRootSession(user.ID, s.sessionDuration)
session = coredata.NewRootSession(user.ID, coredata.AuthMethodPassword, s.sessionDuration)
err = session.Insert(ctx, tx)
if err != nil {
return fmt.Errorf("cannot insert session: %w", err)
@@ -330,17 +330,7 @@ func (s AuthService) CreateIdentityWithPassword(
UpdatedAt: now,
}
session = &coredata.Session{
ID: gid.New(gid.NilTenant, coredata.SessionEntityType),
UserID: user.ID,
Data: coredata.SessionData{
PasswordAuthenticated: true,
SAMLAuthenticatedOrgs: make(map[string]coredata.SAMLAuthInfo),
},
ExpiredAt: now.Add(24 * time.Hour * 7), // 7 days, TODO must to be hardcoded here
CreatedAt: now,
UpdatedAt: now,
}
session = coredata.NewRootSession(user.ID, coredata.AuthMethodPassword, 24*time.Hour*7)
)
confirmationToken, err := statelesstoken.NewToken(
@@ -416,7 +406,7 @@ func (s AuthService) OpenSessionWithSAML(ctx context.Context, userID gid.GID, or
err := s.pg.WithTx(
ctx,
func(conn pg.Conn) (err error) {
session = coredata.NewRootSession(userID, s.sessionDuration)
session = coredata.NewRootSession(userID, coredata.AuthMethodSAML, s.sessionDuration)
err = session.Insert(ctx, conn)
if err != nil {
return fmt.Errorf("cannot insert session: %w", err)
@@ -474,7 +464,7 @@ func (s AuthService) OpenSessionWithPassword(ctx context.Context, email mail.Add
return NewInvalidCredentialsError("invalid email or password")
}
session = coredata.NewRootSession(user.ID, s.sessionDuration)
session = coredata.NewRootSession(user.ID, coredata.AuthMethodPassword, s.sessionDuration)
err = session.Insert(ctx, conn)
if err != nil {
return fmt.Errorf("cannot insert session: %w", err)