[MM-37984] Allow Desktop App to authenticate via external providers outside of the app on supported servers (#23795)

* WIP

* Add rate limiting for desktop token API

* Missing mocks

* Style fixes

* Update snapshots

* Maybe use an actual redirect link :P

* Refactoring for tests

* Add tests for server

* Fix lint issue

* Fix tests

* Fix lint

* Add front-end screen component

* Component logic

* Style changes

* Quick style fix

* Lint fixes

* Initial PR feedback

* Enable logging into the browser as well when completing the login process

* Refactor to push more logic to the other component

* Remove unnecessary helper code

* Fix i18n

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Devin Binnie
2023-07-12 09:25:05 -04:00
коммит произвёл GitHub
родитель 5e3c03a0a8
Коммит abdf4e58c3
41 изменённых файлов: 1847 добавлений и 24 удалений

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

@@ -10,6 +10,7 @@ import (
"net/url"
"path/filepath"
"strings"
"time"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/i18n"
@@ -343,6 +344,29 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
} else { // For web
c.App.AttachSessionCookies(c.AppContext, w, r)
}
desktopToken := ""
if val, ok := props["desktop_token"]; ok {
desktopToken = val
}
if desktopToken != "" {
desktopTokenErr := c.App.AuthenticateDesktopToken(desktopToken, time.Now().Add(-model.DesktopTokenTTL).Unix(), user)
if desktopTokenErr != nil {
desktopTokenErr.Translate(c.AppContext.T)
c.LogErrorByCode(desktopTokenErr)
renderError(desktopTokenErr)
return
}
queryString := map[string]string{
"desktopAuthComplete": "true",
}
if val, ok := props["redirect_to"]; ok {
queryString["redirect_to"] = val
}
redirectURL = utils.AppendQueryParamsToURL(c.GetSiteURLHeader()+"/login/desktop", queryString)
}
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
@@ -357,6 +381,15 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
loginHint := r.URL.Query().Get("login_hint")
redirectURL := r.URL.Query().Get("redirect_to")
desktopToken := r.URL.Query().Get("desktop_token")
if desktopToken != "" {
desktopTokenErr := c.App.CreateDesktopToken(desktopToken, time.Now().Unix())
if desktopTokenErr != nil {
c.Err = desktopTokenErr
return
}
}
if redirectURL != "" && !utils.IsValidWebAuthRedirectURL(c.App.Config(), redirectURL) {
c.Err = model.NewAppError("loginWithOAuth", "api.invalid_redirect_url", nil, "", http.StatusBadRequest)
@@ -369,7 +402,7 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
authURL, err := c.App.GetOAuthLoginEndpoint(w, r, c.Params.Service, teamId, model.OAuthActionLogin, redirectURL, loginHint, false)
authURL, err := c.App.GetOAuthLoginEndpoint(w, r, c.Params.Service, teamId, model.OAuthActionLogin, redirectURL, loginHint, false, desktopToken)
if err != nil {
c.Err = err
return
@@ -398,7 +431,7 @@ func mobileLoginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
authURL, err := c.App.GetOAuthLoginEndpoint(w, r, c.Params.Service, teamId, model.OAuthActionMobile, redirectURL, "", true)
authURL, err := c.App.GetOAuthLoginEndpoint(w, r, c.Params.Service, teamId, model.OAuthActionMobile, redirectURL, "", true, "")
if err != nil {
c.Err = err
return
@@ -426,7 +459,17 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
authURL, err := c.App.GetOAuthSignupEndpoint(w, r, c.Params.Service, teamId)
desktopToken := r.URL.Query().Get("desktop_token")
if desktopToken != "" {
desktopTokenErr := c.App.CreateDesktopToken(desktopToken, time.Now().Unix())
if desktopTokenErr != nil {
c.Err = desktopTokenErr
return
}
}
authURL, err := c.App.GetOAuthSignupEndpoint(w, r, c.Params.Service, teamId, desktopToken)
if err != nil {
c.Err = err
return

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

@@ -9,6 +9,7 @@ import (
"net/http"
"strconv"
"strings"
"time"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
@@ -59,6 +60,16 @@ func loginWithSaml(c *Context, w http.ResponseWriter, r *http.Request) {
relayProps["redirect_to"] = redirectURL
}
desktopToken := r.URL.Query().Get("desktop_token")
if desktopToken != "" {
desktopTokenErr := c.App.CreateDesktopToken(desktopToken, time.Now().Unix())
if desktopTokenErr != nil {
c.Err = err
return
}
relayProps["desktop_token"] = desktopToken
}
relayProps[model.UserAuthServiceIsMobile] = strconv.FormatBool(isMobile)
if len(relayProps) > 0 {
@@ -185,6 +196,26 @@ func completeSaml(c *Context, w http.ResponseWriter, r *http.Request) {
c.App.AttachSessionCookies(c.AppContext, w, r)
desktopToken := relayProps["desktop_token"]
if desktopToken != "" {
desktopTokenErr := c.App.AuthenticateDesktopToken(desktopToken, time.Now().Add(-model.DesktopTokenTTL).Unix(), user)
if desktopTokenErr != nil {
handleError(desktopTokenErr)
return
}
queryString := map[string]string{
"desktopAuthComplete": "true",
}
if val, ok := relayProps["redirect_to"]; ok {
queryString["redirect_to"] = val
}
redirectURL = utils.AppendQueryParamsToURL(c.GetSiteURLHeader()+"/login/desktop", queryString)
http.Redirect(w, r, redirectURL, http.StatusFound)
return
}
if hasRedirectURL {
if isMobile {
// Mobile clients with redirect url support