From 8d697bcc94a77b04cabaa90c4d7bb0b29bd17ebc Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Mon, 21 Oct 2024 20:40:44 +0200 Subject: [PATCH] WebClient: enforce 2fa and password requirements also with OIDC password and 2fa can be used with other protocols Signed-off-by: Nicola Murino --- internal/httpd/oidc.go | 44 ++++++++++++++++++++---------- static/locales/en/translation.json | 2 +- static/locales/it/translation.json | 2 +- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/internal/httpd/oidc.go b/internal/httpd/oidc.go index 2ab22137..4d19949c 100644 --- a/internal/httpd/oidc.go +++ b/internal/httpd/oidc.go @@ -212,21 +212,24 @@ func newOIDCPendingAuth(audience tokenAudience) oidcPendingAuth { } type oidcToken struct { - AccessToken string `json:"access_token"` - TokenType string `json:"token_type,omitempty"` - RefreshToken string `json:"refresh_token,omitempty"` - ExpiresAt int64 `json:"expires_at,omitempty"` - SessionID string `json:"session_id"` - IDToken string `json:"id_token"` - Nonce string `json:"nonce"` - Username string `json:"username"` - Permissions []string `json:"permissions"` - HideUserPageSections int `json:"hide_user_page_sections,omitempty"` - TokenRole string `json:"token_role,omitempty"` // SFTPGo role name - Role any `json:"role"` // oidc user role: SFTPGo user or admin - CustomFields *map[string]any `json:"custom_fields,omitempty"` - Cookie string `json:"cookie"` - UsedAt int64 `json:"used_at"` + AccessToken string `json:"access_token"` + TokenType string `json:"token_type,omitempty"` + RefreshToken string `json:"refresh_token,omitempty"` + ExpiresAt int64 `json:"expires_at,omitempty"` + SessionID string `json:"session_id"` + IDToken string `json:"id_token"` + Nonce string `json:"nonce"` + Username string `json:"username"` + Permissions []string `json:"permissions"` + HideUserPageSections int `json:"hide_user_page_sections,omitempty"` + MustSetTwoFactorAuth bool `json:"must_set_2fa,omitempty"` + MustChangePassword bool `json:"must_change_password,omitempty"` + RequiredTwoFactorProtocols []string `json:"required_two_factor_protocols,omitempty"` + TokenRole string `json:"token_role,omitempty"` // SFTPGo role name + Role any `json:"role"` // oidc user role: SFTPGo user or admin + CustomFields *map[string]any `json:"custom_fields,omitempty"` + Cookie string `json:"cookie"` + UsedAt int64 `json:"used_at"` } func (t *oidcToken) parseClaims(claims map[string]any, usernameField, roleField string, customFields []string, @@ -399,6 +402,9 @@ func (t *oidcToken) refreshUser(r *http.Request) error { } t.Permissions = user.Filters.WebClient t.TokenRole = user.Role + t.MustSetTwoFactorAuth = user.MustSetSecondFactor() + t.MustChangePassword = user.MustChangePassword() + t.RequiredTwoFactorProtocols = user.Filters.TwoFactorAuthProtocols return nil } @@ -470,6 +476,9 @@ func (t *oidcToken) getUser(r *http.Request) error { dataprovider.UpdateLastLogin(user) t.Permissions = user.Filters.WebClient t.TokenRole = user.Role + t.MustSetTwoFactorAuth = user.MustSetSecondFactor() + t.MustChangePassword = user.MustChangePassword() + t.RequiredTwoFactorProtocols = user.Filters.TwoFactorAuthProtocols return nil } @@ -550,6 +559,11 @@ func (s *httpdServer) oidcTokenAuthenticator(audience tokenAudience) func(next h Role: token.TokenRole, HideUserPageSections: token.HideUserPageSections, } + if audience == tokenAudienceWebClient { + jwtTokenClaims.MustSetTwoFactorAuth = token.MustSetTwoFactorAuth + jwtTokenClaims.MustChangePassword = token.MustChangePassword + jwtTokenClaims.RequiredTwoFactorProtocols = token.RequiredTwoFactorProtocols + } _, tokenString, err := jwtTokenClaims.createToken(s.tokenAuth, audience, util.GetIPFromRemoteAddress(r.RemoteAddr)) if err != nil { setFlashMessage(w, r, newFlashMessage("Unable to create cookie", util.I18nError500Message)) diff --git a/static/locales/en/translation.json b/static/locales/en/translation.json index a263165c..89f302d3 100644 --- a/static/locales/en/translation.json +++ b/static/locales/en/translation.json @@ -427,7 +427,7 @@ "save_err": "Failed to save two-factor authentication configuration", "auth_code_required": "The authentication code is required", "no_protocol": "Please select at least a protocol", - "required_protocols": "Unable to disable two-factor authentication. The security policy configured for your account requires two-factor authentication for the following protocols: {{val}}", + "required_protocols": "The security policy configured for your account requires two-factor authentication for the following protocols: {{val}}", "recovery_codes_generate": "Generate new recovery codes", "recovery_codes_view": "View recovery codes" }, diff --git a/static/locales/it/translation.json b/static/locales/it/translation.json index 07d78b20..004ac04c 100644 --- a/static/locales/it/translation.json +++ b/static/locales/it/translation.json @@ -427,7 +427,7 @@ "save_err": "Impossibile salvare la configurazione dell'autenticazione a due fattori", "auth_code_required": "Il codice di autenticazione รจ obbligatorio", "no_protocol": "Seleziona almeno un protocollo", - "required_protocols": "Impossibile disabilitare l'autenticazione a due fattori. La politica di sicurezza configurata per il tuo account richiede l'autenticazione a due fattori per i seguenti protocolli: {{val}}", + "required_protocols": "La politica di sicurezza configurata per il tuo account richiede l'autenticazione a due fattori per i seguenti protocolli: {{val}}", "recovery_codes_generate": "Genera nuovi codici di ripristino", "recovery_codes_view": "Visualizza codici di ripristino" },