github.com/dschalla/mattermost-server@v4.8.1-rc1+incompatible/app/login.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "fmt" 8 "net/http" 9 "strings" 10 "time" 11 12 "github.com/mattermost/mattermost-server/model" 13 "github.com/mssola/user_agent" 14 ) 15 16 func (a *App) AuthenticateUserForLogin(id, loginId, password, mfaToken, deviceId string, ldapOnly bool) (*model.User, *model.AppError) { 17 if len(password) == 0 { 18 err := model.NewAppError("AuthenticateUserForLogin", "api.user.login.blank_pwd.app_error", nil, "", http.StatusBadRequest) 19 return nil, err 20 } 21 22 var user *model.User 23 var err *model.AppError 24 25 if len(id) != 0 { 26 if user, err = a.GetUser(id); err != nil { 27 err.StatusCode = http.StatusBadRequest 28 if a.Metrics != nil { 29 a.Metrics.IncrementLoginFail() 30 } 31 return nil, err 32 } 33 } else { 34 if user, err = a.GetUserForLogin(loginId, ldapOnly); err != nil { 35 if a.Metrics != nil { 36 a.Metrics.IncrementLoginFail() 37 } 38 return nil, err 39 } 40 } 41 42 // and then authenticate them 43 if user, err = a.authenticateUser(user, password, mfaToken); err != nil { 44 if a.Metrics != nil { 45 a.Metrics.IncrementLoginFail() 46 } 47 return nil, err 48 } 49 50 if a.Metrics != nil { 51 a.Metrics.IncrementLogin() 52 } 53 54 return user, nil 55 } 56 57 func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, deviceId string) (*model.Session, *model.AppError) { 58 session := &model.Session{UserId: user.Id, Roles: user.GetRawRoles(), DeviceId: deviceId, IsOAuth: false} 59 60 maxAge := *a.Config().ServiceSettings.SessionLengthWebInDays * 60 * 60 * 24 61 62 if len(deviceId) > 0 { 63 session.SetExpireInDays(*a.Config().ServiceSettings.SessionLengthMobileInDays) 64 65 // A special case where we logout of all other sessions with the same Id 66 if err := a.RevokeSessionsForDeviceId(user.Id, deviceId, ""); err != nil { 67 err.StatusCode = http.StatusInternalServerError 68 return nil, err 69 } 70 } else { 71 session.SetExpireInDays(*a.Config().ServiceSettings.SessionLengthWebInDays) 72 } 73 74 ua := user_agent.New(r.UserAgent()) 75 76 plat := ua.Platform() 77 if plat == "" { 78 plat = "unknown" 79 } 80 81 os := ua.OS() 82 if os == "" { 83 os = "unknown" 84 } 85 86 bname, bversion := ua.Browser() 87 if bname == "" { 88 bname = "unknown" 89 } 90 91 if strings.Contains(r.UserAgent(), "Mattermost") { 92 bname = "Desktop App" 93 } 94 95 if bversion == "" { 96 bversion = "0.0" 97 } 98 99 session.AddProp(model.SESSION_PROP_PLATFORM, plat) 100 session.AddProp(model.SESSION_PROP_OS, os) 101 session.AddProp(model.SESSION_PROP_BROWSER, fmt.Sprintf("%v/%v", bname, bversion)) 102 103 var err *model.AppError 104 if session, err = a.CreateSession(session); err != nil { 105 err.StatusCode = http.StatusInternalServerError 106 return nil, err 107 } 108 109 w.Header().Set(model.HEADER_TOKEN, session.Token) 110 111 secure := false 112 if GetProtocol(r) == "https" { 113 secure = true 114 } 115 116 domain := a.GetCookieDomain() 117 expiresAt := time.Unix(model.GetMillis()/1000+int64(maxAge), 0) 118 sessionCookie := &http.Cookie{ 119 Name: model.SESSION_COOKIE_TOKEN, 120 Value: session.Token, 121 Path: "/", 122 MaxAge: maxAge, 123 Expires: expiresAt, 124 HttpOnly: true, 125 Domain: domain, 126 Secure: secure, 127 } 128 129 userCookie := &http.Cookie{ 130 Name: model.SESSION_COOKIE_USER, 131 Value: user.Id, 132 Path: "/", 133 MaxAge: maxAge, 134 Expires: expiresAt, 135 Domain: domain, 136 Secure: secure, 137 } 138 139 http.SetCookie(w, sessionCookie) 140 http.SetCookie(w, userCookie) 141 142 return session, nil 143 } 144 145 func GetProtocol(r *http.Request) string { 146 if r.Header.Get(model.HEADER_FORWARDED_PROTO) == "https" || r.TLS != nil { 147 return "https" 148 } else { 149 return "http" 150 } 151 }