[MM-25780] Fix incorrect session length when logging in through mobile using SSO (#14874)

* Pass device ID

* dont use device id as way of detecting

* fix spelling mistake

* update layers

* fix test

* fix linting

* save schema

* put columns in correct place

* fix linting

* update

* upgrade go change

* use props

* fix stuff

* update session tests

* address PR comments

* address PR comments
Этот коммит содержится в:
Hossein Ahmadian-Yazdi
2020-06-30 10:34:05 -04:00
коммит произвёл GitHub
родитель df943fbf91
Коммит 4c50c7c59b
12 изменённых файлов: 119 добавлений и 19 удалений

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

@@ -457,7 +457,7 @@ type AppIface interface {
DoEmojisPermissionsMigration()
DoGuestRolesCreationMigration()
DoLocalRequest(rawURL string, body []byte) (*http.Response, *model.AppError)
DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, deviceId string) *model.AppError
DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, deviceId string, isMobile, isOAuth, isSaml bool) *model.AppError
DoPostAction(postId, actionId, userId, selectedOption string) (string, *model.AppError)
DoPostActionWithCookie(postId, actionId, userId, selectedOption string, cookie *model.PostActionCookie) (string, *model.AppError)
DoUploadFile(now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, *model.AppError)
@@ -579,7 +579,7 @@ type AppIface interface {
GetOAuthAppsByCreator(userId string, page, perPage int) ([]*model.OAuthApp, *model.AppError)
GetOAuthCodeRedirect(userId string, authRequest *model.AuthorizeRequest) (string, *model.AppError)
GetOAuthImplicitRedirect(userId string, authRequest *model.AuthorizeRequest) (string, *model.AppError)
GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, service, teamId, action, redirectTo, loginHint string) (string, *model.AppError)
GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, service, teamId, action, redirectTo, loginHint string, isMobile bool) (string, *model.AppError)
GetOAuthSignupEndpoint(w http.ResponseWriter, r *http.Request, service, teamId string) (string, *model.AppError)
GetOAuthStateToken(token string) (*model.Token, *model.AppError)
GetOpenGraphMetadata(requestURL string) *opengraph.OpenGraph

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

@@ -6,6 +6,7 @@ package app
import (
"fmt"
"net/http"
"strconv"
"strings"
"time"
@@ -110,7 +111,7 @@ func (a *App) GetUserForLogin(id, loginId string) (*model.User, *model.AppError)
return nil, model.NewAppError("GetUserForLogin", "store.sql_user.get_for_login.app_error", nil, "", http.StatusBadRequest)
}
func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, deviceId string) *model.AppError {
func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, deviceId string, isMobile, isOAuth, isSaml bool) *model.AppError {
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
var rejectionReason string
pluginContext := a.PluginContext()
@@ -124,7 +125,10 @@ func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User,
}
}
session := &model.Session{UserId: user.Id, Roles: user.GetRawRoles(), DeviceId: deviceId, IsOAuth: false}
session := &model.Session{UserId: user.Id, Roles: user.GetRawRoles(), DeviceId: deviceId, IsOAuth: isOAuth, Props: map[string]string{
model.USER_AUTH_SERVICE_IS_MOBILE: strconv.FormatBool(isMobile),
model.USER_AUTH_SERVICE_IS_SAML: strconv.FormatBool(isSaml),
}}
session.GenerateCSRF()
if len(deviceId) > 0 {
@@ -135,6 +139,10 @@ func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User,
err.StatusCode = http.StatusInternalServerError
return err
}
} else if isMobile {
session.SetExpireInDays(*a.Config().ServiceSettings.SessionLengthMobileInDays)
} else if isOAuth || isSaml {
session.SetExpireInDays(*a.Config().ServiceSettings.SessionLengthSSOInDays)
} else {
session.SetExpireInDays(*a.Config().ServiceSettings.SessionLengthWebInDays)
}

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

