Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional Auth0 integration #229

Merged
merged 12 commits into from
Oct 19, 2020
Merged

Add optional Auth0 integration #229

merged 12 commits into from
Oct 19, 2020

Conversation

macfarlandian
Copy link
Collaborator

@macfarlandian macfarlandian commented Oct 15, 2020

Description of the change

Adds support for an Auth0 integration that puts the entire site behind an auth requirement. The feature can be toggled on and off with environment variables. This includes the necessary Auth0 configuration to support this in staging, but there is no staging environment that is actually set up yet, so we can harden this as needed without any risk in the meantime.

Matters of note:

  • I created a new Auth0 tenant for this, using the default domain supplied by Auth0 rather than a custom one under recidiviz.org. That works just fine, but we can also change it if there's a good reason to? None of our other tenants seem to be set up this way but I don't know the reason for that.
  • Auth0 has a React-specific library that utilizes Universal Login; I don't know how new it is but we haven't used it anywhere else that I have seen. It seems to work pretty well, with much less boilerplate.
  • I have adopted the practice from pulse-dashboard of adding Auth0 rule and hook functions to the repo even though they are not actually used by the application. I did keep them out of the src directory in an attempt to mitigate that ambiguity. I don't think any of the rules we have applied elsewhere are really needed here, so there aren't actually any, but I did replicate the domain filtering hook, which in the actual Auth0 settings only includes recidiviz.org. (I wasn't sure whether we definitely needed to require email verification; pulse-dashboard uses it but the COVID site does not. Question for @jessex whether that is a blocker here for compliance or other reasons.)
  • Because the auth is optional and the necessary settings are not guaranteed to be present in all environments, I had to do something slightly weird to conditionally render the Auth0 library stuff only when we had data for them. There is a provider and a hook that have to be used together, and you can't use a hook conditionally within a component, so this took some indirection. The test that I wrote attempts to cover this.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Configuration change (adjusts configuration to achieve some end related to functionality, development, performance, or security)

Related issues

Closes #220

Checklists

Development

These boxes should be checked by the submitter prior to merging:

  • Manual testing against realistic data has been performed locally

Code review

These boxes should be checked by reviewers prior to merging:

  • This pull request has a descriptive title and information useful to a reviewer
  • This pull request has been moved out of a Draft state, has no "Work In Progress" label, and has assigned reviewers
  • Potential security implications or infrastructural changes have been considered, if relevant

@coveralls
Copy link

Pull Request Test Coverage Report for Build 309550846

  • -5 of 22 (77.27%) changed or added relevant lines in 5 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+72.2%) to 75.0%

Changes Missing Coverage Covered Lines Changed/Added Lines %
spotlight-client/src/utils/isAuthEnabled.ts 0 1 0.0%
spotlight-client/src/AuthProvider/getAuthSettings.ts 1 3 33.33%
spotlight-client/src/AuthWall/AuthWall.tsx 10 12 83.33%
Totals Coverage Status
Change from base Build 307102526: 72.2%
Covered Lines: 18
Relevant Lines: 24

💛 - Coveralls

@coveralls
Copy link

coveralls commented Oct 15, 2020

Pull Request Test Coverage Report for Build 311716257

  • 26 of 26 (100.0%) changed or added relevant lines in 5 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+2.5%) to 5.308%

Totals Coverage Status
Change from base Build 307102526: 2.5%
Covered Lines: 60
Relevant Lines: 1351

💛 - Coveralls

@jessex
Copy link
Member

jessex commented Oct 16, 2020

That works just fine, but we can also change it if there's a good reason to? None of our other tenants seem to be set up this way but I don't know the reason for that.

If by this you mean that the login form is not hosted at a recidiviz.org subdomain yet and is hosted at a subdomain of auth0.com, then we do want to use a recidiviz.org subdomain for consistency and control.

Auth0 has a React-specific library that utilizes Universal Login; I don't know how new it is but we haven't used it anywhere else that I have seen. It seems to work pretty well, with much less boilerplate.

Can you point me to the library we're using in pulse and the library you're now using here so I can compare?

I wasn't sure whether we definitely needed to require email verification; pulse-dashboard uses it but the COVID site does not. Question for @jessex whether that is a blocker here for compliance or other reasons.

