Merge pull request #796 from ericchiang/html-template

{web,server}: use html/template and reduce use of auth request ID
This commit is contained in:
Eric Chiang 2017-02-02 17:33:06 -08:00 committed by GitHub
commit 7f860e09b5
4 changed files with 29 additions and 19 deletions

View file

@ -155,14 +155,22 @@ func (s *Server) handleAuthorization(w http.ResponseWriter, r *http.Request) {
return return
} }
authReq.Expiry = s.now().Add(time.Minute * 30) // TODO(ericchiang): Create this authorization request later in the login flow
// so users don't hit "not found" database errors if they wait at the login
// screen too long.
//
// See: https://github.com/coreos/dex/issues/646
authReq.Expiry = s.now().Add(24 * time.Hour) // Totally arbitrary value.
if err := s.storage.CreateAuthRequest(authReq); err != nil { if err := s.storage.CreateAuthRequest(authReq); err != nil {
s.logger.Errorf("Failed to create authorization request: %v", err) s.logger.Errorf("Failed to create authorization request: %v", err)
s.renderError(w, http.StatusInternalServerError, "Failed to connect to the database.") s.renderError(w, http.StatusInternalServerError, "Failed to connect to the database.")
return return
} }
if len(s.connectors) == 1 { if len(s.connectors) == 1 {
for id := range s.connectors { for id := range s.connectors {
// TODO(ericchiang): Make this pass on r.URL.RawQuery and let something latter
// on create the auth request.
http.Redirect(w, r, s.absPath("/auth", id)+"?req="+authReq.ID, http.StatusFound) http.Redirect(w, r, s.absPath("/auth", id)+"?req="+authReq.ID, http.StatusFound)
return return
} }
@ -174,12 +182,14 @@ func (s *Server) handleAuthorization(w http.ResponseWriter, r *http.Request) {
connectorInfos[i] = connectorInfo{ connectorInfos[i] = connectorInfo{
ID: id, ID: id,
Name: conn.DisplayName, Name: conn.DisplayName,
URL: s.absPath("/auth", id), // TODO(ericchiang): Make this pass on r.URL.RawQuery and let something latter
// on create the auth request.
URL: s.absPath("/auth", id) + "?req=" + authReq.ID,
} }
i++ i++
} }
if err := s.templates.login(w, connectorInfos, authReq.ID); err != nil { if err := s.templates.login(w, connectorInfos); err != nil {
s.logger.Errorf("Server template error: %v", err) s.logger.Errorf("Server template error: %v", err)
} }
} }
@ -198,7 +208,11 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
authReq, err := s.storage.GetAuthRequest(authReqID) authReq, err := s.storage.GetAuthRequest(authReqID)
if err != nil { if err != nil {
s.logger.Errorf("Failed to get auth request: %v", err) s.logger.Errorf("Failed to get auth request: %v", err)
s.renderError(w, http.StatusInternalServerError, "Database error.") if err == storage.ErrNotFound {
s.renderError(w, http.StatusBadRequest, "Login session expired.")
} else {
s.renderError(w, http.StatusInternalServerError, "Database error.")
}
return return
} }
scopes := parseScopes(authReq.Scopes) scopes := parseScopes(authReq.Scopes)
@ -229,7 +243,7 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
} }
http.Redirect(w, r, callbackURL, http.StatusFound) http.Redirect(w, r, callbackURL, http.StatusFound)
case connector.PasswordConnector: case connector.PasswordConnector:
if err := s.templates.password(w, authReqID, r.URL.String(), "", false); err != nil { if err := s.templates.password(w, r.URL.String(), "", false); err != nil {
s.logger.Errorf("Server template error: %v", err) s.logger.Errorf("Server template error: %v", err)
} }
case connector.SAMLConnector: case connector.SAMLConnector:
@ -277,7 +291,7 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
return return
} }
if !ok { if !ok {
if err := s.templates.password(w, authReqID, r.URL.String(), username, true); err != nil { if err := s.templates.password(w, r.URL.String(), username, true); err != nil {
s.logger.Errorf("Server template error: %v", err) s.logger.Errorf("Server template error: %v", err)
} }
return return

View file

@ -2,6 +2,7 @@ package server
import ( import (
"fmt" "fmt"
"html/template"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -9,7 +10,6 @@ import (
"path/filepath" "path/filepath"
"sort" "sort"
"strings" "strings"
"text/template"
) )
const ( const (
@ -181,23 +181,20 @@ func (n byName) Len() int { return len(n) }
func (n byName) Less(i, j int) bool { return n[i].Name < n[j].Name } func (n byName) Less(i, j int) bool { return n[i].Name < n[j].Name }
func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] } func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
func (t *templates) login(w http.ResponseWriter, connectors []connectorInfo, authReqID string) error { func (t *templates) login(w http.ResponseWriter, connectors []connectorInfo) error {
sort.Sort(byName(connectors)) sort.Sort(byName(connectors))
data := struct { data := struct {
Connectors []connectorInfo Connectors []connectorInfo
AuthReqID string }{connectors}
}{connectors, authReqID}
return renderTemplate(w, t.loginTmpl, data) return renderTemplate(w, t.loginTmpl, data)
} }
func (t *templates) password(w http.ResponseWriter, authReqID, callback, lastUsername string, lastWasInvalid bool) error { func (t *templates) password(w http.ResponseWriter, postURL, lastUsername string, lastWasInvalid bool) error {
data := struct { data := struct {
AuthReqID string PostURL string
PostURL string Username string
Username string Invalid bool
Invalid bool }{postURL, lastUsername, lastWasInvalid}
}{authReqID, string(callback), lastUsername, lastWasInvalid}
return renderTemplate(w, t.passwordTmpl, data) return renderTemplate(w, t.passwordTmpl, data)
} }

View file

@ -5,7 +5,7 @@
<div> <div>
{{ range $c := .Connectors }} {{ range $c := .Connectors }}
<div class="theme-form-row"> <div class="theme-form-row">
<a href="{{ $c.URL }}?req={{ $.AuthReqID }}" target="_self"> <a href="{{ $c.URL }}" target="_self">
<button class="dex-btn theme-btn-provider"> <button class="dex-btn theme-btn-provider">
<span class="dex-btn-icon dex-btn-icon--{{ $c.ID }}"></span> <span class="dex-btn-icon dex-btn-icon--{{ $c.ID }}"></span>
<span class="dex-btn-text">Log in with {{ $c.Name }}</span> <span class="dex-btn-text">Log in with {{ $c.Name }}</span>

View file

@ -15,7 +15,6 @@
</div> </div>
<input tabindex="2" required id="password" name="password" type="password" class="theme-form-input" placeholder="password" {{ if .Invalid }} autofocus {{ end }}/> <input tabindex="2" required id="password" name="password" type="password" class="theme-form-input" placeholder="password" {{ if .Invalid }} autofocus {{ end }}/>
</div> </div>
<input type="hidden" name="req" value="{{ .AuthReqID }}"/>
{{ if .Invalid }} {{ if .Invalid }}
<div class="dex-error-box"> <div class="dex-error-box">