@@ -350,7 +350,7 @@ func (a *App) newSessionUpdateToken(appName string, accessData *model.AccessData
return accessRsp, nil
}
func (a *App) GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, service, teamId, action, redirectTo, loginHint string) (string, *model.AppError) {
func (a *App) GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, service, teamId, action, redirectTo, loginHint string, isMobile bool) (string, *model.AppError) {
stateProps := map[string]string{}
stateProps["action"] = action
if len(teamId) != 0 {
@@ -361,6 +361,8 @@ func (a *App) GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, serv
stateProps["redirect_to"] = redirectTo
}
stateProps[model.USER_AUTH_SERVICE_IS_MOBILE] = strconv.FormatBool(isMobile)
authUrl, err := a.GetAuthorizationCode(w, r, service, stateProps, loginHint)
if err != nil {
return "", err

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

@@ -3088,7 +3088,7 @@ func (a *OpenTracingAppLayer) DoLocalRequest(rawURL string, body []byte) (*http.
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, deviceId string) *model.AppError {
func (a *OpenTracingAppLayer) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, deviceId string, isMobile bool, isOAuth bool, isSaml bool) *model.AppError {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DoLogin")
@@ -3100,7 +3100,7 @@ func (a *OpenTracingAppLayer) DoLogin(w http.ResponseWriter, r *http.Request, us
}()
defer span.Finish()
resultVar0 := a.app.DoLogin(w, r, user, deviceId)
resultVar0 := a.app.DoLogin(w, r, user, deviceId, isMobile, isOAuth, isSaml)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))
@@ -6215,7 +6215,7 @@ func (a *OpenTracingAppLayer) GetOAuthImplicitRedirect(userId string, authReques
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, service string, teamId string, action string, redirectTo string, loginHint string) (string, *model.AppError) {
func (a *OpenTracingAppLayer) GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, service string, teamId string, action string, redirectTo string, loginHint string, isMobile bool) (string, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetOAuthLoginEndpoint")
@@ -6227,7 +6227,7 @@ func (a *OpenTracingAppLayer) GetOAuthLoginEndpoint(w http.ResponseWriter, r *ht
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.GetOAuthLoginEndpoint(w, r, service, teamId, action, redirectTo, loginHint)
resultVar0, resultVar1 := a.app.GetOAuthLoginEndpoint(w, r, service, teamId, action, redirectTo, loginHint, isMobile)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))

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

@@ -696,7 +696,7 @@ func TestUserWillLogIn_Blocked(t *testing.T) {
r := &http.Request{}
w := httptest.NewRecorder()
err = th.App.DoLogin(w, r, th.BasicUser, "")
err = th.App.DoLogin(w, r, th.BasicUser, "", false, false, false)
assert.Contains(t, err.Id, "Login rejected by plugin", "Expected Login rejected by plugin, got %s", err.Id)
}
@@ -735,7 +735,7 @@ func TestUserWillLogInIn_Passed(t *testing.T) {
r := &http.Request{}
w := httptest.NewRecorder()
err = th.App.DoLogin(w, r, th.BasicUser, "")
err = th.App.DoLogin(w, r, th.BasicUser, "", false, false, false)
assert.Nil(t, err, "Expected nil, got %s", err)
assert.Equal(t, th.App.Session().UserId, th.BasicUser.Id)
@@ -776,7 +776,7 @@ func TestUserHasLoggedIn(t *testing.T) {
r := &http.Request{}
w := httptest.NewRecorder()
err = th.App.DoLogin(w, r, th.BasicUser, "")
err = th.App.DoLogin(w, r, th.BasicUser, "", false, false, false)
assert.Nil(t, err, "Expected nil, got %s", err)

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

@@ -348,7 +348,7 @@ func (a *App) GetSessionLengthInMillis(session *model.Session) int64 {
var days int
if session.IsMobileApp() {
days = *a.Config().ServiceSettings.SessionLengthMobileInDays
} else if session.IsOAuth {
} else if session.IsSSOLogin() {
days = *a.Config().ServiceSettings.SessionLengthSSOInDays
} else {
days = *a.Config().ServiceSettings.SessionLengthWebInDays

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

@@ -206,6 +206,35 @@ func TestApp_GetSessionLengthInMillis(t *testing.T) {
require.Equal(t, dayMillis*3, sessionLength)
})
t.Run("get session length mobile when isMobile in props is set", func(t *testing.T) {
session := &model.Session{
UserId: model.NewId(),
Props: map[string]string{
model.USER_AUTH_SERVICE_IS_MOBILE: "true",
},
}
session, err := th.App.CreateSession(session)
require.Nil(t, err)
sessionLength := th.App.GetSessionLengthInMillis(session)
require.Equal(t, dayMillis*3, sessionLength)
})
t.Run("get session length mobile when isMobile in props is set and takes priority over saml", func(t *testing.T) {
session := &model.Session{
UserId: model.NewId(),
Props: map[string]string{
model.USER_AUTH_SERVICE_IS_MOBILE: "true",
model.USER_AUTH_SERVICE_IS_SAML: "true",
},
}
session, err := th.App.CreateSession(session)
require.Nil(t, err)
sessionLength := th.App.GetSessionLengthInMillis(session)
require.Equal(t, dayMillis*3, sessionLength)
})
t.Run("get session length SSO", func(t *testing.T) {
session := &model.Session{
UserId: model.NewId(),
@@ -218,6 +247,19 @@ func TestApp_GetSessionLengthInMillis(t *testing.T) {
require.Equal(t, dayMillis*2, sessionLength)
})
t.Run("get session length SSO using props", func(t *testing.T) {
session := &model.Session{
UserId: model.NewId(),
Props: map[string]string{
model.USER_AUTH_SERVICE_IS_SAML: "true",
}}
session, err := th.App.CreateSession(session)
require.Nil(t, err)
sessionLength := th.App.GetSessionLengthInMillis(session)
require.Equal(t, dayMillis*2, sessionLength)
})
t.Run("get session length web/LDAP", func(t *testing.T) {
session := &model.Session{
UserId: model.NewId(),