Commit d1bb106f authored by Eric Chiang's avatar Eric Chiang Committed by GitHub

Merge pull request #521 from ericchiang/allow-dex-to-work-at-non-base-url

Allow dex to work at non base url
parents 1e0ee1e4 40c1ade8
......@@ -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.
......
......@@ -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")
......
......@@ -16,6 +16,7 @@ import (
"net/http"
"net/url"
"os"
"path"
"strings"
"time"
......@@ -43,7 +44,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")
......@@ -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
......
......@@ -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)
......
......@@ -8,6 +8,7 @@ import (
"net/url"
"path"
"sort"
"strings"
"time"
"github.com/coreos/go-oidc/jose"
......@@ -214,41 +215,53 @@ 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) {
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)
}
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 +271,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 {
......@@ -271,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)
......@@ -280,7 +293,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)
}
......
......@@ -2,7 +2,7 @@
<div class="panel">
<h2 class="heading">Log in to Your Account</h2>
<form method="post" action="{{.PostURL | absPath }}">
<form method="post" action="{{ .PostURL }}">
<div class="form-row">
LDAP
<div class="input-desc">
......
......@@ -2,7 +2,7 @@
<div class="panel">
<h2 class="heading">Log in to Your Account</h2>
<form method="post" action="{{.PostURL | absPath}}">
<form method="post" action="{{ .PostURL }}">
<div class="form-row">
<div class="input-desc">
<label for="userid">Email Address</label>
......
......@@ -15,7 +15,7 @@
{{ end }}
{{ else }}
<h2 class="heading">Reset your password</h2>
<form onsubmit="return validate();" id="resetPasswordForm" method="POST" action="/reset-password">
<form onsubmit="return validate();" id="resetPasswordForm" method="POST" action="{{ "/reset-password" | absPath }}">
<div class="form-row">
<div class="input-desc">
<label for="password">New Password</label>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment