dex/connector/login_local.go
Eric Chiang 5a78e89807 clean up LDAP connector
* Remove some unlikely to be used fields to help configurability.
  * Combined "serverHost" and "serverPort" into "host"
  * Remove "timeout" (just default to 30 seconds).
  * Remove "maxIdleConn" will add it back if users feel the need
    to control the number of cached connections.
  * Remove "trustedEmailProvider" (just always trust).
  * Remove "skipCertVerification" you can't make this connector
    ingore TLS errors.
* Fix configs that don't search before bind (previously broken).
* Add more examples to Documentation
* Refactor LDAPPool Acquire() and Put() into a Do() function which
  always does the flow correctly.
* Added more comments and renamed some functions.
* Moved methods on LDAPIdentityProvider to the LDAPConnector
2016-06-28 15:01:39 -07:00

101 lines
2.6 KiB
Go

package connector
import (
"fmt"
"html/template"
"net/http"
"net/url"
phttp "github.com/coreos/dex/pkg/http"
"github.com/coreos/dex/pkg/log"
"github.com/coreos/go-oidc/oauth2"
"github.com/coreos/go-oidc/oidc"
)
func redirectPostError(w http.ResponseWriter, errorURL url.URL, q url.Values) {
redirectURL := phttp.MergeQuery(errorURL, q)
w.Header().Set("Location", redirectURL.String())
w.WriteHeader(http.StatusSeeOther)
}
// passwordLoginProvider is a provider which requires a username and password to identify the user.
type passwordLoginProvider interface {
Identity(email, password string) (*oidc.Identity, error)
}
func handlePasswordLogin(lf oidc.LoginFunc, tpl *template.Template, idp passwordLoginProvider, localErrorPath string, errorURL url.URL) http.HandlerFunc {
handleGET := func(w http.ResponseWriter, r *http.Request, errMsg string) {
q := r.URL.Query()
sessionKey := q.Get("session_key")
p := &Page{PostURL: r.URL.String(), Name: "Local", SessionKey: sessionKey}
if errMsg != "" {
p.Error = true
p.Message = errMsg
}
if err := tpl.Execute(w, p); err != nil {
phttp.WriteError(w, http.StatusInternalServerError, err.Error())
}
}
handlePOST := func(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
msg := fmt.Sprintf("unable to parse form from body: %v", err)
phttp.WriteError(w, http.StatusBadRequest, msg)
return
}
userid := r.PostForm.Get("userid")
if userid == "" {
handleGET(w, r, "missing email address")
return
}
password := r.PostForm.Get("password")
if password == "" {
handleGET(w, r, "missing password")
return
}
ident, err := idp.Identity(userid, password)
if err != nil {
handleGET(w, r, "invalid login")
return
}
q := r.URL.Query()
sessionKey := r.FormValue("session_key")
if sessionKey == "" {
q.Set("error", oauth2.ErrorInvalidRequest)
q.Set("error_description", "missing session_key")
redirectPostError(w, errorURL, q)
return
}
redirectURL, err := lf(*ident, sessionKey)
if err != nil {
log.Errorf("Unable to log in %#v: %v", *ident, err)
q.Set("error", oauth2.ErrorAccessDenied)
q.Set("error_description", "login failed")
redirectPostError(w, errorURL, q)
return
}
w.Header().Set("Location", redirectURL)
w.WriteHeader(http.StatusFound)
}
return func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "POST":
handlePOST(w, r)
case "GET":
handleGET(w, r, "")
default:
w.Header().Set("Allow", "GET, POST")
phttp.WriteError(w, http.StatusMethodNotAllowed, "GET and POST only acceptable methods")
}
}
}