mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-10 15:47:36 +02:00
authenticate: make callback path configurable (#493)
Signed-off-by: Bobby DeSimone <bobbydesimone@gmail.com>
This commit is contained in:
parent
1901cb5ca0
commit
5716113c2a
6 changed files with 57 additions and 26 deletions
|
@ -27,8 +27,6 @@ import (
|
|||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
)
|
||||
|
||||
const callbackPath = "/oauth2/callback"
|
||||
|
||||
// ValidateOptions checks that configuration are complete and valid.
|
||||
// Returns on first error found.
|
||||
func ValidateOptions(o config.Options) error {
|
||||
|
@ -47,6 +45,9 @@ func ValidateOptions(o config.Options) error {
|
|||
if o.ClientSecret == "" {
|
||||
return errors.New("authenticate: 'IDP_CLIENT_SECRET' is required")
|
||||
}
|
||||
if o.AuthenticateCallbackPath == "" {
|
||||
return errors.New("authenticate: 'AUTHENTICATE_CALLBACK_PATH' is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -149,7 +150,7 @@ func New(opts config.Options) (*Authenticate, error) {
|
|||
headerStore := header.NewStore(encryptedEncoder, "Pomerium")
|
||||
|
||||
redirectURL, _ := urlutil.DeepCopy(opts.AuthenticateURL)
|
||||
redirectURL.Path = callbackPath
|
||||
redirectURL.Path = opts.AuthenticateCallbackPath
|
||||
// configure our identity provider
|
||||
provider, err := identity.New(
|
||||
opts.Provider,
|
||||
|
|
|
@ -43,6 +43,8 @@ func TestOptions_Validate(t *testing.T) {
|
|||
badSharedKey.SharedKey = ""
|
||||
badAuthenticateURL := newTestOptions(t)
|
||||
badAuthenticateURL.AuthenticateURL = nil
|
||||
badCallbackPath := newTestOptions(t)
|
||||
badCallbackPath.AuthenticateCallbackPath = ""
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -60,6 +62,7 @@ func TestOptions_Validate(t *testing.T) {
|
|||
{"no client id", emptyClientID, true},
|
||||
{"no client secret", emptyClientSecret, true},
|
||||
{"empty authenticate url", badAuthenticateURL, true},
|
||||
{"empty callback path", badCallbackPath, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -31,8 +31,8 @@ func (a *Authenticate) Handler() http.Handler {
|
|||
a.cookieSecret,
|
||||
csrf.Secure(a.cookieOptions.Secure),
|
||||
csrf.Path("/"),
|
||||
csrf.UnsafePaths([]string{callbackPath}), // enforce CSRF on "safe" handler
|
||||
csrf.FormValueName("state"), // rfc6749 section-10.12
|
||||
csrf.UnsafePaths([]string{a.RedirectURL.Path}), // enforce CSRF on "safe" handler
|
||||
csrf.FormValueName("state"), // rfc6749 section-10.12
|
||||
csrf.CookieName(fmt.Sprintf("%s_csrf", a.cookieOptions.Name)),
|
||||
csrf.ErrorHandler(httputil.HandlerFunc(httputil.CSRFFailureHandler)),
|
||||
))
|
||||
|
|
|
@ -89,6 +89,12 @@ type Options struct {
|
|||
AuthenticateURLString string `mapstructure:"authenticate_service_url" yaml:"authenticate_service_url,omitempty"`
|
||||
AuthenticateURL *url.URL `yaml:"-,omitempty"`
|
||||
|
||||
// AuthenticateCallbackPath is the path to the HTTP endpoint that will
|
||||
// receive the response from your identity provider. The value must exactly
|
||||
// match one of the authorized redirect URIs for the OAuth 2.0 client.
|
||||
// Defaults to: `/oauth2/callback`
|
||||
AuthenticateCallbackPath string `mapstructure:"authenticate_callback_path" yaml:"authenticate_callback_path,omitempty"`
|
||||
|
||||
// Session/Cookie management
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
||||
CookieName string `mapstructure:"cookie_name" yaml:"cookie_name,omitempty"`
|
||||
|
@ -211,16 +217,17 @@ var defaultOptions = Options{
|
|||
"X-XSS-Protection": "1; mode=block",
|
||||
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
|
||||
},
|
||||
Addr: ":443",
|
||||
ReadHeaderTimeout: 10 * time.Second,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 0, // support streaming by default
|
||||
IdleTimeout: 5 * time.Minute,
|
||||
RefreshCooldown: 5 * time.Minute,
|
||||
GRPCAddr: ":443",
|
||||
GRPCClientTimeout: 10 * time.Second, // Try to withstand transient service failures for a single request
|
||||
GRPCClientDNSRoundRobin: true,
|
||||
CacheStore: "autocache",
|
||||
Addr: ":443",
|
||||
ReadHeaderTimeout: 10 * time.Second,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 0, // support streaming by default
|
||||
IdleTimeout: 5 * time.Minute,
|
||||
RefreshCooldown: 5 * time.Minute,
|
||||
GRPCAddr: ":443",
|
||||
GRPCClientTimeout: 10 * time.Second, // Try to withstand transient service failures for a single request
|
||||
GRPCClientDNSRoundRobin: true,
|
||||
CacheStore: "autocache",
|
||||
AuthenticateCallbackPath: "/oauth2/callback",
|
||||
}
|
||||
|
||||
// NewDefaultOptions returns a copy the default options. It's the caller's
|
||||
|
|
|
@ -219,11 +219,12 @@ func TestOptionsFromViper(t *testing.T) {
|
|||
{"good",
|
||||
[]byte(`{"insecure_server":true,"policy":[{"from": "https://from.example","to":"https://to.example"}]}`),
|
||||
&Options{
|
||||
Policies: []Policy{{From: "https://from.example", To: "https://to.example"}},
|
||||
CookieName: "_pomerium",
|
||||
CookieSecure: true,
|
||||
InsecureServer: true,
|
||||
CookieHTTPOnly: true,
|
||||
Policies: []Policy{{From: "https://from.example", To: "https://to.example"}},
|
||||
CookieName: "_pomerium",
|
||||
CookieSecure: true,
|
||||
InsecureServer: true,
|
||||
CookieHTTPOnly: true,
|
||||
AuthenticateCallbackPath: "/oauth2/callback",
|
||||
Headers: map[string]string{
|
||||
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
|
||||
"X-Frame-Options": "SAMEORIGIN",
|
||||
|
@ -233,12 +234,13 @@ func TestOptionsFromViper(t *testing.T) {
|
|||
{"good disable header",
|
||||
[]byte(`{"insecure_server":true,"headers": {"disable":"true"},"policy":[{"from": "https://from.example","to":"https://to.example"}]}`),
|
||||
&Options{
|
||||
Policies: []Policy{{From: "https://from.example", To: "https://to.example"}},
|
||||
CookieName: "_pomerium",
|
||||
CookieSecure: true,
|
||||
CookieHTTPOnly: true,
|
||||
InsecureServer: true,
|
||||
Headers: map[string]string{}},
|
||||
Policies: []Policy{{From: "https://from.example", To: "https://to.example"}},
|
||||
CookieName: "_pomerium",
|
||||
AuthenticateCallbackPath: "/oauth2/callback",
|
||||
CookieSecure: true,
|
||||
CookieHTTPOnly: true,
|
||||
InsecureServer: true,
|
||||
Headers: map[string]string{}},
|
||||
false},
|
||||
{"bad url", []byte(`{"policy":[{"from": "https://","to":"https://to.example"}]}`), nil, true},
|
||||
{"bad policy", []byte(`{"policy":[{"allow_public_unauthenticated_access": "dog","to":"https://to.example"}]}`), nil, true},
|
||||
|
|
|
@ -503,6 +503,24 @@ Identity provider scopes correspond to access privilege scopes as defined in Sec
|
|||
|
||||
Identity Provider Service Account is field used to configure any additional user account or access-token that may be required for querying additional user information during authentication. For a concrete example, Google an additional service account and to make a follow-up request to query a user's group membership. For more information, refer to the [identity provider] docs to see if your provider requires this setting.
|
||||
|
||||
### Authenticate Callback Path
|
||||
|
||||
- Environmental Variable: `AUTHENTICATE_CALLBACK_PATH`
|
||||
- Config File Key: `authenticate_callback_path`
|
||||
- Type: `string`
|
||||
- Default: `/oauth2/callback`
|
||||
- Optional
|
||||
|
||||
The authenticate callback path is the path/url from the authenticate service that will receive the response from your identity provider. The value must exactly match one of the authorized redirect URIs for the OAuth 2.0 client.
|
||||
|
||||
This value is referred to as the `redirect_url` in the [OpenIDConnect](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) and OAuth2 specs.
|
||||
|
||||
See also:
|
||||
|
||||
- [OAuth2 RFC 6749](https://tools.ietf.org/html/rfc6749#section-3.1.2)
|
||||
- [OIDC Spec](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest)
|
||||
- [Google - Setting Redirect URI](https://developers.google.com/identity/protocols/OpenIDConnect#setredirecturi)
|
||||
|
||||
## Proxy Service
|
||||
|
||||
### Signing Key
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue