Skip to content
This repository has been archived by the owner on Oct 24, 2024. It is now read-only.

"AuthSdkError: The app should not attempt to call authorize API on callback." when passing my own AuthService instance #863

Closed
2 of 9 tasks
sarahdayan opened this issue Aug 15, 2020 · 5 comments

Comments

@sarahdayan
Copy link

I'm submitting this issue for the package(s):

  • jwt-verifier
  • okta-angular
  • oidc-middleware
  • okta-react
  • okta-react-native
  • okta-vue

I'm submitting a:

  • Bug report
  • Feature request
  • Other (Describe below)

Current behavior

I'm willing to ensure that both idToken and accessToken are still fresh to determine that a user is authenticated. As recommended here, I'm doing so by implementing my own AuthService instance and passing it down to my <Security> component:

const authService = new AuthService({
  issuer: process.env.REACT_APP_OKTA_ISSUER,
  clientId: process.env.REACT_APP_OKTA_CLIENT_ID,
  redirectUri: `${window.location.origin}/implicit/callback`,
  async isAuthenticated() {
    const tokenManager = authService.getTokenManager();
    const idToken = await tokenManager.get("idToken");
    const accessToken = await tokenManager.get("accessToken");

    return !!(idToken && accessToken);
  },
  onAuthRequired() {
    history.push("/login");
  },
  pkce: true,
});

// ...

<Security authService={authService}>

It works and I successfully sign in, but I get an error printed in the callback phase (when hitting /implicit/callback):

AuthSdkError: The app should not attempt to call authorize API on callback. Authorize flow is already in process. Use parseFromUrl() to receive tokens.

My callback route is using the LoginCallback component provided by the SDK, nothing custom, so I'm unsure why I'm getting this error. I used to have all the options from my AuthService instance passed as props in <Security>, I only moved them into the AuthService constructor.

Expected behavior

I would expect no error to show up, and the behavior should be the same when passing an instance vs. when passing each option as a prop.

Minimal reproduction of the problem with instructions

  1. Implement Okta flow with custom login in a React application.
  2. Create a custom AuthService instance and pass it to <Security> component (code above).
  3. Sign in.

Extra information about the use case/user story you are trying to implement

I'm willing to implement isAuthenticated myself to check whether idToken and accessToken are fresh, as recommended here.

Environment

  • Package Version: @okta/okta-react 3.0.3 | @okta/okta-auth-js 3.2.1
  • Browser: Firefox 79
  • OS: macOS Catalina 10.15.5
  • Node version (node -v): 14.2.0
@aarongranick-okta
Copy link
Contributor

@sarahdayan Thanks for the report. This error is most commonly called by router config. The most common cause is route logic which is meant for a non-callback route running on the callback. For example a route with path / will execute on ALL routes. This can be fixed by using a <Switch> and/or exact attribute on routes. It is important that the callback route executes without any additional logic. It is neither an authenticated nor an unauthenticated route and it is not valid to even ask the question on the callback route. So any logic which is trying to determine authenticated status must not run on the callback route.

@ilgiznurgaliev
Copy link

Hi, @aarongranick-okta. Could you please advise how this can be fixed in angular application. I'm getting the same error when trying to get accessToken.
Part of my app.module.ts:

const oktaConfig = {
  issuer: environment.OKTA_ISSUER,
  clientId: environment.OKTA_CLIENTID,
  redirectUri: 'http://localhost:4200/login',
  scopes: ['openid', 'profile', 'email'],
  pkce: true
}

const routes: Routes = [
  {
    path: '',
    component: AppComponent,
    canActivate: [ OktaAuthGuard ]
  },
  {
    path: 'login',
    component: OktaCallbackComponent,
  }
];

Part of my app.component.ts:

constructor(private httpService: HttpService, public oktaAuth: OktaAuthService) {
    this.oktaAuth.$authenticationState.subscribe(isAuthenticated => this.isAuthenticated = isAuthenticated);
  }
async ngOnInit() {
    this.isAuthenticated = await this.oktaAuth.isAuthenticated();
    const accessToken = await this.oktaAuth.getAccessToken();
    console.log('Access Token: ', accessToken);
}

I have now any other components and routes, everything is within app (root path).
The error from chrome console:
Error: Uncaught (in promise): AuthSdkError: The app should not attempt to call authorize API on callback. Authorize flow is already in process. Use parseFromUrl() to receive tokens.

@aarongranick-okta
Copy link
Contributor

@ilgiznurgaliev a few questions which will help us solve this issue:

  • Does this error occur while performing login callback on the callback route? Or does it occur on other routes, at other times?
  • Are you using hash-based routing?
  • Does your app require use of the "code" query parameter?

@aarongranick-okta
Copy link
Contributor

@ilgiznurgaliev Reading your question closely I see you say that "everything is within app (root path)". So the problem is probably calling isAuthenticated while processing the callback. If doing redirect, we recommend having a dedicated route for callback. Solutions for this problem:

  • Use routing and have dedicated route for the login callback. The logic on this route should call handleAuthentication and nothing else. It should not attempt to determine authentication status while processing the callback.
  • Do not use redirect in the login flow. Using a self-hosted signin widget, you can avoid redirecting to Okta and then there is no need for a callback route. Here is an example of how to do that: okta/samples-js-react@c841d6b (it is made for react, but the logic is the same for angular)
  • If you are doing redirect and not using any routes, then you must test for the callback condition and call handleAuthentication instead of any other methods. Do not call isAuthenticated if the callback condition is true. If processing a PKCE callback there should be a query parameter named "code" in the URL, this can be used as a simple test for the callback condition.

@aarongranick-okta
Copy link
Contributor

Closing this issue. okta-react has now moved here: https://github.com/okta/okta-react If anyone is having this issue, please create a new issue there.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants