From 854b767273c0dded2978accfa5d9c3a3b16883e9 Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Mon, 25 Jul 2016 09:04:58 -0700 Subject: [PATCH 1/4] *: update handlers to include issuer url in path --- server/server.go | 36 +++++++++++++++++++++--------------- static/html/ldap-login.html | 2 +- static/html/local-login.html | 2 +- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/server/server.go b/server/server.go index 3cb9e5f3..1e0590ea 100644 --- a/server/server.go +++ b/server/server.go @@ -214,41 +214,47 @@ func (s *Server) HTTPHandler() http.Handler { clock := clockwork.NewRealClock() mux := http.NewServeMux() - mux.HandleFunc(httpPathDiscovery, handleDiscoveryFunc(s.ProviderConfig())) - mux.HandleFunc(httpPathAuth, handleAuthFunc(s, s.Connectors, s.LoginTemplate, s.EnableRegistration)) - mux.HandleFunc(httpPathOOB, handleOOBFunc(s, s.OOBTemplate)) - mux.HandleFunc(httpPathToken, handleTokenFunc(s)) - mux.HandleFunc(httpPathKeys, handleKeysFunc(s.KeyManager, clock)) - mux.Handle(httpPathHealth, makeHealthHandler(checks)) + handle := func(urlPath string, h http.Handler) { + mux.Handle(path.Join(s.IssuerURL.Path, urlPath), h) + } + handleFunc := func(urlPath string, hf http.HandlerFunc) { + handle(urlPath, hf) + } + handleFunc(httpPathDiscovery, handleDiscoveryFunc(s.ProviderConfig())) + handleFunc(httpPathAuth, handleAuthFunc(s, s.Connectors, s.LoginTemplate, s.EnableRegistration)) + handleFunc(httpPathOOB, handleOOBFunc(s, s.OOBTemplate)) + handleFunc(httpPathToken, handleTokenFunc(s)) + handleFunc(httpPathKeys, handleKeysFunc(s.KeyManager, clock)) + handle(httpPathHealth, makeHealthHandler(checks)) if s.EnableRegistration { - mux.HandleFunc(httpPathRegister, handleRegisterFunc(s, s.RegisterTemplate)) + handleFunc(httpPathRegister, handleRegisterFunc(s, s.RegisterTemplate)) } - mux.HandleFunc(httpPathEmailVerify, handleEmailVerifyFunc(s.VerifyEmailTemplate, + handleFunc(httpPathEmailVerify, handleEmailVerifyFunc(s.VerifyEmailTemplate, s.IssuerURL, s.KeyManager.PublicKeys, s.UserManager)) - mux.Handle(httpPathVerifyEmailResend, s.NewClientTokenAuthHandler(handleVerifyEmailResendFunc(s.IssuerURL, + handle(httpPathVerifyEmailResend, s.NewClientTokenAuthHandler(handleVerifyEmailResendFunc(s.IssuerURL, s.KeyManager.PublicKeys, s.UserEmailer, s.UserRepo, s.ClientManager))) - mux.Handle(httpPathSendResetPassword, &SendResetPasswordEmailHandler{ + handle(httpPathSendResetPassword, &SendResetPasswordEmailHandler{ tpl: s.SendResetPasswordEmailTemplate, emailer: s.UserEmailer, sm: s.SessionManager, cm: s.ClientManager, }) - mux.Handle(httpPathResetPassword, &ResetPasswordHandler{ + handle(httpPathResetPassword, &ResetPasswordHandler{ tpl: s.ResetPasswordTemplate, issuerURL: s.IssuerURL, um: s.UserManager, keysFunc: s.KeyManager.PublicKeys, }) - mux.Handle(httpPathAcceptInvitation, &InvitationHandler{ + handle(httpPathAcceptInvitation, &InvitationHandler{ passwordResetURL: s.absURL(httpPathResetPassword), issuerURL: s.IssuerURL, um: s.UserManager, @@ -258,10 +264,10 @@ func (s *Server) HTTPHandler() http.Handler { }) if s.EnableClientRegistration { - mux.HandleFunc(httpPathClientRegistration, s.handleClientRegistration) + handleFunc(httpPathClientRegistration, s.handleClientRegistration) } - mux.HandleFunc(httpPathDebugVars, health.ExpvarHandler) + handleFunc(httpPathDebugVars, health.ExpvarHandler) pcfg := s.ProviderConfig() for _, idpc := range s.Connectors { @@ -280,7 +286,7 @@ func (s *Server) HTTPHandler() http.Handler { usersAPI := usersapi.NewUsersAPI(s.UserManager, s.ClientManager, s.RefreshTokenRepo, s.UserEmailer, s.localConnectorID) handler := NewUserMgmtServer(usersAPI, s.JWTVerifierFactory(), s.UserManager, s.ClientManager).HTTPHandler() - mux.Handle(apiBasePath+"/", handler) + handle(apiBasePath+"/", handler) return http.Handler(mux) } diff --git a/static/html/ldap-login.html b/static/html/ldap-login.html index 3a80c5af..5fb5cb7d 100644 --- a/static/html/ldap-login.html +++ b/static/html/ldap-login.html @@ -2,7 +2,7 @@

Log in to Your Account

-
+
LDAP
diff --git a/static/html/local-login.html b/static/html/local-login.html index 3e2834b6..9629baa3 100644 --- a/static/html/local-login.html +++ b/static/html/local-login.html @@ -2,7 +2,7 @@

Log in to Your Account

- +
From ede6300a843b45d9658b40e5f1821979173b6a1a Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Mon, 25 Jul 2016 09:05:28 -0700 Subject: [PATCH 2/4] *: by default, have dex listen at a non-root url --- cmd/dex-worker/main.go | 2 +- examples/app/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/dex-worker/main.go b/cmd/dex-worker/main.go index ac9b141a..aef6f6c0 100644 --- a/cmd/dex-worker/main.go +++ b/cmd/dex-worker/main.go @@ -33,7 +33,7 @@ func main() { fs := flag.NewFlagSet("dex-worker", flag.ExitOnError) listen := fs.String("listen", "http://127.0.0.1:5556", "the address that the server will listen on") - issuer := fs.String("issuer", "http://127.0.0.1:5556", "the issuer's location") + issuer := fs.String("issuer", "http://127.0.0.1:5556/dex", "the issuer's location") certFile := fs.String("tls-cert-file", "", "the server's certificate file for TLS connection") keyFile := fs.String("tls-key-file", "", "the server's private key file for TLS connection") diff --git a/examples/app/main.go b/examples/app/main.go index 320a33ec..3344dde5 100644 --- a/examples/app/main.go +++ b/examples/app/main.go @@ -43,7 +43,7 @@ func main() { certFile := fs.String("tls-cert-file", "", "the TLS cert file. If empty, the app will listen on HTTP") keyFile := fs.String("tls-key-file", "", "the TLS key file. If empty, the app will listen on HTTP") - discovery := fs.String("discovery", "http://127.0.0.1:5556", "") + discovery := fs.String("discovery", "http://127.0.0.1:5556/dex", "") logDebug := fs.Bool("log-debug", false, "log debug-level information") logTimestamps := fs.Bool("log-timestamps", false, "prefix log lines with timestamps") From 435cadfc19cd8f91828f340c339a5bf5bec9e1b5 Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Mon, 25 Jul 2016 17:06:20 -0700 Subject: [PATCH 3/4] *: more updates to prepend the correct API path --- examples/app/main.go | 3 ++- server/register.go | 3 ++- server/server.go | 11 +++++++++-- static/html/reset-password.html | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/examples/app/main.go b/examples/app/main.go index 3344dde5..1f2c62c0 100644 --- a/examples/app/main.go +++ b/examples/app/main.go @@ -16,6 +16,7 @@ import ( "net/http" "net/url" "os" + "path" "strings" "time" @@ -181,7 +182,7 @@ func NewClientHandler(c *oidc.Client, issuer string, cbURL url.URL) http.Handler } resendURL := *issuerURL - resendURL.Path = "/resend-verify-email" + resendURL.Path = path.Join(resendURL.Path, "/resend-verify-email") mux.HandleFunc("/resend", handleResendFunc(c, *issuerURL, resendURL, cbURL)) return mux diff --git a/server/register.go b/server/register.go index 013c0b22..c73ef252 100644 --- a/server/register.go +++ b/server/register.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "net/url" + "path" "strings" "github.com/coreos/dex/connector" @@ -336,7 +337,7 @@ func getConnectorForUserByEmail(ur user.UserRepo, email string) (string, error) func newLoginURLFromSession(issuer url.URL, ses *session.Session, register bool, connectorFilter []string, msgCode string) *url.URL { loginURL := issuer v := loginURL.Query() - loginURL.Path = httpPathAuth + loginURL.Path = path.Join(loginURL.Path, httpPathAuth) v.Set("redirect_uri", ses.RedirectURL.String()) v.Set("state", ses.ClientState) v.Set("client_id", ses.ClientID) diff --git a/server/server.go b/server/server.go index 1e0590ea..49611149 100644 --- a/server/server.go +++ b/server/server.go @@ -8,6 +8,7 @@ import ( "net/url" "path" "sort" + "strings" "time" "github.com/coreos/go-oidc/jose" @@ -215,7 +216,13 @@ func (s *Server) HTTPHandler() http.Handler { clock := clockwork.NewRealClock() mux := http.NewServeMux() handle := func(urlPath string, h http.Handler) { - mux.Handle(path.Join(s.IssuerURL.Path, urlPath), h) + p := path.Join(s.IssuerURL.Path, urlPath) + // path.Join always trims trailing slashes (https://play.golang.org/p/GRr0jDd9P7). + // If path being registered has a trailing slash, add it back on. + if strings.HasSuffix(urlPath, "/") { + p = p + "/" + } + mux.Handle(p, h) } handleFunc := func(urlPath string, hf http.HandlerFunc) { handle(urlPath, hf) @@ -277,7 +284,7 @@ func (s *Server) HTTPHandler() http.Handler { } // NOTE(ericchiang): This path MUST end in a "/" in order to indicate a // path prefix rather than an absolute path. - mux.Handle(path.Join(httpPathAuth, idpc.ID())+"/", idpc.Handler(*errorURL)) + handle(path.Join(httpPathAuth, idpc.ID())+"/", idpc.Handler(*errorURL)) } apiBasePath := path.Join(httpPathAPI, APIVersion) diff --git a/static/html/reset-password.html b/static/html/reset-password.html index 898b3255..b692489e 100644 --- a/static/html/reset-password.html +++ b/static/html/reset-password.html @@ -15,7 +15,7 @@ {{ end }} {{ else }}

Reset your password

- +
From 40c1ade816e470264f8bebd282010aa0c9278cd0 Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Tue, 26 Jul 2016 11:21:54 -0700 Subject: [PATCH 4/4] Documentation: update connector callback documentation to use issuer URL --- Documentation/connectors-configuration.md | 24 +++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Documentation/connectors-configuration.md b/Documentation/connectors-configuration.md index 635bdced..0aa12c27 100644 --- a/Documentation/connectors-configuration.md +++ b/Documentation/connectors-configuration.md @@ -54,10 +54,14 @@ In order to use the `oidc` connector you must register dex as an OIDC client; th When registering dex as a client, you need to provide redirect URLs to the provider. dex requires just one: ``` -https://$DEX_HOST:$DEX_PORT/auth/$CONNECTOR_ID/callback +$ISSUER_URL/auth/$CONNECTOR_ID/callback ``` -`$DEX_HOST` and `$DEX_PORT` are the host and port of your dex installation. `$CONNECTOR_ID` is the `id` field of the connector for this OIDC provider. +For example runnning a connector with ID `"google"` and an issuer URL of `"https://auth.example.com/foo"` the redirect would be. + +``` +https://auth.example.com/foo/auth/google/callback +``` Here's what a `oidc` connector looks like configured for authenticating with Google; the clientID and clientSecret shown are not usable. We consider Google a trusted email provider because the email address that is present in claims is for a Google provisioned email account (eg. an `@gmail.com` address) @@ -82,10 +86,14 @@ This connector config lets users authenticate through [GitHub](https://github.co To begin, register an OAuth application with GitHub through your, or your organization's [account settings](ttps://github.com/settings/applications/new). To register dex as a client of your GitHub application, enter dex's redirect URL under 'Authorization callback URL': ``` -https://$DEX_HOST:$DEX_PORT/auth/$CONNECTOR_ID/callback +$ISSUER_URL/auth/$CONNECTOR_ID/callback ``` -`$DEX_HOST` and `$DEX_PORT` are the host and port of your dex installation. `$CONNECTOR_ID` is the `id` field of the connector. +For example runnning a connector with ID `"github"` and an issuer URL of `"https://auth.example.com/bar"` the redirect would be. + +``` +https://auth.example.com/bar/auth/github/callback +``` Here's an example of a `github` connector; the clientID and clientSecret should be replaced by values provided by GitHub. @@ -113,10 +121,14 @@ __NOTE:__ When configuring a consumer through Bitbucket you _must_ configure rea To register dex as a client of your Bitbucket consumer, enter dex's redirect URL under 'Callback URL': ``` -https://$DEX_HOST:$DEX_PORT/auth/$CONNECTOR_ID/callback +$ISSUER_URL/auth/$CONNECTOR_ID/callback ``` -`$DEX_HOST` and `$DEX_PORT` are the host and port of your dex installation. `$CONNECTOR_ID` is the `id` field of the connector. +For example runnning a connector with ID `"bitbucket"` and an issuer URL of `"https://auth.example.com/spaz"` the redirect would be. + +``` +https://auth.example.com/spaz/auth/bitbucket/callback +``` Here's an example of a `bitbucket` connector; the clientID and clientSecret should be replaced by values provided by Bitbucket.