Scope of this PR: what it does and what it doesn't
This PR is intended strictly as a proof of concept, so we can start formulating a more concrete plan. Our short-term goal for this PR is to eliminate anything (code, workflows, documentation) that can possibly be delegated to the new single-sign on infrastructure. The current goal is a clear boundary between what we need and what is extra, even if we temporarily remove things that need to be added back in later.
One exception: I'm leaving the columns encrypted_password, reset_password_token and reset_password_sent_at in the database. Presumably we would write that removal migration in a later PR once we answer some of the questions below.
It follows that we are assuming, for now, an instantaneous switchover.
Of course, this may not be a good idea in practice. We may want to work toward a more sophisticated version of this PR that can handle both SSO and password-based logins.
Within the above-mentioned constraints, this PR tries to make as few changes to the user interface as possible. (I would like to make UI a separate project, and a separate PR.) Namely:
all logout buttons (there are at least two) are preserved and work as they did before;
I'm adding a temporary log on / log off link to the footer, which we can replace later on - or not.
For now, I'm not documenting the (fairly easy) setup within https://portal.azure.com/ and how the keys and values in there map to env variables.
Changes to devise and to the User class
Based on the above scope, we're making the following changes to devise configuration and the User class:
configuring a new authentication mechanism with four new env settings:
:azure_client_id identifies the app to Microsoft Azure;
:azure_client_secret authenticates the app to Microsoft Azure;
:azure_tenant_id identifies the Microsoft Azure directory the app wants to check;
:dev_login, which allows a developer to bypass login for a particular email address in dev.
eliminating 4 devise models:
:database_authenticatable (since we're no longer using the DB to authenticate);
:validatable (this just provides some validation code, some of which we no longer need and some of which we are adding directly to the user model);
:rememberable (keeping track of session duration is no longer our purview).
The changes above remove the password method and attributes from the user model. The DB columns remain untouched for now.
AuthController
A new controller, controllers/auth_controller.rb
handles the interaction with azure;
also provides a method dev_login which, only in dev and only for a single email address, allows a developer to log in without worrying about SSO.
Other changes
Two new gems, omniauth-azure-activedirectory-v2 and omniauth-rails_csrf_protection;
A couple adjustments to ApplicationController;
We're now handling email validation on the user model ourselves, instead of getting it for free from devise as part of :validatable;
A couple rake tasks in scihist.rake under the :user namespace are modified or removed, as they work with user passwords, which are going away;
A new test file spec/requests/auth_controller_spec.rb which tests the new auth controller. It includes a bunch of tests that used to live in spec/system/login_spec.rb but were slow and flaky.
The only thing left in login_spec.rb is a test to show that post-login redirect works;
Some other trivial changes to the tests.
Questions to consider
Do we really want to stop allowing users to log in using a form on the site? Can we think of any use cases that would force us to keep the on-site log in form?
We are introducing a major new dependency which might scare off some potential adopters. Do we care ?
Note: the :dev_login workaround alleviates this potential problem.
How do we envision the switchover? A code flag? Or do we want to quit cold turkey, as it were?
What should the UI look like?
How do we communicate with users about the change?
Ref #2564
This is in beta; do not review, do not merge.
Scope of this PR: what it does and what it doesn't
encrypted_password
,reset_password_token
andreset_password_sent_at
in the database. Presumably we would write that removal migration in a later PR once we answer some of the questions below.https://portal.azure.com/
and how the keys and values in there map to env variables.Changes to devise and to the User class
Based on the above scope, we're making the following changes to
devise
configuration and theUser
class:env
settings::azure_client_id
identifies the app to Microsoft Azure;:azure_client_secret
authenticates the app to Microsoft Azure;:azure_tenant_id
identifies the Microsoft Azure directory the app wants to check;:dev_login
, which allows a developer to bypass login for a particular email address in dev.devise
models::database_authenticatable
(since we're no longer using the DB to authenticate);:validatable
(this just provides some validation code, some of which we no longer need and some of which we are adding directly to the user model);:recoverable
(go to https://login.microsoftonline.com/ if you want to reset your password from now on);:rememberable
(keeping track of session duration is no longer our purview).password
method and attributes from the user model. The DB columns remain untouched for now.AuthController
A new controller,
controllers/auth_controller.rb
dev_login
which, only in dev and only for a single email address, allows a developer to log in without worrying about SSO.Other changes
omniauth-azure-activedirectory-v2
andomniauth-rails_csrf_protection
;devise
as part of:validatable
;scihist.rake
under the:user
namespace are modified or removed, as they work with user passwords, which are going away;spec/requests/auth_controller_spec.rb
which tests the new auth controller. It includes a bunch of tests that used to live inspec/system/login_spec.rb
but were slow and flaky.login_spec.rb
is a test to show that post-login redirect works;Questions to consider
:dev_login
workaround alleviates this potential problem.