git.iko.soy/typeable/oauth2-proxy
on master help sign in
Allow the OIDC issuer verification to be skipped if desired. (#467)

* Allow the OIDC issuer verification to be skipped if desired. * Remove stale warning * Add CHANGELOG entry Co-authored-by: Henry Jenkins <henry@henryjenkins.name> Co-authored-by: Dan Bond <pm@danbond.io>

commitc6294c40a384156e5c356df705b66ee56a8ddb63 authorChristopher Kohnert <58753523+chkohner@users.noreply.github.com> dateSun 19 Apr 2020, 04:19 (6 years ago) parent6fa3d6c
4 files changed+61−16
CHANGELOG.md+1 docs/configuration/configuration.md+1 main.go+1 options.go+58−16
CHANGELOG.md+1
@@ -22,6 +22,7 @@
2222- [#486](https://github.com/oauth2-proxy/oauth2-proxy/pull/486) Add new linters (@johejo)
2323- [#440](https://github.com/oauth2-proxy/oauth2-proxy/pull/440) Switch Azure AD Graph API to Microsoft Graph API (@johejo)
2424- [#453](https://github.com/oauth2-proxy/oauth2-proxy/pull/453) Prevent browser caching during auth flow (@johejo)
25+- [#467](https://github.com/oauth2-proxy/oauth2-proxy/pull/467) Allow OIDC issuer verification to be skipped (@chkohner)
2526- [#481](https://github.com/oauth2-proxy/oauth2-proxy/pull/481) Update Okta docs (@trevorbox)
2627- [#474](https://github.com/oauth2-proxy/oauth2-proxy/pull/474) Always log hasMember request error object (@jbielick)
2728- [#468](https://github.com/oauth2-proxy/oauth2-proxy/pull/468) Implement graceful shutdown and propagate request context (@johejo)
docs/configuration/configuration.md+1
@@ -71,6 +71,7 @@ An example [oauth2-proxy.cfg]({{ site.gitweb }}/contrib/oauth2-proxy.cfg.example
7171| `-jwt-key-file` | string | path to the private key file in PEM format used to sign the JWT so that you can say something like `-jwt-key-file=/etc/ssl/private/jwt_signing_key.pem`: required by login.gov | |
7272| `-login-url` | string | Authentication endpoint | |
7373| `-insecure-oidc-allow-unverified-email` | bool | don't fail if an email address in an id_token is not verified | false |
74+| `-insecure-oidc-skip-issuer-verification` | bool | allow the OIDC issuer URL to differ from the expected (currently required for Azure multi-tenant compatibility) | false |
7475| `-oidc-issuer-url` | string | the OpenID Connect issuer URL. ie: `"https://accounts.google.com"` | |
7576| `-oidc-jwks-url` | string | OIDC JWKS URI for token verification; required if OIDC discovery is disabled | |
7677| `-pass-access-token` | bool | pass OAuth access_token to upstream via X-Forwarded-Access-Token header | false |
main.go+1
@@ -128,6 +128,7 @@ func main() {
128128 flagSet.String("provider-display-name", "", "Provider display name")
129129 flagSet.String("oidc-issuer-url", "", "OpenID Connect issuer URL (ie: https://accounts.google.com)")
130130 flagSet.Bool("insecure-oidc-allow-unverified-email", false, "Don't fail if an email address in an id_token is not verified")
131+ flagSet.Bool("insecure-oidc-skip-issuer-verification", false, "Do not verify if issuer matches OIDC discovery URL")
131132 flagSet.Bool("skip-oidc-discovery", false, "Skip OIDC discovery and use manually supplied Endpoints")
132133 flagSet.String("oidc-jwks-url", "", "OpenID Connect JWKS URL (ie: https://www.googleapis.com/oauth2/v3/certs)")
133134 flagSet.String("login-url", "", "Authentication endpoint")
options.go+58−16
@@ -22,6 +22,7 @@ import (
2222 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
2323 "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
2424 "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
25+ "github.com/oauth2-proxy/oauth2-proxy/pkg/requests"
2526 "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions"
2627 "github.com/oauth2-proxy/oauth2-proxy/providers"
2728 "gopkg.in/natefinch/lumberjack.v2"
@@ -91,20 +92,21 @@ type Options struct {
9192
9293 // These options allow for other providers besides Google, with
9394 // potential overrides.
94− Provider string `flag:"provider" cfg:"provider" env:"OAUTH2_PROXY_PROVIDER"`
95− ProviderName string `flag:"provider-display-name" cfg:"provider_display_name" env:"OAUTH2_PROXY_PROVIDER_DISPLAY_NAME"`
96− OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url" env:"OAUTH2_PROXY_OIDC_ISSUER_URL"`
97− InsecureOIDCAllowUnverifiedEmail bool `flag:"insecure-oidc-allow-unverified-email" cfg:"insecure_oidc_allow_unverified_email" env:"OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL"`
98− SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery" env:"OAUTH2_PROXY_SKIP_OIDC_DISCOVERY"`
99− OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url" env:"OAUTH2_PROXY_OIDC_JWKS_URL"`
100− LoginURL string `flag:"login-url" cfg:"login_url" env:"OAUTH2_PROXY_LOGIN_URL"`
101− RedeemURL string `flag:"redeem-url" cfg:"redeem_url" env:"OAUTH2_PROXY_REDEEM_URL"`
102− ProfileURL string `flag:"profile-url" cfg:"profile_url" env:"OAUTH2_PROXY_PROFILE_URL"`
103− ProtectedResource string `flag:"resource" cfg:"resource" env:"OAUTH2_PROXY_RESOURCE"`
104− ValidateURL string `flag:"validate-url" cfg:"validate_url" env:"OAUTH2_PROXY_VALIDATE_URL"`
105− Scope string `flag:"scope" cfg:"scope" env:"OAUTH2_PROXY_SCOPE"`
106− Prompt string `flag:"prompt" cfg:"prompt" env:"OAUTH2_PROXY_PROMPT"`
107− ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt" env:"OAUTH2_PROXY_APPROVAL_PROMPT"` // Deprecated by OIDC 1.0
95+ Provider string `flag:"provider" cfg:"provider" env:"OAUTH2_PROXY_PROVIDER"`
96+ ProviderName string `flag:"provider-display-name" cfg:"provider_display_name" env:"OAUTH2_PROXY_PROVIDER_DISPLAY_NAME"`
97+ OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url" env:"OAUTH2_PROXY_OIDC_ISSUER_URL"`
98+ InsecureOIDCAllowUnverifiedEmail bool `flag:"insecure-oidc-allow-unverified-email" cfg:"insecure_oidc_allow_unverified_email" env:"OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL"`
99+ InsecureOIDCSkipIssuerVerification bool `flag:"insecure-oidc-skip-issuer-verification" cfg:"insecure_oidc_skip_issuer_verification" env:"OAUTH2_PROXY_INSECURE_OIDC_SKIP_ISSUER_VERIFICATION"`
100+ SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery" env:"OAUTH2_PROXY_SKIP_OIDC_DISCOVERY"`
101+ OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url" env:"OAUTH2_PROXY_OIDC_JWKS_URL"`
102+ LoginURL string `flag:"login-url" cfg:"login_url" env:"OAUTH2_PROXY_LOGIN_URL"`
103+ RedeemURL string `flag:"redeem-url" cfg:"redeem_url" env:"OAUTH2_PROXY_REDEEM_URL"`
104+ ProfileURL string `flag:"profile-url" cfg:"profile_url" env:"OAUTH2_PROXY_PROFILE_URL"`
105+ ProtectedResource string `flag:"resource" cfg:"resource" env:"OAUTH2_PROXY_RESOURCE"`
106+ ValidateURL string `flag:"validate-url" cfg:"validate_url" env:"OAUTH2_PROXY_VALIDATE_URL"`
107+ Scope string `flag:"scope" cfg:"scope" env:"OAUTH2_PROXY_SCOPE"`
108+ Prompt string `flag:"prompt" cfg:"prompt" env:"OAUTH2_PROXY_PROMPT"`
109+ ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt" env:"OAUTH2_PROXY_APPROVAL_PROMPT"` // Deprecated by OIDC 1.0
108110
109111 // Configuration values for logging
110112 LoggingFilename string `flag:"logging-filename" cfg:"logging_filename" env:"OAUTH2_PROXY_LOGGING_FILENAME"`
@@ -254,6 +256,44 @@ func (o *Options) Validate() error {
254256
255257 ctx := context.Background()
256258
259+ if o.InsecureOIDCSkipIssuerVerification && !o.SkipOIDCDiscovery {
260+ // go-oidc doesn't let us pass bypass the issuer check this in the oidc.NewProvider call
261+ // (which uses discovery to get the URLs), so we'll do a quick check ourselves and if
262+ // we get the URLs, we'll just use the non-discovery path.
263+
264+ logger.Printf("Performing OIDC Discovery...")
265+
266+ if req, err := http.NewRequest("GET", strings.TrimSuffix(o.OIDCIssuerURL, "/")+"/.well-known/openid-configuration", nil); err == nil {
267+ if body, err := requests.Request(req); err == nil {
268+
269+ // Prefer manually configured URLs. It's a bit unclear
270+ // why you'd be doing discovery and also providing the URLs
271+ // explicitly though...
272+ if o.LoginURL == "" {
273+ o.LoginURL = body.Get("authorization_endpoint").MustString()
274+ }
275+
276+ if o.RedeemURL == "" {
277+ o.RedeemURL = body.Get("token_endpoint").MustString()
278+ }
279+
280+ if o.OIDCJwksURL == "" {
281+ o.OIDCJwksURL = body.Get("jwks_uri").MustString()
282+ }
283+
284+ if o.ProfileURL == "" {
285+ o.ProfileURL = body.Get("userinfo_endpoint").MustString()
286+ }
287+
288+ o.SkipOIDCDiscovery = true
289+ } else {
290+ logger.Printf("error: failed to discover OIDC configuration: %v", err)
291+ }
292+ } else {
293+ logger.Printf("error: failed parsing OIDC discovery URL: %v", err)
294+ }
295+ }
296+
257297 // Construct a manual IDTokenVerifier from issuer URL & JWKS URI
258298 // instead of metadata discovery if we enable -skip-oidc-discovery.
259299 // In this case we need to make sure the required endpoints for
@@ -270,7 +310,8 @@ func (o *Options) Validate() error {
270310 }
271311 keySet := oidc.NewRemoteKeySet(ctx, o.OIDCJwksURL)
272312 o.oidcVerifier = oidc.NewVerifier(o.OIDCIssuerURL, keySet, &oidc.Config{
273− ClientID: o.ClientID,
313+ ClientID: o.ClientID,
314+ SkipIssuerCheck: o.InsecureOIDCSkipIssuerVerification,
274315 })
275316 } else {
276317 // Configure discoverable provider data.
@@ -279,7 +320,8 @@ func (o *Options) Validate() error {
279320 return err
280321 }
281322 o.oidcVerifier = provider.Verifier(&oidc.Config{
282− ClientID: o.ClientID,
323+ ClientID: o.ClientID,
324+ SkipIssuerCheck: o.InsecureOIDCSkipIssuerVerification,
283325 })
284326
285327 o.LoginURL = provider.Endpoint().AuthURL