diff --git a/auth.go b/auth.go index 84a3c28..1d4f1c4 100644 --- a/auth.go +++ b/auth.go @@ -2,10 +2,7 @@ package main import ( "crypto/rand" - "errors" - "fmt" "math/big" - "net/smtp" "sync" ) @@ -37,64 +34,6 @@ func (a *Auth) Authorized(token string) bool { return false } -func (a *Auth) Login(email string, config *BoringProxyConfig) (string, error) { - - key, err := genRandomKey() - if err != nil { - return "", errors.New("Error generating key") - } - - link := fmt.Sprintf("https://%s/login?key=%s", config.WebUiDomain, key) - - bodyTemplate := "From: %s <%s>\r\n" + - "To: %s\r\n" + - "Subject: Email Verification\r\n" + - "\r\n" + - "This is email verification request from %s. Please click the following link to complete the verification:\r\n" + - "\r\n" + - "%s\r\n" - - fromText := "boringproxy email verifier" - fromEmail := fmt.Sprintf("auth@%s", config.WebUiDomain) - emailBody := fmt.Sprintf(bodyTemplate, fromText, fromEmail, email, config.WebUiDomain, link) - - emailAuth := smtp.PlainAuth("", config.Smtp.Username, config.Smtp.Password, config.Smtp.Server) - srv := fmt.Sprintf("%s:%d", config.Smtp.Server, config.Smtp.Port) - msg := []byte(emailBody) - err = smtp.SendMail(srv, emailAuth, fromEmail, []string{email}, msg) - if err != nil { - return "", errors.New("Sending email failed. Probably a bad email address.") - } - - a.mutex.Lock() - a.pendingRequests[key] = &LoginRequest{email} - a.mutex.Unlock() - - return "", nil -} - -func (a *Auth) Verify(key string) (string, error) { - a.mutex.Lock() - defer a.mutex.Unlock() - - request, ok := a.pendingRequests[key] - - if !ok { - return "", errors.New("No pending request for that key. It may have expired.") - } - - delete(a.pendingRequests, key) - - token, err := genRandomKey() - if err != nil { - return "", errors.New("Error generating key") - } - - a.db.SetTokenData(token, TokenData{Id: request.Email}) - - return token, nil -} - const chars string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" func genRandomKey() (string, error) { diff --git a/webui/login.tmpl b/webui/login.tmpl index af2c7a8..4c54d42 100644 --- a/webui/login.tmpl +++ b/webui/login.tmpl @@ -19,9 +19,9 @@ -
- - + + +
diff --git a/webui_handler.go b/webui_handler.go index 1c0a0f9..93f9ed0 100644 --- a/webui_handler.go +++ b/webui_handler.go @@ -226,51 +226,33 @@ func (h *WebUiHandler) handleTunnels(w http.ResponseWriter, r *http.Request) { func (h *WebUiHandler) handleLogin(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case "GET": - query := r.URL.Query() - key, exists := query["key"] - - if !exists { - w.WriteHeader(400) - fmt.Fprintf(w, "Must provide key for verification") - return - } - - token, err := h.auth.Verify(key[0]) - - if err != nil { - w.WriteHeader(400) - fmt.Fprintf(w, "Invalid key") - return - } - - cookie := &http.Cookie{Name: "access_token", Value: token, Secure: true, HttpOnly: true} - http.SetCookie(w, cookie) - - http.Redirect(w, r, "/", 307) - - case "POST": - - r.ParseForm() - - toEmail, ok := r.Form["email"] - - if !ok { - w.WriteHeader(400) - w.Write([]byte("Email required for login")) - return - } - - // run in goroutine because it can take some time to send the - // email - go h.auth.Login(toEmail[0], h.config) - - io.WriteString(w, "Check your email to finish logging in") - default: + // Using GET requests to avoid form resubmission warnings in browsers + if r.Method != "GET" { w.WriteHeader(405) w.Write([]byte("Invalid method for login")) } + + r.ParseForm() + + tokenList, ok := r.Form["token"] + + if !ok { + w.WriteHeader(400) + w.Write([]byte("Token required for login")) + return + } + + token := tokenList[0] + + if h.auth.Authorized(token) { + cookie := &http.Cookie{Name: "access_token", Value: token, Secure: true, HttpOnly: true} + http.SetCookie(w, cookie) + http.Redirect(w, r, "/", 307) + } else { + w.WriteHeader(401) + w.Write([]byte("Invalid token")) + return + } } func (h *WebUiHandler) handleCreateTunnel(w http.ResponseWriter, r *http.Request) {