From 018a25be04dfcab9fae3ee12ea6710bc52d578ad Mon Sep 17 00:00:00 2001 From: Daryl Finlay Date: Mon, 20 May 2019 12:32:10 +0100 Subject: [PATCH 1/4] Create option to skip verified email check in OIDC provider --- docs/configuration/configuration.md | 1 + main.go | 1 + options.go | 69 +++++++++++++++-------------- providers/oidc.go | 5 ++- 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index b3c38b2..d7cdcd9 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -63,6 +63,7 @@ Usage of oauth2_proxy: -jwt-key string: private key in PEM format used to sign JWT, so that you can say something like -jwt-key="${OAUTH2_PROXY_JWT_KEY}": required by login.gov -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 -login-url string: Authentication endpoint + -oidc-allow-unverified-email: don't fail if an email address in an id_token is not verified -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 diff --git a/main.go b/main.go index 6884462..4187257 100644 --- a/main.go +++ b/main.go @@ -104,6 +104,7 @@ func main() { flagSet.String("provider", "google", "OAuth provider") flagSet.String("oidc-issuer-url", "", "OpenID Connect issuer URL (ie: https://accounts.google.com)") + flagSet.Bool("oidc-allow-unverified-email", false, "Don't fail if an email address in an id_token is not verified") 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") diff --git a/options.go b/options.go index 4a41ebe..3cd6e3a 100644 --- a/options.go +++ b/options.go @@ -79,17 +79,18 @@ type Options struct { // These options allow for other providers besides Google, with // potential overrides. - Provider string `flag:"provider" cfg:"provider" env:"OAUTH2_PROXY_PROVIDER"` - OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url" env:"OAUTH2_PROXY_OIDC_ISSUER_URL"` - SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery" env:"OAUTH2_SKIP_OIDC_DISCOVERY"` - OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url" env:"OAUTH2_OIDC_JWKS_URL"` - LoginURL string `flag:"login-url" cfg:"login_url" env:"OAUTH2_PROXY_LOGIN_URL"` - RedeemURL string `flag:"redeem-url" cfg:"redeem_url" env:"OAUTH2_PROXY_REDEEM_URL"` - ProfileURL string `flag:"profile-url" cfg:"profile_url" env:"OAUTH2_PROXY_PROFILE_URL"` - ProtectedResource string `flag:"resource" cfg:"resource" env:"OAUTH2_PROXY_RESOURCE"` - ValidateURL string `flag:"validate-url" cfg:"validate_url" env:"OAUTH2_PROXY_VALIDATE_URL"` - Scope string `flag:"scope" cfg:"scope" env:"OAUTH2_PROXY_SCOPE"` - ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt" env:"OAUTH2_PROXY_APPROVAL_PROMPT"` + Provider string `flag:"provider" cfg:"provider" env:"OAUTH2_PROXY_PROVIDER"` + OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url" env:"OAUTH2_PROXY_OIDC_ISSUER_URL"` + OIDCAllowUnverifiedEmail bool `flag:"oidc-allow-unverified-email" cfg:"oidc_allow_unverified_email" env:"OAUTH2_PROXY_OIDC_ALLOW_UNVERIFIED_EMAIL"` + SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery" env:"OAUTH2_SKIP_OIDC_DISCOVERY"` + OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url" env:"OAUTH2_OIDC_JWKS_URL"` + LoginURL string `flag:"login-url" cfg:"login_url" env:"OAUTH2_PROXY_LOGIN_URL"` + RedeemURL string `flag:"redeem-url" cfg:"redeem_url" env:"OAUTH2_PROXY_REDEEM_URL"` + ProfileURL string `flag:"profile-url" cfg:"profile_url" env:"OAUTH2_PROXY_PROFILE_URL"` + ProtectedResource string `flag:"resource" cfg:"resource" env:"OAUTH2_PROXY_RESOURCE"` + ValidateURL string `flag:"validate-url" cfg:"validate_url" env:"OAUTH2_PROXY_VALIDATE_URL"` + Scope string `flag:"scope" cfg:"scope" env:"OAUTH2_PROXY_SCOPE"` + ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt" env:"OAUTH2_PROXY_APPROVAL_PROMPT"` // Configuration values for logging LoggingFilename string `flag:"logging-filename" cfg:"logging_filename" env:"OAUTH2_LOGGING_FILENAME"` @@ -147,28 +148,29 @@ func NewOptions() *Options { SessionOptions: options.SessionOptions{ Type: "cookie", }, - SetXAuthRequest: false, - SkipAuthPreflight: false, - PassBasicAuth: true, - PassUserHeaders: true, - PassAccessToken: false, - PassHostHeader: true, - SetAuthorization: false, - PassAuthorization: false, - ApprovalPrompt: "force", - SkipOIDCDiscovery: false, - LoggingFilename: "", - LoggingMaxSize: 100, - LoggingMaxAge: 7, - LoggingMaxBackups: 0, - LoggingLocalTime: true, - LoggingCompress: false, - StandardLogging: true, - StandardLoggingFormat: logger.DefaultStandardLoggingFormat, - RequestLogging: true, - RequestLoggingFormat: logger.DefaultRequestLoggingFormat, - AuthLogging: true, - AuthLoggingFormat: logger.DefaultAuthLoggingFormat, + SetXAuthRequest: false, + SkipAuthPreflight: false, + PassBasicAuth: true, + PassUserHeaders: true, + PassAccessToken: false, + PassHostHeader: true, + SetAuthorization: false, + PassAuthorization: false, + ApprovalPrompt: "force", + OIDCAllowUnverifiedEmail: false, + SkipOIDCDiscovery: false, + LoggingFilename: "", + LoggingMaxSize: 100, + LoggingMaxAge: 7, + LoggingMaxBackups: 0, + LoggingLocalTime: true, + LoggingCompress: false, + StandardLogging: true, + StandardLoggingFormat: logger.DefaultStandardLoggingFormat, + RequestLogging: true, + RequestLoggingFormat: logger.DefaultRequestLoggingFormat, + AuthLogging: true, + AuthLoggingFormat: logger.DefaultAuthLoggingFormat, } } @@ -397,6 +399,7 @@ func parseProviderInfo(o *Options, msgs []string) []string { } } case *providers.OIDCProvider: + p.AllowUnverifiedEmail = o.OIDCAllowUnverifiedEmail if o.oidcVerifier == nil { msgs = append(msgs, "oidc provider requires an oidc issuer URL") } else { diff --git a/providers/oidc.go b/providers/oidc.go index b0d2dda..86a58f6 100644 --- a/providers/oidc.go +++ b/providers/oidc.go @@ -14,7 +14,8 @@ import ( type OIDCProvider struct { *ProviderData - Verifier *oidc.IDTokenVerifier + Verifier *oidc.IDTokenVerifier + AllowUnverifiedEmail bool } // NewOIDCProvider initiates a new OIDCProvider @@ -119,7 +120,7 @@ func (p *OIDCProvider) createSessionState(ctx context.Context, token *oauth2.Tok // TODO: Try getting email from /userinfo before falling back to Subject claims.Email = claims.Subject } - if claims.Verified != nil && !*claims.Verified { + if !p.AllowUnverifiedEmail && claims.Verified != nil && !*claims.Verified { return nil, fmt.Errorf("email in id_token (%s) isn't verified", claims.Email) } From 39b6a42d43b96cf41ee110406c4dd1b7ffc565b7 Mon Sep 17 00:00:00 2001 From: Daryl Finlay Date: Thu, 11 Jul 2019 15:18:36 +0100 Subject: [PATCH 2/4] Mark option to skip verified email check as insecure --- options.go | 72 +++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/options.go b/options.go index 3cd6e3a..7436d85 100644 --- a/options.go +++ b/options.go @@ -79,18 +79,18 @@ type Options struct { // These options allow for other providers besides Google, with // potential overrides. - Provider string `flag:"provider" cfg:"provider" env:"OAUTH2_PROXY_PROVIDER"` - OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url" env:"OAUTH2_PROXY_OIDC_ISSUER_URL"` - OIDCAllowUnverifiedEmail bool `flag:"oidc-allow-unverified-email" cfg:"oidc_allow_unverified_email" env:"OAUTH2_PROXY_OIDC_ALLOW_UNVERIFIED_EMAIL"` - SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery" env:"OAUTH2_SKIP_OIDC_DISCOVERY"` - OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url" env:"OAUTH2_OIDC_JWKS_URL"` - LoginURL string `flag:"login-url" cfg:"login_url" env:"OAUTH2_PROXY_LOGIN_URL"` - RedeemURL string `flag:"redeem-url" cfg:"redeem_url" env:"OAUTH2_PROXY_REDEEM_URL"` - ProfileURL string `flag:"profile-url" cfg:"profile_url" env:"OAUTH2_PROXY_PROFILE_URL"` - ProtectedResource string `flag:"resource" cfg:"resource" env:"OAUTH2_PROXY_RESOURCE"` - ValidateURL string `flag:"validate-url" cfg:"validate_url" env:"OAUTH2_PROXY_VALIDATE_URL"` - Scope string `flag:"scope" cfg:"scope" env:"OAUTH2_PROXY_SCOPE"` - ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt" env:"OAUTH2_PROXY_APPROVAL_PROMPT"` + Provider string `flag:"provider" cfg:"provider" env:"OAUTH2_PROXY_PROVIDER"` + OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url" env:"OAUTH2_PROXY_OIDC_ISSUER_URL"` + InsecureOIDCAllowUnverifiedEmail bool `flag:"insecure-oidc-allow-unverified-email" cfg:"insecure_oidc_allow_unverified_email" env:"OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL"` + SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery" env:"OAUTH2_SKIP_OIDC_DISCOVERY"` + OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url" env:"OAUTH2_OIDC_JWKS_URL"` + LoginURL string `flag:"login-url" cfg:"login_url" env:"OAUTH2_PROXY_LOGIN_URL"` + RedeemURL string `flag:"redeem-url" cfg:"redeem_url" env:"OAUTH2_PROXY_REDEEM_URL"` + ProfileURL string `flag:"profile-url" cfg:"profile_url" env:"OAUTH2_PROXY_PROFILE_URL"` + ProtectedResource string `flag:"resource" cfg:"resource" env:"OAUTH2_PROXY_RESOURCE"` + ValidateURL string `flag:"validate-url" cfg:"validate_url" env:"OAUTH2_PROXY_VALIDATE_URL"` + Scope string `flag:"scope" cfg:"scope" env:"OAUTH2_PROXY_SCOPE"` + ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt" env:"OAUTH2_PROXY_APPROVAL_PROMPT"` // Configuration values for logging LoggingFilename string `flag:"logging-filename" cfg:"logging_filename" env:"OAUTH2_LOGGING_FILENAME"` @@ -148,29 +148,29 @@ func NewOptions() *Options { SessionOptions: options.SessionOptions{ Type: "cookie", }, - SetXAuthRequest: false, - SkipAuthPreflight: false, - PassBasicAuth: true, - PassUserHeaders: true, - PassAccessToken: false, - PassHostHeader: true, - SetAuthorization: false, - PassAuthorization: false, - ApprovalPrompt: "force", - OIDCAllowUnverifiedEmail: false, - SkipOIDCDiscovery: false, - LoggingFilename: "", - LoggingMaxSize: 100, - LoggingMaxAge: 7, - LoggingMaxBackups: 0, - LoggingLocalTime: true, - LoggingCompress: false, - StandardLogging: true, - StandardLoggingFormat: logger.DefaultStandardLoggingFormat, - RequestLogging: true, - RequestLoggingFormat: logger.DefaultRequestLoggingFormat, - AuthLogging: true, - AuthLoggingFormat: logger.DefaultAuthLoggingFormat, + SetXAuthRequest: false, + SkipAuthPreflight: false, + PassBasicAuth: true, + PassUserHeaders: true, + PassAccessToken: false, + PassHostHeader: true, + SetAuthorization: false, + PassAuthorization: false, + ApprovalPrompt: "force", + InsecureOIDCAllowUnverifiedEmail: false, + SkipOIDCDiscovery: false, + LoggingFilename: "", + LoggingMaxSize: 100, + LoggingMaxAge: 7, + LoggingMaxBackups: 0, + LoggingLocalTime: true, + LoggingCompress: false, + StandardLogging: true, + StandardLoggingFormat: logger.DefaultStandardLoggingFormat, + RequestLogging: true, + RequestLoggingFormat: logger.DefaultRequestLoggingFormat, + AuthLogging: true, + AuthLoggingFormat: logger.DefaultAuthLoggingFormat, } } @@ -399,7 +399,7 @@ func parseProviderInfo(o *Options, msgs []string) []string { } } case *providers.OIDCProvider: - p.AllowUnverifiedEmail = o.OIDCAllowUnverifiedEmail + p.AllowUnverifiedEmail = o.InsecureOIDCAllowUnverifiedEmail if o.oidcVerifier == nil { msgs = append(msgs, "oidc provider requires an oidc issuer URL") } else { From 776d063b987f950bb238680cc6e52174dbd4a7e4 Mon Sep 17 00:00:00 2001 From: Daryl Finlay Date: Thu, 11 Jul 2019 15:23:24 +0100 Subject: [PATCH 3/4] Update changelog to include --insecure-oidc-allow-unverified-email --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8e2212..ed9d4df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ - Google Group membership is additionally checked via email address, allowing users outside a GSuite domain to be authorized. - [#195](https://github.com/pusher/outh2_proxy/pull/195) Add `-banner` flag for overriding the banner line that is displayed (@steakunderscore) - [#198](https://github.com/pusher/outh2_proxy/pull/198) Switch from gometalinter to golangci-lint (@steakunderscore) +- [#159](https://github.com/pusher/oauth2_proxy/pull/159) Add option to skip the OIDC provider verified email check: `--insecure-oidc-allow-unverified-email` # v3.2.0 From 9823971b7d9e7e5f24a988b488c8a0955dbafaa8 Mon Sep 17 00:00:00 2001 From: Daryl Finlay Date: Thu, 11 Jul 2019 15:58:31 +0100 Subject: [PATCH 4/4] Make insecure-oidc-allow-unverified-email configuration usage consistent --- docs/configuration/configuration.md | 2 +- main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index d7cdcd9..016fe3a 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -63,7 +63,7 @@ Usage of oauth2_proxy: -jwt-key string: private key in PEM format used to sign JWT, so that you can say something like -jwt-key="${OAUTH2_PROXY_JWT_KEY}": required by login.gov -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 -login-url string: Authentication endpoint - -oidc-allow-unverified-email: don't fail if an email address in an id_token is not verified + -insecure-oidc-allow-unverified-email: don't fail if an email address in an id_token is not verified -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 diff --git a/main.go b/main.go index 4187257..f82205d 100644 --- a/main.go +++ b/main.go @@ -104,7 +104,7 @@ func main() { flagSet.String("provider", "google", "OAuth provider") flagSet.String("oidc-issuer-url", "", "OpenID Connect issuer URL (ie: https://accounts.google.com)") - flagSet.Bool("oidc-allow-unverified-email", false, "Don't fail if an email address in an id_token is not verified") + flagSet.Bool("insecure-oidc-allow-unverified-email", false, "Don't fail if an email address in an id_token is not verified") 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")