Add -skip-oidc-discovery option (#41)

* added karrieretutor go-oidc fork for using an AAD B2C Policy

* added karrieretutor go-oidc fork for using an AAD B2C Policy

* added --skip-oidc-discovery option

* added --skip-oidc-discovery option

* add simple test for skip-oidc-discovery option

* revert Dockerfile to pusher upstream

* revert Dockerfile to pusher upstream

* remove karrieretutor b2c option leftover

* remove karrieretutor b2c option leftover

* Fix typo (missing letters)

Co-Authored-By: marratj <marrat@marrat.de>

* Fix typo (missing letters)

Co-Authored-By: marratj <marrat@marrat.de>

* replace fake http client with NewProvider() from go-oidc

* remove OIDC UserInfo URL option (not required)

* add info about -skip-oidc-discovery to README

* add note to changelog

* Update outdated comment
This commit is contained in:
Marcel D. Juhnke 2019-03-04 14:54:22 +01:00 committed by Joel Speed
parent fb1614c873
commit 8816a2a972
5 changed files with 78 additions and 9 deletions

View File

@ -3,6 +3,7 @@
## Changes since v3.1.0 ## Changes since v3.1.0
- [#68](https://github.com/pusher/oauth2_proxy/pull/68) forward X-Auth-Access-Token header (@davidholsgrove) - [#68](https://github.com/pusher/oauth2_proxy/pull/68) forward X-Auth-Access-Token header (@davidholsgrove)
- [#41](https://github.com/pusher/oauth2_proxy/pull/41) Added option to manually specify OIDC endpoints instead of relying on discovery
# v3.1.0 # v3.1.0

View File

@ -166,6 +166,26 @@ OpenID Connect is a spec for OAUTH 2.0 + identity that is implemented by many ma
-cookie-secure=false -cookie-secure=false
-email-domain example.com -email-domain example.com
#### Skip OIDC discovery
Some providers do not support OIDC discovery via their issuer URL, so oauth2_proxy cannot simply grab the authorization, token and jwks URI endpoints from the provider's metadata.
In this case, you can set the `-skip-oidc-discovery` option, and supply those required endpoints manually:
```
-provider oidc
-client-id oauth2_proxy
-client-secret proxy
-redirect-url http://127.0.0.1:4180/oauth2/callback
-oidc-issuer-url http://127.0.0.1:5556
-skip-oidc-discovery
-login-url http://127.0.0.1:5556/authorize
-redeem-url http://127.0.0.1:5556/token
-oidc-jwks-url http://127.0.0.1:5556/keys
-cookie-secure=false
-email-domain example.com
```
## Email Authentication ## Email Authentication
To authorize by email domain use `--email-domain=yourcompany.com`. To authorize individual email addresses use `--authenticated-emails-file=/path/to/file` with one email per line. To authorize all email addresses use `--email-domain=*`. To authorize by email domain use `--email-domain=yourcompany.com`. To authorize individual email addresses use `--authenticated-emails-file=/path/to/file` with one email per line. To authorize all email addresses use `--email-domain=*`.
@ -213,6 +233,7 @@ Usage of oauth2_proxy:
-https-address string: <addr>:<port> to listen on for HTTPS clients (default ":443") -https-address string: <addr>:<port> to listen on for HTTPS clients (default ":443")
-login-url string: Authentication endpoint -login-url string: Authentication endpoint
-oidc-issuer-url: the OpenID Connect issuer URL. ie: "https://accounts.google.com" -oidc-issuer-url: the OpenID Connect issuer URL. ie: "https://accounts.google.com"
-oidc-jwks-url string: OIDC JWKS URI for token verification; required if OIDC discovery is disabled
-pass-access-token: pass OAuth access_token to upstream via X-Forwarded-Access-Token header -pass-access-token: pass OAuth access_token to upstream via X-Forwarded-Access-Token header
-pass-authorization-header: pass OIDC IDToken to upstream via Authorization Bearer header -pass-authorization-header: pass OIDC IDToken to upstream via Authorization Bearer header
-pass-basic-auth: pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream (default true) -pass-basic-auth: pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream (default true)
@ -232,6 +253,7 @@ Usage of oauth2_proxy:
-signature-key string: GAP-Signature request signature key (algorithm:secretkey) -signature-key string: GAP-Signature request signature key (algorithm:secretkey)
-skip-auth-preflight: will skip authentication for OPTIONS requests -skip-auth-preflight: will skip authentication for OPTIONS requests
-skip-auth-regex value: bypass authentication for requests path's that match (may be given multiple times) -skip-auth-regex value: bypass authentication for requests path's that match (may be given multiple times)
-skip-oidc-discovery: bypass OIDC endpoint discovery. login-url, redeem-url and oidc-jwks-url must be configured in this case
-skip-provider-button: will skip sign-in-page to directly reach the next step: oauth/start -skip-provider-button: will skip sign-in-page to directly reach the next step: oauth/start
-ssl-insecure-skip-verify: skip validation of certificates presented when using HTTPS -ssl-insecure-skip-verify: skip validation of certificates presented when using HTTPS
-tls-cert string: path to certificate file -tls-cert string: path to certificate file

View File

@ -76,6 +76,8 @@ func main() {
flagSet.String("provider", "google", "OAuth provider") flagSet.String("provider", "google", "OAuth provider")
flagSet.String("oidc-issuer-url", "", "OpenID Connect issuer URL (ie: https://accounts.google.com)") flagSet.String("oidc-issuer-url", "", "OpenID Connect issuer URL (ie: https://accounts.google.com)")
flagSet.Bool("skip-oidc-discovery", false, "Skip OIDC discovery and use manually supplied Endpoints")
flagSet.String("oidc-jwks-url", "", "OpenID Connect JWKS URL (ie: https://www.googleapis.com/oauth2/v3/certs)")
flagSet.String("login-url", "", "Authentication endpoint") flagSet.String("login-url", "", "Authentication endpoint")
flagSet.String("redeem-url", "", "Token redemption endpoint") flagSet.String("redeem-url", "", "Token redemption endpoint")
flagSet.String("profile-url", "", "Profile access endpoint") flagSet.String("profile-url", "", "Profile access endpoint")

View File

@ -71,6 +71,8 @@ type Options struct {
// potential overrides. // potential overrides.
Provider string `flag:"provider" cfg:"provider"` Provider string `flag:"provider" cfg:"provider"`
OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url"` OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url"`
SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery"`
OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url"`
LoginURL string `flag:"login-url" cfg:"login_url"` LoginURL string `flag:"login-url" cfg:"login_url"`
RedeemURL string `flag:"redeem-url" cfg:"redeem_url"` RedeemURL string `flag:"redeem-url" cfg:"redeem_url"`
ProfileURL string `flag:"profile-url" cfg:"profile_url"` ProfileURL string `flag:"profile-url" cfg:"profile_url"`
@ -121,6 +123,7 @@ func NewOptions() *Options {
PassAuthorization: false, PassAuthorization: false,
ApprovalPrompt: "force", ApprovalPrompt: "force",
RequestLogging: true, RequestLogging: true,
SkipOIDCDiscovery: false,
RequestLoggingFormat: defaultRequestLoggingFormat, RequestLoggingFormat: defaultRequestLoggingFormat,
} }
} }
@ -161,16 +164,40 @@ func (o *Options) Validate() error {
} }
if o.OIDCIssuerURL != "" { if o.OIDCIssuerURL != "" {
// Configure discoverable provider data.
provider, err := oidc.NewProvider(context.Background(), o.OIDCIssuerURL) ctx := context.Background()
if err != nil {
return err // Construct a manual IDTokenVerifier from issuer URL & JWKS URI
// instead of metadata discovery if we enable -skip-oidc-discovery.
// In this case we need to make sure the required endpoints for
// the provider are configured.
if o.SkipOIDCDiscovery {
if o.LoginURL == "" {
msgs = append(msgs, "missing setting: login-url")
}
if o.RedeemURL == "" {
msgs = append(msgs, "missing setting: redeem-url")
}
if o.OIDCJwksURL == "" {
msgs = append(msgs, "missing setting: oidc-jwks-url")
}
keySet := oidc.NewRemoteKeySet(ctx, o.OIDCJwksURL)
o.oidcVerifier = oidc.NewVerifier(o.OIDCIssuerURL, keySet, &oidc.Config{
ClientID: o.ClientID,
})
} else {
// Configure discoverable provider data.
provider, err := oidc.NewProvider(ctx, o.OIDCIssuerURL)
if err != nil {
return err
}
o.oidcVerifier = provider.Verifier(&oidc.Config{
ClientID: o.ClientID,
})
o.LoginURL = provider.Endpoint().AuthURL
o.RedeemURL = provider.Endpoint().TokenURL
} }
o.oidcVerifier = provider.Verifier(&oidc.Config{
ClientID: o.ClientID,
})
o.LoginURL = provider.Endpoint().AuthURL
o.RedeemURL = provider.Endpoint().TokenURL
if o.Scope == "" { if o.Scope == "" {
o.Scope = "openid email profile" o.Scope = "openid email profile"
} }

View File

@ -251,3 +251,20 @@ func TestValidateCookieBadName(t *testing.T) {
assert.Equal(t, err.Error(), "Invalid configuration:\n"+ assert.Equal(t, err.Error(), "Invalid configuration:\n"+
fmt.Sprintf(" invalid cookie name: %q", o.CookieName)) fmt.Sprintf(" invalid cookie name: %q", o.CookieName))
} }
func TestSkipOIDCDiscovery(t *testing.T) {
o := testOptions()
o.Provider = "oidc"
o.OIDCIssuerURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/v2.0/"
o.SkipOIDCDiscovery = true
err := o.Validate()
assert.Equal(t, "Invalid configuration:\n"+
fmt.Sprintf(" missing setting: login-url\n missing setting: redeem-url\n missing setting: oidc-jwks-url"), err.Error())
o.LoginURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_sign_in"
o.RedeemURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_sign_in"
o.OIDCJwksURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/discovery/v2.0/keys"
assert.Equal(t, nil, o.Validate())
}