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

DCJ-654: Sign-in via OIDC #2667

Merged
merged 32 commits into from
Sep 19, 2024
Merged

DCJ-654: Sign-in via OIDC #2667

merged 32 commits into from
Sep 19, 2024

Conversation

rushtong
Copy link
Contributor

@rushtong rushtong commented Sep 9, 2024

Addresses

https://broadworkbench.atlassian.net/browse/DCJ-654

Summary

This PR completes the efforts started in #2611 and #2657. This replaces Google Sign-in with Oidc sign-in.

Full Screen

Screenshot 2024-09-17 at 11 37 41 AM

Minimized Screen

Screenshot 2024-09-17 at 11 37 50 AM

Our (current) B2C Tenant Screen

This will be changed to a DUOS version in https://broadworkbench.atlassian.net/browse/DCJ-165
Screenshot 2024-09-17 at 12 07 56 PM


Have you read Terra's Contributing Guide lately? If not, do that first.

  • Label PR with a Jira ticket number and include a link to the ticket
  • Label PR with a security risk modifier [no, low, medium, high]
  • PR describes scope of changes
  • Get a minimum of one thumbs worth of review, preferably two if enough team members are available
  • Get PO sign-off for all non-trivial UI or workflow changes
  • Verify all tests go green
  • Test this change deployed correctly and works on dev environment after deployment

@rushtong rushtong marked this pull request as ready for review September 17, 2024 15:57
@rushtong rushtong requested a review from a team as a code owner September 17, 2024 15:57
@rushtong rushtong requested review from fboulnois and removed request for a team September 17, 2024 15:57
Copy link
Contributor

@fboulnois fboulnois left a comment

Choose a reason for hiding this comment

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

overall looks good, questions relating to tests:

cy.on('fail', (err) => {
return err.message !== Auth.signInError();
});
Auth.signIn();
Copy link
Contributor

Choose a reason for hiding this comment

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

This function still seems to be async, does it need to be awaited?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call, but await-ing breaks the test, I think I need to use then

'clientId': 'clientId'
});
await Auth.initialize();
Auth.initialize();
Copy link
Contributor

Choose a reason for hiding this comment

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

This function still seems to be async, does it need to be awaited?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was initially confused by this. Cypress gives you a warning if you use async in beforeEach:

Cypress Warning: Cypress detected that you returned a promise in a test, but also invoked one or more cy commands inside of that promise.

The test title was:

  > Auth Success "before each" hook

While this works in practice, it's often indicative of an anti-pattern. You almost never need to return both a promise and also invoke cy commands.

Cy commands themselves are already promise like, and you can likely avoid the use of the separate Promise.

https://on.cypress.io/returning-promise-and-commands-in-test

@@ -5,7 +5,6 @@
"hash": "alpha",
"apiUrl": "https://consent.dsde-alpha.broadinstitute.org",
"ontologyApiUrl": "https://consent-ontology.dsde-alpha.broadinstitute.org/",
"clientId": "1020846292598-hd801vsmmbhh97vaf6aar17lu0q2evfj.apps.googleusercontent.com",
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought alpha didn't exist anymore? Why do we need this config?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This config file name is not important and is, unfortunately, an artifact of our build image process. Originally, it did reference real environment variables. I'll change this in a separate PR/ticket.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I created https://broadworkbench.atlassian.net/browse/DCJ-678 to cover this bit of tech debt.

@@ -139,11 +102,15 @@ export const SignInButton = (props: SignInButtonProps) => {
const registerAndRedirectNewUser = async (redirectTo: string, shouldRedirect: boolean) => {
const registeredUser: DuosUser = await User.registerUser();
setUserRoleStatuses(registeredUser, Storage);
await onSignIn();
await syncSignInOrRegistrationEvent(eventList.userRegister);
history.push(`/tos_acceptance${shouldRedirect ? `?redirectTo=${redirectTo}` : ''}`);
Copy link
Contributor

Choose a reason for hiding this comment

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

why move this line from syncSignInOrRegistrationEvent to here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My goal with syncSignInOrRegistrationEvent was to isolate the Metrics calls. I wanted that to remain short and focused. Since the history modification is not related to that functionality, I pulled it out so it would be more clear as to where it is being used. What I found in going through this code is that there was a lot of dual-function helper methods that were very confusing to debug, especially the new user registration piece. By isolating functionality, I was better able to log and reason about what was happening in the different cases.

import {unregister} from './registerServiceWorker';
import {BrowserRouter} from 'react-router-dom';

const load = async () => {
unregister();
await Auth.initialize();
if (window.location.pathname.startsWith('/redirect-from-oauth')) {
await OidcBroker.getUserManager().signinPopupCallback(window.location.href);
Copy link
Contributor

Choose a reason for hiding this comment

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

what does this do?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great question. In the original version of this work, there was a whole component dedicated to servicing this single path. This is my attempt to simplify it. In short, it does this:

  1. The OIDC client calls a popup window with a redirect url here: https://github.com/DataBiosphere/duos-ui/pull/2667/files#diff-c22f0b724cae791bb887d11ce9ada280a1581625e133634e5c2356a5637d6980L42
  2. The user goes through the auth dance and is redirected to that url, but the popup doesn't go away.
  3. On reload, we detect the path
  4. Call the signinPopupCallback which does two things
    • It closes the open popup
    • Redirects the user to the original href, which is either the home page, or a sub-page inside the app to which we redirect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm going to add some comments around this for future devs.

Copy link
Contributor

@rjohanek rjohanek left a comment

Choose a reason for hiding this comment

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

overall, looks good! Just a couple questions for my own understanding

@rushtong rushtong merged commit 1652274 into develop Sep 19, 2024
9 checks passed
@rushtong rushtong deleted the gr-DCJ-654-sign-in branch September 19, 2024 15:20
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.

3 participants