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

Dev 4.0 #8

Closed
wants to merge 13 commits into from
Closed

Dev 4.0 #8

wants to merge 13 commits into from

Conversation

aarongranick-okta
Copy link
Contributor

@aarongranick-okta aarongranick-okta commented Oct 2, 2020

Sample update PR: okta/samples-js-react#144

Code changes:

  • Updates with new apis in auth-js@4.1
  • Removes AuthService
  • <Security>
    • removes implicit oktaAuth instance initialization
    • accepts oktaAuth, onAuthRequired from props
    • implements default restoreOriginalUri callback
  • <SecureRoute>
    • accepts onAuthRequired callback, prefer component props than root level props

@jrwpatterson
Copy link

How long for this to be implemented?

@shuowu shuowu marked this pull request as ready for review November 4, 2020 23:27
@shuowu shuowu requested a review from swiftone November 4, 2020 23:27
// Only process logic if the route matches
if (!match) {
return;
}
// Start login if and only if app has decided it is not logged inn
if(!authState.isAuthenticated && !authState.isPending) {
authService.login();
handleLogin();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a problem with calling an async function within a useEffect block? What if the component renders again while we are awaiting the onAuthRequired function? Would it make sense to use something like state to prevent multiple calls?

Copy link
Contributor

Choose a reason for hiding this comment

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

The isPending options should prevent multiple calls - at least, that was part of the role when it was in okta-react directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The default signInWithRedirect will take us to Okta and so unload the entire application.
But onAuthRequired may never resolve before it cases actions that make isAuthenticated to change to true. Then, something else happens which causes isAuthenticated to become false, and it will call onAuthRequired again, possibly before the first call has returned. It's an edge case, but imagine instead of a redirect flow we are doing an interact flow and we are waiting for a code from a mobile app. Meanwhile actions in other tabs cause the tokens to change which update auth state and toggle the value of isAuthenticated causing a re-render. Once we enter an auth flow and show the user a form, I don't think we'd want to re-render and erase the progress the user has made on that form, no matter what is happening under the hood.

Copy link
Contributor

@shuowu shuowu Nov 5, 2020

Choose a reason for hiding this comment

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

Is there a problem with calling an async function within a useEffect block?

Yes, use async directly with useEffect will cause warning in console.
https://stackoverflow.com/a/53572588

Would it make sense to use something like state to prevent multiple calls?

Agree. We already implemented logic to prevent multiple calls for signInWithRedirect https://github.com/okta/okta-auth-js/blob/master/lib/browser/browser.ts#L264, the callback options should also be protected with similar logic.

Copy link
Contributor

Choose a reason for hiding this comment

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

Protected with pendingRef in SecureRoute

@@ -14,6 +14,9 @@ const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
const JUnitXmlReporter = require('jasmine-reporters').JUnitXmlReporter;
const TEST_RESULT_FILE_DIR = '../../../test-reports/e2e';

// eslint-disable-next-line node/no-unpublished-require
require('../../../env'); // will load environment vars from testenv file and set on process.env
Copy link
Contributor Author

Choose a reason for hiding this comment

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

will E2E no longer respect the testenv file?

Copy link
Contributor

Choose a reason for hiding this comment

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

It failed to bind the testenv when I tried yarn test:e2e and yarn protractor in the test folder.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

maybe the testenv file is malformed or in the wrong location. message me and we can troubleshoot.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Only the environment variables used by the specs would be affected here: https://github.com/okta/okta-react/blob/master/test/e2e/harness/e2e/App.test.js#L40 USERNAME, PASSWORD

The harness app reads them when it webpacks: https://github.com/okta/okta-react/blob/master/test/e2e/harness/config-overrides.js#L4 ISSUER, CLIENT_ID

Copy link
Contributor

Choose a reason for hiding this comment

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

right, I think the protractor script should support locally e2e execution properly. With this line, it can wire user credentials from testenv.

Any concern for adding this line?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No concern, this is the right place to modify environment vars for protractor

README.md Outdated Show resolved Hide resolved

Components can get this object as a passed prop using the [withOktaAuth](#withoktaauth) HOC or using the [useOktaAuth](#useoktaauth) React Hook. The `authService` object provides methods for managing tokens and auth state.
From version 4.0, the Security component starts to explicitly accept [oktaAuth][Okta Auth SDK] instance as prop to replace the internal `authService` instance. You will need to replace the [Okta Auth SDK related configurations](https://github.com/okta/okta-auth-js#configuration-reference) with a pre-initialized [oktaAuth][Okta Auth SDK] instance.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

maybe it's worth mentioning that you must add @okta/okta-auth-js as a dependency to your project and install it separately from okta-react


```bash
npm install --save @okta/okta-react
```

Install peer dependency `@okta/okta-auth-js`
Copy link
Contributor

Choose a reason for hiding this comment

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

Note - npm 7 installs peer dependencies by default. I don't think that's a problem for us, but please take a moment to consider if I'm wrong.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think a manual install will not hurt even if it's installed by default in npm7, as it can also handle cases for package managers < npm7 or yarn.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
This example defines 3 routes:

- **/** - Anyone can access the home page
- **/protected** - Protected is only visible to authenticated users
- **/implicit/callback** - This is where auth is handled for you after redirection
- **/login/callback** - This is where auth is handled for you after redirection
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't the console still create /implicit/callback uris by default?

README.md Outdated Show resolved Hide resolved
README.md Outdated

You may also configure an instance of the [Auth service][] directly and pass it to the Security component.
- Initialize [oktaAuth](Okta Auth SDK) instance with `pkce=true` and pass it to the `Security` component.
Copy link
Contributor

Choose a reason for hiding this comment

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

pkce is the default now, we should rephrase this.

Copy link
Contributor

Choose a reason for hiding this comment

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

how about remove this sample? as initial pkce or not actually is the responsibility for auth-js instead of okta-react


You may also configure an instance of the [Auth service][] directly and pass it to the Security component.
- Initialize [oktaAuth](Okta Auth SDK) instance with `pkce=true` and pass it to the `Security` component.
- add `/login/callback` route with [LoginCallback](#logincallback) component to handle login redirect from OKTA.
Copy link
Contributor

Choose a reason for hiding this comment

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

In addition to the /implicit/callback vs /login/callback issue, we should be sure to mention that whatever they use needs to match the configuration of their app in Okta.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree! I don't really have a strong opinion on which one to use, probably use /login/callback and mention that they need to match config in okta app can save us from some future changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think PKCE is worth a mention, but I agree that we can mention it...and point to the AuthJS docs.

Note, however, that I'm not very happy with the AuthJS docs. We should improve those before we start removing too much from elsewhere and leaning on AuthJS docs. An overhaul to focus on customer use-cases like Aaron did with the Widget is overdue, I think.

Copy link
Contributor

Choose a reason for hiding this comment

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

looks like with so many repo/doc depend on auth-js readme, we probably want to maintain proper versions of readme for auth-js, so we don't end up with broken links everywhere.

README.md Outdated Show resolved Hide resolved
README.md Outdated

#### `authService.getAuthState()`
- `@okta/okta-auth-js` has been changed as a peerDependency for this SDK. You must add `@okta/okta-auth-js` as a dependency to your project and install it separately from `@okta/okta-react`.
- [onAuthRequired](#onauthrequired) is kept in Security's props.
Copy link
Contributor

Choose a reason for hiding this comment

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

is kept in Security's props

I'm not sure what this is saying. That it is now a prop?

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated

(async method) Triggers a re-evaluation of whether a user is considered authenticated. Might be need to be triggered manually for users that pass overrides to `onAuthRequired` to the Security component or to the `Auth` constructor. Does NOT perform a login, simply re-evaluates the current authenticated status. An 'authStateChange' event is emitted once the re-evaluation is complete.
- `isAuthenticated` will be true if **both** accessToken **and** idToken are valid
Copy link
Contributor

Choose a reason for hiding this comment

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

suggest: "if and only if"

What if their scopes don't involve both tokens? Is that still a case that can happen?

Copy link
Contributor

Choose a reason for hiding this comment

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

What if their scopes don't involve both tokens? Is that still a case that can happen?

by default should be added. We may also want to add an explanation in auth-js#readme about how to use the transformAuthState callback to handle custom scopes cases.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated

#### Example with AuthService object
*(optional)* Callback function. Called when authentication is required. If this is not supplied, `okta-react` redirects to Okta. This callback will receive [oktaAuth][Okta Auth SDK] instance as the first function parameter. This is triggered when a `SecureRoute` is accessed without authentication.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we give better advice on what this should be used for? We discuss when it is called, but not why. Our example below sends them to a location - is this instead of the normal redirection? We don't say what happens in such a case here.

import OktaContext from './OktaContext';
import OktaError from './OktaError';

const Security = ({ oktaAuth, onAuthRequired, children }) => {
const history = useHistory();
const [authState, setAuthState] = useState(oktaAuth.authStateManager.getAuthState());
const [authState, setAuthState] = useState(() => {
if (!oktaAuth) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wow are we actually allowing it to work without okta-auth-js What is the concept? That<Security> can be created first, and then later re-rendered with an oktaAuth instance?

Copy link
Contributor

Choose a reason for hiding this comment

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

it's a workaround to make the <Security> render error when oktaAuth is missing. The linter does not allow conditional hooks (render error before the hook)

https://github.com/okta/okta-react/pull/8/files/5c3aee19c504c57e3203ca802079d560e0e6b20c#diff-b511f09482238b22139073ef766c2326566a2d86519cc15b992399092c344cddR56

Copy link
Contributor

Choose a reason for hiding this comment

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

Worthy of a comment then, methinks

package.json Outdated
@@ -38,10 +38,10 @@
},
"dependencies": {
"@babel/runtime": "^7.11.2",
"@okta/configuration-validation": "^0.4.1",
"@okta/okta-auth-js": "^3.2.5"
"babel-jest": "^26.3.0"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

can probably be a dev dependency?

@aarongranick-okta
Copy link
Contributor Author

@shuowu When you are ready for final review, close this PR and open a new one. I can't approve this PR because I opened it. Also squash the commits down to just the unique items which we want to add in the CHANGELOG

@shuowu
Copy link
Contributor

shuowu commented Nov 20, 2020

@aarongranick-okta How about a new empty dev-4.0 branch with barely the version bump, then we keep merging the pending PRs into it? It would be easier to merge the whole 4.0 changes into master.

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.

4 participants