[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 <build@mattermost.com>
Этот коммит содержится в:
Ben Schumacher
2024-05-06 17:31:16 +02:00
коммит произвёл GitHub
родитель 0a3a55bb80
Коммит 31015a971e
2 изменённых файлов: 53 добавлений и 2 удалений

Просмотреть файл

@@ -76,7 +76,7 @@ func authorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
} }
auditRec.Success() auditRec.Success()
c.LogAudit("") c.LogAudit("success")
w.Write([]byte(model.MapToJSON(map[string]string{"redirect": redirectURL}))) 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 := c.MakeAuditRecord("deauthorizeOAuthApp", audit.Fail)
auditRec.AddMeta("client_id", clientId)
defer c.LogAuditRec(auditRec) defer c.LogAuditRec(auditRec)
err := c.App.DeauthorizeOAuthAppForUser(c.AppContext, c.AppContext.Session().UserId, clientId) 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 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) oauthApp, err := c.App.GetOAuthApp(authRequest.ClientId)
if err != nil { if err != nil {
utils.RenderWebAppError(c.App.Config(), w, r, err, c.App.AsymmetricSigningKey()) 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 // here we should check if the user is logged in
if c.AppContext.Session().UserId == "" { if c.AppContext.Session().UserId == "" {
auditRec.Success()
c.LogAudit("success")
if loginHint == model.UserAuthServiceSaml { if loginHint == model.UserAuthServiceSaml {
http.Redirect(w, r, c.GetSiteURLHeader()+"/login/sso/saml?redirect_to="+url.QueryEscape(r.RequestURI), http.StatusFound) http.Redirect(w, r, c.GetSiteURLHeader()+"/login/sso/saml?redirect_to="+url.QueryEscape(r.RequestURI), http.StatusFound)
} else { } else {
@@ -167,16 +176,21 @@ func authorizeOAuthPage(c *Context, w http.ResponseWriter, r *http.Request) {
// Automatically allow if the app is trusted // Automatically allow if the app is trusted
if oauthApp.IsTrusted || isAuthorized { if oauthApp.IsTrusted || isAuthorized {
redirectURL, err := c.App.AllowOAuthAppAccessToUser(c.AppContext, c.AppContext.Session().UserId, authRequest) redirectURL, err := c.App.AllowOAuthAppAccessToUser(c.AppContext, c.AppContext.Session().UserId, authRequest)
if err != nil { if err != nil {
utils.RenderWebAppError(c.App.Config(), w, r, err, c.App.AsymmetricSigningKey()) utils.RenderWebAppError(c.App.Config(), w, r, err, c.App.AsymmetricSigningKey())
return return
} }
auditRec.Success()
c.LogAudit("success")
http.Redirect(w, r, redirectURL, http.StatusFound) http.Redirect(w, r, redirectURL, http.StatusFound)
return return
} }
auditRec.Success()
c.LogAudit("success")
w.Header().Set("X-Frame-Options", "SAMEORIGIN") w.Header().Set("X-Frame-Options", "SAMEORIGIN")
w.Header().Set("Content-Security-Policy", fmt.Sprintf("frame-ancestors %s", frameAncestors)) w.Header().Set("Content-Security-Policy", fmt.Sprintf("frame-ancestors %s", frameAncestors))
w.Header().Set("Content-Type", "text/html; charset=utf-8") 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 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") oauthError := r.URL.Query().Get("error")
if oauthError == "access_denied" { if oauthError == "access_denied" {
utils.RenderWebError(c.App.Config(), w, r, http.StatusTemporaryRedirect, url.Values{ 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 // Old mobile version
if isMobile && !hasRedirectURL { if isMobile && !hasRedirectURL {
c.App.AttachSessionCookies(c.AppContext, w, r) c.App.AttachSessionCookies(c.AppContext, w, r)
auditRec.Success()
c.LogAudit("success")
return return
} else } else
// New mobile version // New mobile version
@@ -342,6 +364,10 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
model.SessionCookieCsrf: c.AppContext.Session().GetCSRF(), model.SessionCookieCsrf: c.AppContext.Session().GetCSRF(),
}) })
utils.RenderMobileAuthComplete(w, redirectURL) utils.RenderMobileAuthComplete(w, redirectURL)
auditRec.Success()
c.LogAudit("success")
return return
} }
// For web // 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") w.Header().Set("Content-Type", "text/html; charset=utf-8")
http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect) http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect)
} }
@@ -395,6 +424,10 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return 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()) teamId, err := c.App.GetTeamIdFromQuery(c.AppContext, r.URL.Query())
if err != nil { if err != nil {
c.Err = err c.Err = err
@@ -407,6 +440,9 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
auditRec.Success()
c.LogAudit("success")
http.Redirect(w, r, authURL, http.StatusFound) http.Redirect(w, r, authURL, http.StatusFound)
} }
@@ -424,6 +460,10 @@ func mobileLoginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return 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()) teamId, err := c.App.GetTeamIdFromQuery(c.AppContext, r.URL.Query())
if err != nil { if err != nil {
c.Err = err c.Err = err
@@ -436,6 +476,9 @@ func mobileLoginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
auditRec.Success()
c.LogAudit("success")
http.Redirect(w, r, authURL, http.StatusFound) http.Redirect(w, r, authURL, http.StatusFound)
} }
@@ -452,6 +495,10 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return 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()) teamId, err := c.App.GetTeamIdFromQuery(c.AppContext, r.URL.Query())
if err != nil { if err != nil {
c.Err = err c.Err = err
@@ -466,6 +513,9 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
auditRec.Success()
c.LogAudit("success")
http.Redirect(w, r, authURL, http.StatusFound) http.Redirect(w, r, authURL, http.StatusFound)
} }

Просмотреть файл

@@ -32,6 +32,7 @@ func TestOAuthComplete_AccessDenied(t *testing.T) {
Params: &Params{ Params: &Params{
Service: "TestService", Service: "TestService",
}, },
AppContext: request.EmptyContext(th.TestLogger),
} }
responseWriter := httptest.NewRecorder() responseWriter := httptest.NewRecorder()
request, _ := http.NewRequest(http.MethodGet, th.App.GetSiteURL()+"/signup/TestService/complete?error=access_denied", nil) request, _ := http.NewRequest(http.MethodGet, th.App.GetSiteURL()+"/signup/TestService/complete?error=access_denied", nil)