Commit 230ae972 authored by ale's avatar ale

Allow user to switch 2FA mechanism if more than one is supported

Add links 'use a numeric / hardware token instead' to the 2FA login
pages, using the list of available 2FA mechanisms found in the
auth Response.
parent d0fa32ce
Pipeline #2834 passed with stages
in 2 minutes and 43 seconds
......@@ -1124,6 +1124,14 @@ var _templatesLogin_otpHtml = []byte(`{{template "header" .}}
</form>
{{if .AuthResponse.Has2FAMethod "u2f"}}
<p>
<a href="{{.URLPrefix}}/login?2fa=u2f">
Use a hardware token instead.
</a>
</p>
{{end}}
{{template "footer" .}}
`)
......@@ -1137,7 +1145,7 @@ func templatesLogin_otpHtml() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "templates/login_otp.html", size: 562, mode: os.FileMode(420), modTime: time.Unix(1550307595, 0)}
info := bindataFileInfo{name: "templates/login_otp.html", size: 711, mode: os.FileMode(420), modTime: time.Unix(1556965814, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
......@@ -1226,6 +1234,14 @@ var _templatesLogin_u2fHtml = []byte(`{{template "header" .}}
</form>
{{if .AuthResponse.Has2FAMethod "otp"}}
<p>
<a href="{{.URLPrefix}}/login?2fa=otp">
Use a numeric one-time token instead.
</a>
</p>
{{end}}
{{template "footer" .}}
`)
......@@ -1239,7 +1255,7 @@ func templatesLogin_u2fHtml() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "templates/login_u2f.html", size: 512, mode: os.FileMode(420), modTime: time.Unix(1541234815, 0)}
info := bindataFileInfo{name: "templates/login_u2f.html", size: 669, mode: os.FileMode(420), modTime: time.Unix(1556965831, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
......
......@@ -39,7 +39,9 @@ type loginSession struct {
AuthResponse *auth.Response
}
var defaultLoginSessionLifetime = 300 * time.Second
// The login session is short-lived, it only needs to last for the duration of
// the login process itself.
var defaultLoginSessionLifetime = 10 * time.Minute
func newLoginSession() *loginSession {
return &loginSession{
......@@ -189,10 +191,8 @@ func (l *loginHandler) dispatch(w http.ResponseWriter, req *http.Request, sessio
switch session.State {
case loginStatePassword:
return l.handlePassword(w, req, session)
case loginStateOTP:
return l.handleOTP(w, req, session)
case loginStateU2F:
return l.handleU2F(w, req, session)
case loginStateOTP, loginStateU2F:
return l.handle2FA(w, req, session)
}
return loginStateNone, nil, errors.New("unreachable")
}
......@@ -241,11 +241,39 @@ func (l *loginHandler) handlePassword(w http.ResponseWriter, req *http.Request,
return loginStateNone, body, err
}
func (l *loginHandler) handle2FA(w http.ResponseWriter, req *http.Request, session *loginSession) (loginState, []byte, error) {
// The '2fa' request parameter can be used to manually switch between
// 2fa mechanisms. There is no need to pass the parameter through POSTs
// though, as the login session state is sticky.
if switch2fa := auth.TFAMethod(req.FormValue("2fa")); switch2fa != "" {
if !session.AuthResponse.Has2FAMethod(switch2fa) {
return loginStateNone, nil, errors.New("unsupported 2FA method")
}
switch switch2fa {
case auth.TFAMethodOTP:
session.State = loginStateOTP
case auth.TFAMethodU2F:
session.State = loginStateU2F
}
}
switch session.State {
case loginStateOTP:
return l.handleOTP(w, req, session)
case loginStateU2F:
return l.handleU2F(w, req, session)
}
return loginStateNone, nil, errors.New("unreachable")
}
// Handle login with password and TOTP.
func (l *loginHandler) handleOTP(w http.ResponseWriter, req *http.Request, session *loginSession) (loginState, []byte, error) {
otp := req.FormValue("otp")
env := map[string]interface{}{"Error": false}
env := map[string]interface{}{
"AuthResponse": session.AuthResponse,
"Error": false,
}
if req.Method == "POST" && otp != "" {
resp, err := l.makeAuthRequest(w, req, session.Username, session.Password, otp, nil)
if err != nil {
......@@ -267,6 +295,7 @@ func (l *loginHandler) handleU2F(w http.ResponseWriter, req *http.Request, sessi
u2fresponse := req.FormValue("u2f_response")
env := map[string]interface{}{
"AuthResponse": session.AuthResponse,
"U2FSignRequest": session.AuthResponse.U2FSignRequest,
"Error": false,
}
......
......@@ -18,4 +18,12 @@
</form>
{{if .AuthResponse.Has2FAMethod "u2f"}}
<p>
<a href="{{.URLPrefix}}/login?2fa=u2f">
Use a hardware token instead.
</a>
</p>
{{end}}
{{template "footer" .}}
......@@ -20,4 +20,12 @@
</form>
{{if .AuthResponse.Has2FAMethod "otp"}}
<p>
<a href="{{.URLPrefix}}/login?2fa=otp">
Use a numeric one-time token instead.
</a>
</p>
{{end}}
{{template "footer" .}}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment