package login import ( "fmt" "html/template" "net/http" "github.com/golang/glog" "k8s.io/kubernetes/pkg/auth/user" utilruntime "k8s.io/kubernetes/pkg/util/runtime" "github.com/openshift/origin/pkg/auth/authenticator" "github.com/openshift/origin/pkg/auth/oauth/handlers" "github.com/openshift/origin/pkg/auth/server/csrf" ) type RequestAuthenticator interface { authenticator.Request handlers.AuthenticationSuccessHandler } type ConfirmFormRenderer interface { Render(form ConfirmForm, w http.ResponseWriter, req *http.Request) } type ConfirmForm struct { Action string Error string User user.Info Values ConfirmFormValues } type ConfirmFormValues struct { Then string CSRF string } type Confirm struct { csrf csrf.CSRF auth RequestAuthenticator render ConfirmFormRenderer } func NewConfirm(csrf csrf.CSRF, auth RequestAuthenticator, render ConfirmFormRenderer) *Confirm { return &Confirm{ csrf: csrf, auth: auth, render: render, } } func (c *Confirm) ServeHTTP(w http.ResponseWriter, req *http.Request) { switch req.Method { case "GET": c.handleConfirmForm(w, req) case "POST": c.handleConfirm(w, req) default: http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } } func (c *Confirm) handleConfirmForm(w http.ResponseWriter, req *http.Request) { uri, err := getBaseURL(req) if err != nil { glog.Errorf("Unable to generate base URL: %v", err) http.Error(w, "Unable to determine URL", http.StatusInternalServerError) return } form := ConfirmForm{ Action: uri.String(), } if then := req.URL.Query().Get("then"); then != "" { // TODO: sanitize 'then' form.Values.Then = then } switch req.URL.Query().Get("reason") { case "": break default: form.Error = "An unknown error has occurred. Please try again." } csrf, err := c.csrf.Generate(w, req) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to generate CSRF token: %v", err)) } form.Values.CSRF = csrf user, ok, err := c.auth.AuthenticateRequest(req) if err != nil || !ok { glog.Errorf("Unable to authenticate request: %v", err) form.Error = "An unknown error has occurred. Contact your administrator." c.render.Render(form, w, req) return } form.User = user c.render.Render(form, w, req) } func (c *Confirm) handleConfirm(w http.ResponseWriter, req *http.Request) { if ok, err := c.csrf.Check(req, req.FormValue("csrf")); !ok || err != nil { glog.Errorf("Unable to check CSRF token: %v", err) failed("token expired", w, req) return } user, ok, err := c.auth.AuthenticateRequest(req) if err != nil || !ok { if err != nil { glog.Errorf("Unable authenticate request: %v", err) } failed("access denied", w, req) return } then := req.FormValue("then") c.auth.AuthenticationSucceeded(user, then, w, req) } var DefaultConfirmFormRenderer = confirmTemplateRenderer{} type confirmTemplateRenderer struct{} func (r confirmTemplateRenderer) Render(form ConfirmForm, w http.ResponseWriter, req *http.Request) { w.Header().Add("Content-Type", "text/html; charset=UTF-8") w.WriteHeader(http.StatusOK) if err := confirmTemplate.Execute(w, form); err != nil { utilruntime.HandleError(fmt.Errorf("unable render confirm template: %v", err)) } } var confirmTemplate = template.Must(template.New("ConfirmForm").Parse(` {{ if .Error }}
{{ .Error }}
{{ end }}
{{ if .User }}

You are now logged in as {{ .User.GetName }}

{{ else }}

You are not currently logged in.

{{ end }}
`))