We do need to do email verification of some kind. Otherwise, random people can sign up for accounts using whatever@recidiviz.org and immediately start surfing through staging. The Covid app does do email verification but it's done in the app itself, not with rules via Auth0. I think I prefer the way the Covid app does it actually, but you should take a look.

Copy link
Member

@jessex jessex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a fairly elegant approach! The only thing that's not perfect is that we have to have two separate places where we check if auth is enabled or not (the provider and the wall) but that's not terrible. Well done!

Just a few questions.

Expected environment variables include:

- `REACT_APP_AUTH_ENABLED` - set to `true` or `false` to toggle Auth0 protection per environment. Currently only used in staging to make the entire site private. No need to enable this locally unless you are developing or testing something auth-related.
- `REACT_APP_AUTH_ENV` - a string indicating the "auth environment" used to point to the correct Auth0 tenant. Either "development" (which also covers staging) or "production".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this true and relevant? I thought we only had one auth environment for this app.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes you are right ... I adapted this from the pulse readme and was a little unsure of how to handle the production case. But after sleeping on it, it seems pretty obvious to me that the docs should just reflect the current state of things (just the one environment) and not worry about being future-proof. I'll update this!

};
});

test("require auth", async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing test 🚀

@@ -0,0 +1,55 @@
// Recidiviz - a data platform for criminal justice reform
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this code copied from Auth0 or was it entirely hand-written? Just curious!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not copied, although the logic is simplistic enough that it probably substantially resembles what's in the docs for this library

spotlight-client/src/AuthWall/AuthWall.tsx Outdated Show resolved Hide resolved
@macfarlandian
Copy link
Collaborator Author

@jessex re: the Auth0 libraries: here we are using auth0-react, which as far as I can tell is a React wrapper around @auth0/auth0-spa-js, the more generic JS library we are using in pulse (and covid). It essentially replaces the react-auth0-spa file that we have adapted from the Auth0 docs for each of those sites.

I am also not in love with the double environment check but I am hoping the tests will be decently effective at catching that; one of both of those top-level App tests should fail if the two checks were to get out of sync, or if they both broke simultaneously for some reason. (The only thing I can think of that they wouldn't catch is if the mocked functions somehow became non-deterministic? Or you know .... solar flares.)

As far as the additional Auth0 config is concerned ... I'll keep working on that and update here as needed.

@jessex
Copy link
Member

jessex commented Oct 16, 2020

Fascinating! Yeah it appears that auth0-react is newish and was created after our first uses of Auth0 in our frontend. Would be good to standardize on this not long from now after this app has proven its worth.

@macfarlandian
Copy link
Collaborator Author

all comments up until this point should be addressed now!

Copy link
Member

@jessex jessex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, @macfarlandian!

@jovergaag
Copy link

@macfarlandian This looks great! Great test coverage.

As far as standardizing on an auth package, I agree that we should move towards this, especially considering I've been stuck in an IE11 localhost authentication hole for a full day. I'm wondering if the auth0-react package has tidied some of that up? I do a spike to try to install this package on pulse on Monday and see if it clears anything up.

Copy link

@jovergaag jovergaag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌮

@macfarlandian
Copy link
Collaborator Author

I had a flash of inspiration this afternoon about reducing the number of magical incantations required to prevent this auth solution from breaking. In the latest commit I pushed:

  • the environment variable is only checked once
  • App.tsx only imports one component, which encapsulates all of the necessary Auth0 coordination
  • to better support their required coordination, the provider and the checker are co-located in the same file and are private to that module

Tests continued to pass without modification (I only had to change some import paths) so ... that's good at least? I am curious whether you all actually see this as an improvement, though, so I will defer merging until after the weekend to let you weigh in. (The thing that allowed this new approach was the surprising discovery that the auth0 hook does not actually blow up if you call it without a Provider; that feels maybe a little hacky to me but could potentially be improved if this new overall pattern is to our liking)

Copy link
Member

@jessex jessex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think this is an improvement! Centralizing complexity into a single location to be reasoned about, with as few instances of moving parts as possible, is worthwhile.

@macfarlandian macfarlandian merged commit b78f80f into master Oct 19, 2020
@macfarlandian macfarlandian deleted the 220-private-staging branch October 19, 2020 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Set up Auth0 for staging
5 participants