Supporting user authentication for Jetstream 2
Had a talk with @j.michael.lowe today. What I learned about Jetstream 2 plans:
- Users' OpenStack accounts will match their XSEDE usernames, so they will look more like
cmart
thantg836338
- Passwords for users' OpenStack accounts will probably be local to Keystone, not linked to XSEDE or backed by anything else
- Users will be able to reset/change their OpenStack (Keystone) password, but some of them won't need to think about it, because:
- User auth to Horizon will likely use Globus via OpenID Connect, and Mike now has a working example of this.
- For user auth to OpenStack CLI/API, folks can generate a long-lived Keystone application credential from Horizon, and use that.
- For user auth to whatever CyVerse builds to support Jetstream 2, a Keystone application credential will be generated when the OpenStack account is created (which happens upon receipt of notification from XSEDE).
- OpenStack Adjutant may play a role in creating OpenStack accounts with an expired password, maybe emailing user a password reset link
More on OAuth/OpenID Connect via Globus:
- OpenID Connect via Globus appears to be XSEDE's only officially supported way for Jetstream to authenticate users who provide their XSEDE credentials
- A Kerberos server ultimately backs all of this, but JS2's OpenStack is not allowed to talk to it, only Globus can talk to it
- This arrangement is a little tricky to use with anything that's not a web application (e.g. CLI or API), because this implementation of OAuth appears to require the user to interact with a browser. The user's choices will be 1. use application credentials, or 2. (re)set your Keystone password, which requires managing another password.
The options for Exosphere to support a good login UX with Jetstream 2 (where user provides XSEDE credentials and then chooses from a list of projects/allocations that they're a member of):
- Do what Horizon does, the OAuth/OIDC dance with Keystone and Globus
- https://docs.openstack.org/keystone/latest/admin/federation/introduction.html#openid-connect-with-keystone-and-horizon
- https://docs.openstack.org/keystone/latest/admin/federation/configure_federation.html#setting-up-openid-connect
- https://docs.openstack.org/keystone/latest/admin/federation/configure_federation.html#add-a-trusted-dashboard-websso
- May require some reverse engineering of how Horizon does it. There's a Keystone endpoint to support this, and Exosphere deployments will need to be added as
trusted_dashboard
s in Keystone config. - May require another custom server-side component.
- Failing that, we could write a Keystone backend for Jetstream which uses user-provided credentials to attempt to log into an XSEDE web-based service that accepts a username and password (e.g. the XSEDE User Portal login page), and parses the results to determine authentication success/failure. This would be dirty, somewhere between unsupported and forbidden by XSEDE, I don't know
😁
This issue is a successor to #260 (closed).
Design login flow
- User clicks "Log in" button
- Exosphere sends user (via
Browser.Navigation.load
to the cloud's Keystone:/v3/auth/OS-FEDERATION/websso/openid?origin=https://my.exosphere.domain/exosphere/auth/websso
. The following steps are out of our/Exosphere's hands until user is redirected back. - Keystone returns a 302 redirect to the OpenID Connect Identity Provider (in this case, Globus)
- User authenticates self with ID provider, gets redirected back and forth between there and Keystone a bunch
- Eventually, Keystone serves some JavaScript to browser which redirects user to (e.g.)
https://my.exosphere.domain/exosphere/auth/websso
, POSTing form data with an unscoped Keystone auth token astoken
. Now the responsibility is back in our hands. This route matches our little Flask app which reads the form data and 302s tohttps://my.exosphere.domain/exosphere/auth/oidc-login?token=unscoped-auth-token-here
, or something like that. - Exosphere loads in the user's browser again, parses unscoped token in URL query string.
- Exosphere does the equivalent of
curl -H "X-Auth-Token: foobar" https://my.openstack.cloud:5000/v3/auth/projects
, passing the unscoped auth token as a header. This returns a list of projects. - Exosphere shows a list of projects to the user as a multi-select. User chooses one or more projects.
- For each chosen project, Exosphere POSTs to
https://my.openstack.cloud:5000/v3/auth/tokens
, passing JSON like the following:
{
"auth": {
"identity": {
"methods": [
"token"
],
"token": {
"id": "entire-token-value-goes-here"
}
},
"scope": {
"project": {
"id": "uuid-of-desired project"
}
}
}
}
- The above XHR returns a scoped auth token for the project, a service catalog, and the user name/ID/domain. Only now does Exosphere know information about the OpenStack user. Maybe there's a way to get it sooner, but not that I've found yet.
- From here everything is the same as what we already do, e.g. request and store a long-lived application credential for the project.
Design Todo
-
Look at what we already do for unscoped tokens, what needs to change to also support the above login flow. For example, with OIDC it seems we won't know anything about the user until we ask for a project-scoped auth token.
Implementation plan
-
In Types.Types.UnscopedProvider
, remove `keystonePassword`` -
In OpenStack.Types.UnscopedAuthToken
, user name+domain must be either removed or made aMaybe
-
Rest.Keystone.requestScopedAuthToken
needs to support use of an unscoped token instead of a password or app credential -
Rest.Keystone.requestUnscopedProjects
should use/v3/auth/projects
instead of/v3/users/user-uuid-here/projects
, then doesn't need to know anything about the user anymore -
Ability to pass OIDC login configuration via flags - Icon and text of OIDC login button
- Keystone URL
-
URL route to take unscoped auth token and prompt user to select projects -
Change https://my.exosphere.domain/exosphere/auth/websso
tohttps://my.exosphere.domain/exosphere/oidc-redirector
(needs Mike's help) -
Fix ugly login picker view -
Document the OIDC Redirector Flask app -
Document how to use this feature
Things to think about
- Initial redirect to Keystone may require user's browser to load page at (e.g.) port 5000. Some internet connections won't let people do this. Might be able to pass this through the Cloud CORS Proxy, or somehow use a bit of Horizon.