keystoneauth1.identity.v3.websso module¶
Keystone WebSSO authentication plugin.
Keystone’s WebSSO endpoint delegates authentication to a browser. This plugin
opens the endpoint in the user’s browser, listens on a loopback port for the
form POST that Keystone makes once the identity provider has authenticated the
user, and turns the token in that POST into an unscoped AccessInfo.
The unscoped token it obtains can be rescoped to any project, domain or
system, so an application that holds on to it through
get_unscoped_auth_state spares the user a login for each one.
WebSSO is not a standardised protocol. Keystone defined it so that Horizon
could authenticate users against an external identity provider, and modelled
it on the SAML 2.0 Web Browser SSO Profile: as in that profile’s HTTP POST
binding, the identity service returns an auto-submitting HTML form which posts
the credential to a pre-registered, trusted origin. Because Keystone compares
that origin against its [federation] trusted_dashboard list verbatim, the
callback path and default port used here are the ones given in the Horizon and
Keystone federation installation guides rather than values of our choosing.
Warning
The callback is open to login CSRF and cannot be closed to it. While the listener is running, any page open in the user’s browser can submit a form to the callback port and have its own Keystone token accepted, which would leave the user operating as whoever obtained that token.
Nothing in the request distinguishes such a submission from Keystone’s. The
Fetch Metadata headers of a scripted cross-origin form submission are
identical to those of Keystone’s auto-submitted form, and on the https to
http callback that this flow relies on the Fetch standard serializes
Origin as null and drops Referer for both.
Binding the callback to the request it belongs to would need a nonce in the
origin parameter, and there is nowhere to put one: Keystone requires
that parameter to match a trusted_dashboard entry exactly, so it cannot
carry per-request data. The window is limited instead: the listener binds to
loopback only, runs only while a login is in progress, stops at the first
token it accepts, and times out.
- class keystoneauth1.identity.v3.websso.WebSSO(auth_url: str, identity_provider: str, protocol: str, *, redirect_host: str = 'localhost', redirect_port: int = 9990, login_timeout: float = 60, username: str | None = None, trust_id: str | None = None, system_scope: str | None = None, domain_id: str | None = None, domain_name: str | None = None, project_id: str | None = None, project_name: str | None = None, project_domain_id: str | None = None, project_domain_name: str | None = None, reauthenticate: bool = True, include_catalog: bool = True)¶
Bases:
FederationBaseAuthAuthenticate using Keystone’s browser based WebSSO flow.
The user is sent to Keystone’s WebSSO endpoint in their browser and authenticates there against the configured identity provider. Keystone then posts the resulting unscoped token back to a listener this plugin runs on a loopback port.
The callback URL,
http://<redirect_host>:<redirect_port>/auth/websso/, must appear verbatim in the server’s[federation] trusted_dashboardlist or Keystone refuses to complete the flow.usernameis optional and plays no part in authenticating: the identity is chosen in the browser. It only labels the unscoped token for caching, so a caller who signs in as more than one SSO account against the same identity provider can tell those accounts’ cached tokens apart. Give each account a distinct value; leave it unset if there is only one.login_timeoutis how many seconds to wait for the user to finish authenticating in the browser before giving up. The default suits an established session, but a first login through an external identity provider, particularly one that prompts for MFA, can take longer; raise it for those.- __abstractmethods__ = frozenset({})¶
- __annotate_func__ = None¶
- __annotations_cache__ = {}¶
- __doc__ = "Authenticate using Keystone's browser based WebSSO flow.\n\nThe user is sent to Keystone's WebSSO endpoint in their browser and\nauthenticates there against the configured identity provider. Keystone\nthen posts the resulting unscoped token back to a listener this plugin\nruns on a loopback port.\n\nThe callback URL, ``http://<redirect_host>:<redirect_port>/auth/websso/``,\nmust appear verbatim in the server's ``[federation] trusted_dashboard``\nlist or Keystone refuses to complete the flow.\n\n``username`` is optional and plays no part in authenticating: the identity\nis chosen in the browser. It only labels the unscoped token for caching, so\na caller who signs in as more than one SSO account against the same\nidentity provider can tell those accounts' cached tokens apart. Give each\naccount a distinct value; leave it unset if there is only one.\n\n``login_timeout`` is how many seconds to wait for the user to finish\nauthenticating in the browser before giving up. The default suits an\nestablished session, but a first login through an external identity\nprovider, particularly one that prompts for MFA, can take longer; raise it\nfor those.\n"¶
- __firstlineno__ = 341¶
- __init__(auth_url: str, identity_provider: str, protocol: str, *, redirect_host: str = 'localhost', redirect_port: int = 9990, login_timeout: float = 60, username: str | None = None, trust_id: str | None = None, system_scope: str | None = None, domain_id: str | None = None, domain_name: str | None = None, project_id: str | None = None, project_name: str | None = None, project_domain_id: str | None = None, project_domain_name: str | None = None, reauthenticate: bool = True, include_catalog: bool = True)¶
- __module__ = 'keystoneauth1.identity.v3.websso'¶
- __static_attributes__ = ('login_timeout', 'redirect_host', 'redirect_port', 'redirect_uri', 'username')¶
- _abc_impl = <_abc._abc_data object>¶
- property _base_url: str¶
The versioned root of the identity service.
- _get_auth_token() str¶
Send the user to their browser and wait for the token.
- property federated_token_url: str¶
URL that starts the WebSSO flow.
- get_unscoped_auth_ref(session: Session) AccessInfoV3¶
Authenticate in a browser and return the unscoped token.
Keystone hands back only the token itself, so it is validated against the identity service to pick up its expiry and catalog.
- get_unscoped_cache_id_elements() dict[str, str | None]¶
Add the caller supplied username to the unscoped token’s identity.
The browser, not this plugin, chooses who logs in, so the username is not used to authenticate and nothing checks it against the token that comes back. It is here only so a caller who authenticates as more than one SSO account against the same identity provider can keep their unscoped tokens apart in a cache; leaving it unset keeps the identifier as it would otherwise be.
- interactive_unscoped_auth: ClassVar[bool] = True¶
Whether authenticating requires the user to do something, such as completing a login in a browser. Where it does, holding on to the credential saves an interaction rather than merely a round trip.