From 31015a971e52f93616240cebb5ec54ac54426228 Mon Sep 17 00:00:00 2001 From: Ben Schumacher Date: Mon, 6 May 2024 17:31:16 +0200 Subject: [PATCH] [MM-56340] Add audit events for OAuth logins (#25859) * Add audit events for OAuth logins * Fix test * Fix auth record --------- Co-authored-by: Mattermost Build --- server/channels/web/oauth.go | 54 +++++++++++++++++++++++++++++-- server/channels/web/oauth_test.go | 1 + 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/server/channels/web/oauth.go b/server/channels/web/oauth.go index d19058d959..04b701c619 100644 --- a/server/channels/web/oauth.go +++ b/server/channels/web/oauth.go @@ -76,7 +76,7 @@ func authorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec.Success() - c.LogAudit("") + c.LogAudit("success") w.Write([]byte(model.MapToJSON(map[string]string{"redirect": redirectURL}))) } @@ -91,6 +91,7 @@ func deauthorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("deauthorizeOAuthApp", audit.Fail) + auditRec.AddMeta("client_id", clientId) defer c.LogAuditRec(auditRec) err := c.App.DeauthorizeOAuthAppForUser(c.AppContext, c.AppContext.Session().UserId, clientId) @@ -131,6 +132,11 @@ func authorizeOAuthPage(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("authorizeOAuthPage", audit.Fail) + auditRec.AddMeta("client_id", authRequest.ClientId) + auditRec.AddMeta("scope", authRequest.Scope) + defer c.LogAuditRec(auditRec) + oauthApp, err := c.App.GetOAuthApp(authRequest.ClientId) if err != nil { utils.RenderWebAppError(c.App.Config(), w, r, err, c.App.AsymmetricSigningKey()) @@ -139,6 +145,9 @@ func authorizeOAuthPage(c *Context, w http.ResponseWriter, r *http.Request) { // here we should check if the user is logged in if c.AppContext.Session().UserId == "" { + auditRec.Success() + c.LogAudit("success") + if loginHint == model.UserAuthServiceSaml { http.Redirect(w, r, c.GetSiteURLHeader()+"/login/sso/saml?redirect_to="+url.QueryEscape(r.RequestURI), http.StatusFound) } else { @@ -167,16 +176,21 @@ func authorizeOAuthPage(c *Context, w http.ResponseWriter, r *http.Request) { // Automatically allow if the app is trusted if oauthApp.IsTrusted || isAuthorized { redirectURL, err := c.App.AllowOAuthAppAccessToUser(c.AppContext, c.AppContext.Session().UserId, authRequest) - if err != nil { utils.RenderWebAppError(c.App.Config(), w, r, err, c.App.AsymmetricSigningKey()) return } + auditRec.Success() + c.LogAudit("success") + http.Redirect(w, r, redirectURL, http.StatusFound) return } + auditRec.Success() + c.LogAudit("success") + w.Header().Set("X-Frame-Options", "SAMEORIGIN") w.Header().Set("Content-Security-Policy", fmt.Sprintf("frame-ancestors %s", frameAncestors)) w.Header().Set("Content-Type", "text/html; charset=utf-8") @@ -255,6 +269,10 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) { service := c.Params.Service + auditRec := c.MakeAuditRecord("completeOAuth", audit.Fail) + defer c.LogAuditRec(auditRec) + audit.AddEventParameter(auditRec, "service", service) + oauthError := r.URL.Query().Get("error") if oauthError == "access_denied" { utils.RenderWebError(c.App.Config(), w, r, http.StatusTemporaryRedirect, url.Values{ @@ -333,6 +351,10 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) { // Old mobile version if isMobile && !hasRedirectURL { c.App.AttachSessionCookies(c.AppContext, w, r) + + auditRec.Success() + c.LogAudit("success") + return } else // New mobile version @@ -342,6 +364,10 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) { model.SessionCookieCsrf: c.AppContext.Session().GetCSRF(), }) utils.RenderMobileAuthComplete(w, redirectURL) + + auditRec.Success() + c.LogAudit("success") + return } // For web @@ -376,6 +402,9 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) { } } + auditRec.Success() + c.LogAudit("success") + w.Header().Set("Content-Type", "text/html; charset=utf-8") http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect) } @@ -395,6 +424,10 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("loginWithOAuth", audit.Fail) + auditRec.AddMeta("service", c.Params.Service) + defer c.LogAuditRec(auditRec) + teamId, err := c.App.GetTeamIdFromQuery(c.AppContext, r.URL.Query()) if err != nil { c.Err = err @@ -407,6 +440,9 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec.Success() + c.LogAudit("success") + http.Redirect(w, r, authURL, http.StatusFound) } @@ -424,6 +460,10 @@ func mobileLoginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("mobileLoginWithOAuth", audit.Fail) + auditRec.AddMeta("service", c.Params.Service) + defer c.LogAuditRec(auditRec) + teamId, err := c.App.GetTeamIdFromQuery(c.AppContext, r.URL.Query()) if err != nil { c.Err = err @@ -436,6 +476,9 @@ func mobileLoginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec.Success() + c.LogAudit("success") + http.Redirect(w, r, authURL, http.StatusFound) } @@ -452,6 +495,10 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("signupWithOAuth", audit.Fail) + auditRec.AddMeta("service", c.Params.Service) + defer c.LogAuditRec(auditRec) + teamId, err := c.App.GetTeamIdFromQuery(c.AppContext, r.URL.Query()) if err != nil { c.Err = err @@ -466,6 +513,9 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec.Success() + c.LogAudit("success") + http.Redirect(w, r, authURL, http.StatusFound) } diff --git a/server/channels/web/oauth_test.go b/server/channels/web/oauth_test.go index d9d63ee9d9..2e833742c0 100644 --- a/server/channels/web/oauth_test.go +++ b/server/channels/web/oauth_test.go @@ -32,6 +32,7 @@ func TestOAuthComplete_AccessDenied(t *testing.T) { Params: &Params{ Service: "TestService", }, + AppContext: request.EmptyContext(th.TestLogger), } responseWriter := httptest.NewRecorder() request, _ := http.NewRequest(http.MethodGet, th.App.GetSiteURL()+"/signup/TestService/complete?error=access_denied", nil)