PLT-4767 Implement MFA Enforcement (#4662)

* Create MFA setup page and remove MFA setup from account settings modal

* Add enforce MFA to system console and force redirect

* Lockdown mfa required API routes, add localization, other changes

* Minor fixes

* Fix typo

* Fix some unit tests

* Fix more unit tests

* Minor fix

* Updating UI for MFA screen (#4670)

* Updating UI for MFA screen

* Updating styles for MFA page

* Add the ability to switch between email/sso with MFA enabled

* Added mfa change email

* Minor UI updates for MFA enforcement

* Fix unit test

* Fix client unit test

* Allow switching email to ldap and back when MFA is enabled

* Fix unit test

* Revert config.json
Этот коммит содержится в:
Joram Wilander
2016-12-12 08:16:10 -05:00
коммит произвёл enahum
родитель f0d71d8789
Коммит 30a10d35a8
34 изменённых файлов: 1001 добавлений и 231 удалений

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

@@ -47,51 +47,55 @@ type Context struct {
}
func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, false, false, true, false, false, false}
return &handler{h, false, false, true, false, false, false, false}
}
func AppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, false, false, false, false, false, false}
return &handler{h, false, false, false, false, false, false, false}
}
func AppHandlerIndependent(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, false, false, false, false, true, false}
return &handler{h, false, false, false, false, true, false, false}
}
func ApiUserRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, true, false, true, false, false, false}
return &handler{h, true, false, true, false, false, false, true}
}
func ApiUserRequiredActivity(h func(*Context, http.ResponseWriter, *http.Request), isUserActivity bool) http.Handler {
return &handler{h, true, false, true, isUserActivity, false, false}
return &handler{h, true, false, true, isUserActivity, false, false, true}
}
func ApiUserRequiredMfa(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, true, false, true, false, false, false, false}
}
func UserRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, true, false, false, false, false, false}
return &handler{h, true, false, false, false, false, false, true}
}
func AppHandlerTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, false, false, false, false, false, true}
return &handler{h, false, false, false, false, false, true, false}
}
func ApiAdminSystemRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, true, true, true, false, false, false}
return &handler{h, true, true, true, false, false, false, true}
}
func ApiAdminSystemRequiredTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, true, true, true, false, false, true}
return &handler{h, true, true, true, false, false, true, true}
}
func ApiAppHandlerTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, false, false, true, false, false, true}
return &handler{h, false, false, true, false, false, true, false}
}
func ApiUserRequiredTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, true, false, true, false, false, true}
return &handler{h, true, false, true, false, false, true, true}
}
func ApiAppHandlerTrustRequesterIndependent(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &handler{h, false, false, true, false, true, true}
return &handler{h, false, false, true, false, true, true, false}
}
type handler struct {
@@ -102,6 +106,7 @@ type handler struct {
isUserActivity bool
isTeamIndependent bool
trustRequester bool
requireMfa bool
}
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -204,6 +209,10 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c.UserRequired()
}
if c.Err == nil && h.requireMfa {
c.MfaRequired()
}
if c.Err == nil && h.requireSystemAdmin {
c.SystemAdminRequired()
}
@@ -331,6 +340,39 @@ func (c *Context) UserRequired() {
}
}
func (c *Context) MfaRequired() {
// Must be licensed for MFA and have it configured for enforcement
if !utils.IsLicensed || !*utils.License.Features.MFA || !*utils.Cfg.ServiceSettings.EnableMultifactorAuthentication || !*utils.Cfg.ServiceSettings.EnforceMultifactorAuthentication {
return
}
// OAuth integrations are excepted
if c.Session.IsOAuth {
return
}
if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
c.Err = model.NewLocAppError("", "api.context.session_expired.app_error", nil, "MfaRequired")
c.Err.StatusCode = http.StatusUnauthorized
return
} else {
user := result.Data.(*model.User)
// Only required for email and ldap accounts
if user.AuthService != "" &&
user.AuthService != model.USER_AUTH_SERVICE_EMAIL &&
user.AuthService != model.USER_AUTH_SERVICE_LDAP {
return
}
if !user.MfaActive {
c.Err = model.NewLocAppError("", "api.context.mfa_required.app_error", nil, "MfaRequired")
c.Err.StatusCode = http.StatusUnauthorized
return
}
}
}
func (c *Context) SystemAdminRequired() {
if len(c.Session.UserId) == 0 {
c.Err = model.NewLocAppError("", "api.context.session_expired.app_error", nil, "SystemAdminRequired")