Skip to content

Commit

Permalink
fallback to env variable for oidc,oauth2 client id and secret (#3217)
Browse files Browse the repository at this point in the history
Signed-off-by: Carl Zhou <czhou@brex.com>
  • Loading branch information
czhou-brex committed Sep 5, 2024
1 parent 5dae8c8 commit d3e3756
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 34 deletions.
4 changes: 2 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,8 @@ func NewConfig() *Config {
flag.StringVar(&cfg.Oauth2RevokeTokenURL, "oauth2-revoke-token-url", "", "the url where the access and refresh tokens can be revoked when logging out")
flag.StringVar(&cfg.Oauth2TokeninfoURL, "oauth2-tokeninfo-url", "", "sets the default tokeninfo URL to query information about an incoming OAuth2 token in oauth2Tokeninfo filters")
flag.StringVar(&cfg.Oauth2SecretFile, "oauth2-secret-file", "", "sets the filename with the encryption key for the authentication cookie and grant flow state stored in secrets registry")
flag.StringVar(&cfg.Oauth2ClientID, "oauth2-client-id", "", "sets the OAuth2 client id of the current service, used to exchange the access code")
flag.StringVar(&cfg.Oauth2ClientSecret, "oauth2-client-secret", "", "sets the OAuth2 client secret associated with the oauth2-client-id, used to exchange the access code")
flag.StringVar(&cfg.Oauth2ClientID, "oauth2-client-id", "", "sets the OAuth2 client id of the current service, used to exchange the access code. Falls back to env variable OAUTH2_CLIENT_ID if value is empty.")
flag.StringVar(&cfg.Oauth2ClientSecret, "oauth2-client-secret", "", "sets the OAuth2 client secret associated with the oauth2-client-id, used to exchange the access code. Falls back to env variable OAUTH2_CLIENT_SECRET if value is empty.")
flag.StringVar(&cfg.Oauth2ClientIDFile, "oauth2-client-id-file", "", "sets the path of the file containing the OAuth2 client id of the current service, used to exchange the access code. "+
"File name may contain {host} placeholder which will be replaced by the request host")
flag.StringVar(&cfg.Oauth2ClientSecretFile, "oauth2-client-secret-file", "", "sets the path of the file containing the OAuth2 client secret associated with the oauth2-client-id, used to exchange the access code. "+
Expand Down
42 changes: 21 additions & 21 deletions docs/reference/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -1736,25 +1736,25 @@ single_page_app:

Skipper arguments:

| Argument | Required? | Description |
| -------- | --------- | ----------- |
| `-enable-oauth2-grant-flow` | **yes** | toggle flag to enable the `oauthGrant()` filter. Must be set if you use the filter in routes. Example: `-enable-oauth2-grant-flow` |
| `-oauth2-auth-url` | **yes** | URL of the OAuth2 provider's authorize endpoint. Example: `-oauth2-auth-url=https://identity.example.com/oauth2/authorize` |
| `-oauth2-token-url` | **yes** | URL of the OAuth2 provider's token endpoint. Example: `-oauth2-token-url=https://identity.example.com/oauth2/token` |
| `-oauth2-tokeninfo-url` | **yes** | URL of the OAuth2 provider's tokeninfo endpoint. Example: `-oauth2-tokeninfo-url=https://identity.example.com/oauth2/tokeninfo` |
| `-oauth2-secret-file` | **yes** | path to the file containing the secret for encrypting and decrypting the grant token cookie (the secret can be anything). Example: `-oauth2-secret-file=/path/to/secret` |
| `-oauth2-client-id-file` | conditional | path to the file containing the OAuth2 client ID. Required if you have not set `-oauth2-client-id`. Example: `-oauth2-client-id-file=/path/to/client_id` |
| `-oauth2-client-secret-file` | conditional | path to the file containing the OAuth2 client secret. Required if you have not set `-oauth2-client-secret`. Example: `-oauth2-client-secret-file=/path/to/client_secret` |
| `-oauth2-client-id` | conditional | OAuth2 client ID for authenticating with your OAuth2 provider. Required if you have not set `-oauth2-client-id-file`. Example: `-oauth2-client-id=myclientid` |
| `-oauth2-client-secret` | conditional | OAuth2 client secret for authenticating with your OAuth2 provider. Required if you have not set `-oauth2-client-secret-file`. Example: `-oauth2-client-secret=myclientsecret` |
| `-credentials-update-interval` | no | the time interval for updating client id and client secret from files. Example: `-credentials-update-interval=30s` |
| `-oauth2-access-token-header-name` | no | the name of the request header where the user's bearer token should be set. Example: `-oauth2-access-token-header-name=X-Grant-Authorization` |
| `-oauth2-grant-tokeninfo-keys` | no | comma separated list of keys to preserve in OAuth2 Grant Flow tokeninfo. Default: empty, preserves all tokeninfo keys. Example: `-oauth2-grant-tokeninfo-keys=scope,realm,expires_in` |
| `-oauth2-auth-url-parameters` | no | any additional URL query parameters to set for the OAuth2 provider's authorize and token endpoint calls. Example: `-oauth2-auth-url-parameters=key1=foo,key2=bar` |
| `-oauth2-callback-path` | no | path of the Skipper route containing the `grantCallback()` filter for accepting an authorization code and using it to get an access token. Example: `-oauth2-callback-path=/oauth/callback` |
| `-oauth2-token-cookie-name` | no | the name of the cookie where the access tokens should be stored in encrypted form. Default: `oauth-grant`. Example: `-oauth2-token-cookie-name=SESSION` |
| `-oauth2-token-cookie-remove-subdomains` | no | the number of subdomains to remove from the callback request hostname to obtain token cookie domain. Default: `1`. Example: `-oauth2-token-cookie-remove-subdomains=0` |
| `-oauth2-grant-insecure` | no | omits `Secure` attribute of the token cookie and uses `http` scheme for callback url. Default: `false` |
| Argument | Required? | Description |
| -------- | --------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-enable-oauth2-grant-flow` | **yes** | toggle flag to enable the `oauthGrant()` filter. Must be set if you use the filter in routes. Example: `-enable-oauth2-grant-flow` |
| `-oauth2-auth-url` | **yes** | URL of the OAuth2 provider's authorize endpoint. Example: `-oauth2-auth-url=https://identity.example.com/oauth2/authorize` |
| `-oauth2-token-url` | **yes** | URL of the OAuth2 provider's token endpoint. Example: `-oauth2-token-url=https://identity.example.com/oauth2/token` |
| `-oauth2-tokeninfo-url` | **yes** | URL of the OAuth2 provider's tokeninfo endpoint. Example: `-oauth2-tokeninfo-url=https://identity.example.com/oauth2/tokeninfo` |
| `-oauth2-secret-file` | **yes** | path to the file containing the secret for encrypting and decrypting the grant token cookie (the secret can be anything). Example: `-oauth2-secret-file=/path/to/secret` |
| `-oauth2-client-id-file` | conditional | path to the file containing the OAuth2 client ID. Required if you have not set `-oauth2-client-id`. Example: `-oauth2-client-id-file=/path/to/client_id` |
| `-oauth2-client-secret-file` | conditional | path to the file containing the OAuth2 client secret. Required if you have not set `-oauth2-client-secret`. Example: `-oauth2-client-secret-file=/path/to/client_secret` |
| `-oauth2-client-id` | conditional | OAuth2 client ID for authenticating with your OAuth2 provider. Required if you have not set `-oauth2-client-id-file` or `OAUTH2_CLIENT_ID` env variable. Example: `-oauth2-client-id=myclientid` |
| `-oauth2-client-secret` | conditional | OAuth2 client secret for authenticating with your OAuth2 provider. Required if you have not set `-oauth2-client-secret-file` or `OAUTH2_CLIENT_SECRET` env variable. Example: `-oauth2-client-secret=myclientsecret` |
| `-credentials-update-interval` | no | the time interval for updating client id and client secret from files. Example: `-credentials-update-interval=30s` |
| `-oauth2-access-token-header-name` | no | the name of the request header where the user's bearer token should be set. Example: `-oauth2-access-token-header-name=X-Grant-Authorization` |
| `-oauth2-grant-tokeninfo-keys` | no | comma separated list of keys to preserve in OAuth2 Grant Flow tokeninfo. Default: empty, preserves all tokeninfo keys. Example: `-oauth2-grant-tokeninfo-keys=scope,realm,expires_in` |
| `-oauth2-auth-url-parameters` | no | any additional URL query parameters to set for the OAuth2 provider's authorize and token endpoint calls. Example: `-oauth2-auth-url-parameters=key1=foo,key2=bar` |
| `-oauth2-callback-path` | no | path of the Skipper route containing the `grantCallback()` filter for accepting an authorization code and using it to get an access token. Example: `-oauth2-callback-path=/oauth/callback` |
| `-oauth2-token-cookie-name` | no | the name of the cookie where the access tokens should be stored in encrypted form. Default: `oauth-grant`. Example: `-oauth2-token-cookie-name=SESSION` |
| `-oauth2-token-cookie-remove-subdomains` | no | the number of subdomains to remove from the callback request hostname to obtain token cookie domain. Default: `1`. Example: `-oauth2-token-cookie-remove-subdomains=0` |
| `-oauth2-grant-insecure` | no | omits `Secure` attribute of the token cookie and uses `http` scheme for callback url. Default: `false` |

#### grantCallback

Expand Down Expand Up @@ -1835,8 +1835,8 @@ oauthOidcUserInfo("https://oidc-provider.example.com", "client_id", "client_secr
The filter needs the following parameters:

* **OpenID Connect Provider URL** For example Google OpenID Connect is available on `https://accounts.google.com`
* **Client ID** This value is obtained from the provider upon registration of the application.
* **Client Secret** Also obtained from the provider
* **Client ID** This value is obtained from the provider upon registration of the application. Falls back to```OIDC_CLIENT_ID``` env variable for empty value.
* **Client Secret** Also obtained from the provider. Falls back to ```OIDC_CLIENT_SECRET``` env variable for empty value.
* **Callback URL** The entire path to the callback from the provider on which the token will be received.
It can be any value which is a subpath on which the filter is applied.
* **Scopes** The OpenID scopes separated by spaces which need to be specified when requesting the token from the provider.
Expand Down
26 changes: 19 additions & 7 deletions filters/auth/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,12 @@ const (
)

type OidcOptions struct {
MaxIdleConns int
CookieValidity time.Duration
Timeout time.Duration
Tracer opentracing.Tracer
MaxIdleConns int
CookieValidity time.Duration
Timeout time.Duration
Tracer opentracing.Tracer
OidcClientId string
OidcClientSecret string
}

type (
Expand Down Expand Up @@ -242,19 +244,29 @@ func (s *tokenOidcSpec) CreateFilter(args []interface{}) (filters.Filter, error)
validity = defaultCookieValidity
}

oidcClientId := sargs[paramClientID]
if oidcClientId == "" {
oidcClientId = s.options.OidcClientId
}

oidcClientSecret := sargs[paramClientSecret]
if oidcClientSecret == "" {
oidcClientSecret = s.options.OidcClientSecret
}

f := &tokenOidcFilter{
typ: s.typ,
redirectPath: redirectURL.Path,
config: &oauth2.Config{
ClientID: sargs[paramClientID],
ClientSecret: sargs[paramClientSecret],
ClientID: oidcClientId,
ClientSecret: oidcClientSecret,
RedirectURL: sargs[paramCallbackURL], // self endpoint
Endpoint: provider.Endpoint(),
Scopes: []string{oidc.ScopeOpenID}, // mandatory scope by spec
},
provider: provider,
verifier: provider.Verifier(&oidc.Config{
ClientID: sargs[paramClientID],
ClientID: oidcClientId,
}),
validity: validity,
cookiename: generatedCookieName,
Expand Down
18 changes: 14 additions & 4 deletions skipper.go
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,13 @@ func (o *Options) OAuthGrantOptions() *auth.OAuthConfig {
oauthConfig.TokeninfoURL = o.OAuthTokeninfoURL
oauthConfig.SecretFile = o.OAuth2SecretFile
oauthConfig.ClientID = o.OAuth2ClientID
if oauthConfig.ClientID == "" {
oauthConfig.ClientID, _ = os.LookupEnv("OAUTH2_CLIENT_ID")
}
oauthConfig.ClientSecret = o.OAuth2ClientSecret
if oauthConfig.ClientSecret == "" {
oauthConfig.ClientSecret, _ = os.LookupEnv("OAUTH2_CLIENT_SECRET")
}
oauthConfig.ClientIDFile = o.OAuth2ClientIDFile
oauthConfig.ClientSecretFile = o.OAuth2ClientSecretFile
oauthConfig.CallbackPath = o.OAuth2CallbackPath
Expand Down Expand Up @@ -1672,11 +1678,15 @@ func run(o Options, sig chan os.Signal, idleConnsCH chan struct{}) error {
)

if o.OIDCSecretsFile != "" {
oidcClientId, _ := os.LookupEnv("OIDC_CLIENT_ID")
oidcClientSecret, _ := os.LookupEnv("OIDC_CLIENT_SECRET")
opts := auth.OidcOptions{
CookieValidity: o.OIDCCookieValidity,
Timeout: o.OIDCDistributedClaimsTimeout,
MaxIdleConns: o.IdleConnectionsPerHost,
Tracer: tracer,
CookieValidity: o.OIDCCookieValidity,
Timeout: o.OIDCDistributedClaimsTimeout,
MaxIdleConns: o.IdleConnectionsPerHost,
Tracer: tracer,
OidcClientId: oidcClientId,
OidcClientSecret: oidcClientSecret,
}

o.CustomFilters = append(o.CustomFilters,
Expand Down

0 comments on commit d3e3756

Please sign in to comment.