All services using sso_proxy
are configured in a upstream_config.yml
file.
All config values can be templated from environmental variables with the prefix SSO_CONFIG_
.
For example, the following config would have the following environment variables configed:, SSO_CONFIG_CLUSTER
, SSO_CONFIG_ROOT_DOMAIN
.
- service: example_service
default:
from: example-service.sso.{{cluster}}.{{root_domain}}
to: example-service.{{cluster}}.{{root_domain}}
options:
allowed_groups:
- sso-test-group-1@example.com
- sso-test-group-2@example.com
skip_auth_regex:
- ^\/github-webhook\/$
header_overrides:
X-Frame-Options: DENY
inject_request_headers:
Authorization: Basic dXNlcjpwYXNzd29yZA==
prod:
from: example-service.example.com
- service is the name of the service being protected
- default is the default specifier used to set cluster settings for all clusters
- from is the domain that will be used to access the service
- to is the cname of the proxied service (this tells sso proxy where to proxy requests that come in on the from field)
- type declares the type of route to use, right now there is just simple and rewrite.
- options are a set of options that can be added to your configuration.
- allowed groups optional list of authorized google groups that can access the service. If not specified, anyone within an email domain is allowed to access the service. Note: We do not support nested group authentication at this time. Groups must be made up of email addresses associated with individual's accounts. See #133.
- allowed_email_domains optional list of authorized email domains that can access the service.
- allowed_email_addresses optional list of authorized email addresses that can access the service.
- flush_interval sets an interval to periodically flush the buffered response to the client. If specified, SSO Proxy will not timeout requests to this upstream and will stream the response to the client. NOTE: Use with extreme caution.
- header_overrides overrides any heads set either by SSO proxy itself or upstream applications. Useful for modifying browser security headers.
- inject_request_headers adds headers to the request before the request is sent to the proxied service. Useful for adding basic auth headers if needed.
- provider_slug determines which identity provider this upstream will use. This provider must first be configured within
sso_auth
. - skip_auth_regex skips authentication for paths matching these regular expressions. NOTE: Use with extreme caution.
- timeout sets the amount of time that SSO Proxy will wait for the upstream to complete its request.
- extra_routes allows services to specify multiple routes. These route can includes the from, to, type, and options fields defined above and inherit any configuration from their parent routing config if not specified here (e.g. options).
- cluster name are cluster-specific settings. Any configuration specified in the default field can be override here with cluster specific configuration.
There are currently two route types used by SSO to route requests, simple and rewrite.
simple, the default type, route using strict host string matching from the incoming request and proxies that request to the to field.
For example:
- service: example_service
default:
from: example-service.sso.{{cluster}}.{{root_domain}}
to: example-service.{{cluster}}.{{root_domain}}
matches requests with the incoming host of example-service.sso.{{cluster}}.{{root_domain}}
and proxies those requests example-service.{{cluster}}.{{root_domain}}
rewrite routes allow for host regexp matching of incoming requests and then proxying that request
to an upstream using the to
field which can be templated with replacements. Internally, this API
just uses Regexp.ReplaceAllString
For example:
- service: example_service
default:
from: ^example-service--(.*).sso.{{cluster}}.{{root_domain}}$
to: example-service--$1.{{cluster}}.{{root_domain}}
matches requests that using the above regex and then constructs an upstream uri by replacing any match groups
the templated replacements in the to
field.
So, if sso received a request with the host header example-service--janedoe.sso.{{cluster}}.{{root_domain}}
, it would
match the provided regex and have one match group. Using Regexp.ReplaceAllString
and the incoming request host header, we can construct the upstream uri using the to
field, here example-service--janedoe.cluster.root_domin
,
and proxy the request to that upstream.
SSO Proxy can sign requests using an HMAC shared-secret signing key specified per upstream. This must be of the form algorithm:secret_value
, where sha256
is preferred for the algorithm.
To enable request signing, SSO Proxy looks for environment variables with the format SSO_CONFIG_{{SERVICE}}_SIGNING_KEY
with the previous mentioned key.
For example:
export SSO_CONFIG_FOOBAR_SIGNING_KEY="sha256:shared-secret-value"
would be the signing key for the foobar
upstream service, use the sha256 with the shared-secret-value
as it's signing key value.
This signs the request using defined signature headers found in https://github.com/buzzfeed/sso/blob/main/sso_proxy/oauthproxy.go#L25. Specific implementation details can be found at https://github.com/18F/hmacauth
sso_proxy
adds the following headers to each request it proxies to upstream services, so that upstream services may identify the authenticated user.
X-Forwarded-User
- This header contains user's username as a string:
user.name
for useruser.name@example.com
.
- This header contains user's username as a string:
X-Forwarded-Email
- This header contains the user's email address as a string:
user.name@example.com
.
- This header contains the user's email address as a string:
X-Forwarded-Groups
- This header contains the groups a user is a member of, as a comma-separated list. Only groups specified in an upstream's
allowed_groups
config option will be included. Upstream services may use this list to do finer-grained access control as necessary.
- This header contains the groups a user is a member of, as a comma-separated list. Only groups specified in an upstream's
X-Forwarded-Host
- This header contains the original host header received by sso proxy for the request, which can be used to reconstruct the original request URL if an upstream needs to do so.
Optional:
Gap-Signature
if asigning_key
for the upstream is specified
sso_proxy
adds the following headers to every outgoing request, to ensure a baseline level of browser security for every service that it protects. These headers cannot be overridden by upstream services, but can be overridden in the HEADER_OVERRIDES
environment variable.
Strict-Transport-Security
X-Content-Type-Options
X-Frame-Options
X-XSS-Protection
Each SSO session lasts for 15 days and is re-validated with sso_auth
every minute. This means that any user should only need to sign into SSO once every 15 days, while still ensuring that revoking a user's access will take effect within 4 minutes.
There are four configuration options that can be set as environment variables related to the behavior of sso proxy when it authenticates with sso authenticator.
The session_ttl_valid option controls the amount of time it will take for
sso_proxy
to pick up on authentication changes in the 3rd party provider
(e.g. revoked access, group membership updates). Once expired, sso_proxy
will make an internal request to sso_auth
(i.e. invisible to the
end user) to revalidate & refresh the session.
The sessioni_ttl_lifetime option controls the maximum lifetime of a
sso_proxy
session, after which a user will be 301 redirected to
sso_auth
to go through the 3rd party OAuth2 flow again.
The session_cookie_expire option controls the maximum lifetime of the sso_proxy
cookie stored by a user's web browser, after which a user will also be 301
redirected to sso_auth
to go through the 3rd party OAuth2 flow
again.
The session_ttl_graceperiod option controls the duration of the grace period that
sso_proxy
grants to existing sessions in the event that sso_auth
's
upstream provider is unavailable. sso_proxy
starts this grace period whenever
sso_auth
returns either a 429 Too Many Requests
or 503 Service Unavailable
response. During the grace period, existing session data is
honored as valid. The grace period ends either after the TTL expires or when
sso_auth
's upstream provider becomes available again.
-
For now, the
session_cookie_expire
value should be greater than or equal to thesession_lifetime_ttl
value. In the future, we should remove the separatecookie_expire
option altogether and just rely onsession_lifetime_ttl
. -
The value of
session_ttl_valid
has a direct impact on the number of requests we will make to the 3rd party authentication provider, as requests to re-validate a user's permissions will be made every time it expires. Tune this value to balance between responsiveness to permission changes and (over)use of 3rd party API quotas.See Google service accounts below to check API usage and quotas.
-
The grace period defined by
session_ttl_graceperiod
is granted on a per-user basis, starting from the first failure to authenticate.
SSO supports upstreams that use websockets, providing the upstream has a positive flush interval (flush_interval
) set.
/
- Begins the proxy process, attempting to authenticate the session cookie, redirecting tosso-authenticator
if there is no cookie or an invalid one./oauth2/sign_out
- Clears thesso_proxy
session cookie and redirects the user to sign out withsso-authenticator
/oauth2/callback
- The endpoint thatsso_auth
is redirected to after authenticating. This validates the redirect response and redirects to the service if the user is authenticated and authorized./oauth2/auth
- The endpoint that solely authenticates a user’s session cookie, returning a401 Status Unauthorized
response if invalid and a202 Status Accepted
response if valid./ping
- Health check endpoint. Can be used by load balancer to verify that service is still alive.
Please note that these endpoints will mask any endpoints exposed by upstream services which may share the same paths.