Skip to content
This repository has been archived by the owner on Jul 26, 2022. It is now read-only.

Unhandled Rejection (AuthSdkError) #885

Open
2 of 8 tasks
GabrielMoscone opened this issue Aug 31, 2020 · 7 comments
Open
2 of 8 tasks

Unhandled Rejection (AuthSdkError) #885

GabrielMoscone opened this issue Aug 31, 2020 · 7 comments

Comments

@GabrielMoscone
Copy link

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

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

I'm submitting a:

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

Current behavior

If i clear the cache and cookies before Login i have this error:
Unhandled Rejection (AuthSdkError): The app should not attempt to call getToken on callback. Authorize flow is already in process. Use parseFromUrl() to receive tokens.

Expected behavior

Login with success

Minimal reproduction of the problem with instructions

Before try to login i clear the cache and cookies and have this issue,
If i try to login again without clear the cache, dont show this error

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

I just want to know if someone have this same issue or what can be the cause
I tried to search what part of the code have this issue and i think it is the LoginCallback, but i dont know how change that component

image

Environment

  • Package Version: 3.0.4 and 3.0.5
  • Browser: Any
  • Other:
@shuowu
Copy link
Contributor

shuowu commented Aug 31, 2020

@Dark-Games I failed to reproduce your issue with cache and cookies cleared.
The error you are seeing comes from okta-auth-js, it's designed to prevent the app from running into pkce race condition.
Here is the error: https://github.com/okta/okta-auth-js/blob/92ed9c126cd1e89d988d16d19b8aab0ec64ad0da/lib/token.ts#L595

I would be happy to investigate more if you can share detailed reproduction steps.

@GabrielMoscone
Copy link
Author

GabrielMoscone commented Sep 1, 2020

@Dark-Games I failed to reproduce your issue with cache and cookies cleared.
The error you are seeing comes from okta-auth-js, it's designed to prevent the app from running into pkce race condition.
Here is the error: https://github.com/okta/okta-auth-js/blob/92ed9c126cd1e89d988d16d19b8aab0ec64ad0da/lib/token.ts#L595

I would be happy to investigate more if you can share detailed reproduction steps.

@shuowu
This can answer if the error comes from my code or from the okta configuration of my account?

@shuowu
Copy link
Contributor

shuowu commented Sep 1, 2020

@Dark-Games I don't think it's caused by your configuration, probably it comes from your code, which triggered multiple pkce login flow concurrently.

@GabrielMoscone
Copy link
Author

@shuowu I will try to send to you the code that i'm using because i searching for what was the cause but didn't found nothing wrong. If you find something wrong with the code i appreciate!

App.js

import React, { Component } from 'react';
import './global.css';
import Routes from './routes';

class App extends Component {
  render() {
    return (
      <div className="app">
        <Routes />
      </div>
    );
  }
}

export default App;

routes.js

import React, { Component } from 'react';
import { Route, BrowserRouter } from 'react-router-dom';
import Pendentes from './components/pendentes/pendentes';
import Glossario from './components/glossario/glossario';
import Reporting from './components/reporting/reporting';
import Planilha from './components/planilha/planilha';
import Dashboard from './components/dashboard';
import AppBar from './components/app_bar';
import { LoginCallback } from '@okta/okta-react';

import AuthOkta from './auth_okta';
import { Security, SecureRoute } from '@okta/okta-react';

class Routes extends Component {
  render() {
    const config = {
      issuer: 'https://{url}/oauth2/default',
      redirectUri: window.location.origin + '/implicit/callback',
      clientId: {id},
      pkce: true,
    };
    return (
      <BrowserRouter>
        <Security
           {...config}
        >
          <AuthOkta>
            <SecureRoute component={AppBar} />
            <SecureRoute exact path="/" component={Dashboard} />
            <SecureRoute path="/dashboard" component={Dashboard} />
            <SecureRoute path="/pendentes" component={Pendentes} />
            <SecureRoute path="/glossario" component={Glossario} />
            <SecureRoute path="/reporting" component={Reporting} />
            <SecureRoute path="/planilha" component={Planilha} />
          </AuthOkta>
          <Route path="/implicit/callback" component={LoginCallback} />
        </Security>
      </BrowserRouter>
    );
  }
}

export default Routes;

auth_okta.js

import React, { Component } from 'react';
import { withOktaAuth } from '@okta/okta-react';
import toastr from 'toastr';
import { obterParametros } from './actions/index';
import { connect } from 'react-redux';
import _ from 'lodash';
import CircularProgress from '@material-ui/core/CircularProgress';

class AuthOkta extends Component {
  constructor(props) {
    super(props);
    this.state = { authenticated: null };
    this.checkAuthentication = this.checkAuthentication.bind(this);
    this.checkAuthentication();
  }

  async checkAuthentication() {
    const authenticated = this.props.authState.isAuthenticated;
    if (authenticated !== this.state.authenticated) {
      if (authenticated) {
        try {
          const token = `Token ${await this.props.authService.getAccessToken()}`;

          this.props.obterParametros(token);
        } catch (error) {
          toastr.error('Erro obtendo credenciais');
        }
        this.setState({ authenticated: true });
      } else {
        this.setState({ authenticated: false });
      }
    }
  }

  componentDidUpdate() {
    this.checkAuthentication();
  }

  render() {
    if (this.state.authenticated === null) {
      return null;
    } else if (this.state.authenticated) {
      if (_.isEmpty(this.props.parametros)) {
        return (
          <div
            style={{
              position: 'fixed',
              top: '50%',
              left: '50%',
              transform: 'translate(-50%, -50%)',
            }}
          >
            <CircularProgress color="secondary" thickness={6} size={50} />
          </div>
        );
      } else {
        return this.props.children;
      }
    } else {
      this.props.authService.login('/');
      return <div />;
    }
  }
}

function mapStateToProps(state) {
  return {
    parametros: state.parametros,
  };
}

export default connect(mapStateToProps, { obterParametros })(
  withOktaAuth(AuthOkta)
);

app_bar.js

import { withOktaAuth } from '@okta/okta-react';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';
import Dashboard from '@material-ui/icons/Dashboard';
import ExitToApp from '@material-ui/icons/ExitToApp';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';

class CustomAppBar extends Component {
  constructor(props) {
    super(props);
    this.logoff = this.logoff.bind(this);
    this.handlePendentesClick = this.handlePendentesClick.bind(this);
    this.handleGlossarioClick = this.handleGlossarioClick.bind(this);
    this.handleReportingClick = this.handleReportingClick.bind(this);
    this.handlePlanilhaClick = this.handlePlanilhaClick.bind(this);
  }

  logoff() {
    this.props.authService.logout('/');
  }

  handlePendentesClick() {
    this.props.history.push('/pendentes');
  }

  handleGlossarioClick() {
    this.props.history.push('/glossario');
  }

  handleReportingClick() {
    this.props.history.push('/reporting');
  }

  handlePlanilhaClick() {
    this.props.history.push('/planilha');
  }

  render() {
    if (!this.props.authState.isAuthenticated) {
      return null;
    }
    const { classes } = this.props;
    return (
      <AppBar className={classes.appBar} position="fixed">
        <Toolbar className={classes.navBar}>
          <div style={{ display: 'flex' }}>
            <Link to="/">
              <IconButton
                style={{ alignSelf: 'center' }}
                color="secondary"
                title="Home"
              >
                <Dashboard />
              </IconButton>
            </Link>
            <Button onClick={this.handlePendentesClick} color="inherit">
              Notas pendentes
            </Button>
            <Button onClick={this.handleGlossarioClick} color="inherit">
              Glossário
            </Button>
            <Button onClick={this.handleReportingClick} color="inherit">
              Reporting
            </Button>
            <Button onClick={this.handlePlanilhaClick} color="inherit">
              Planilha
            </Button>
          </div>

          <div style={{ textAlign: 'center', display: 'flex' }}>
            <Typography style={{ paddingTop: 15, color: 'white' }}>
              Versão 2020.03
            </Typography>
            <IconButton
              title="Logoff"
              onClick={() => {
                this.logoff();
              }}
            >
              <ExitToApp color="error" />
            </IconButton>
          </div>
        </Toolbar>
      </AppBar>
    );
  }
}

const styles = {
  appBar: {
    background: '#2e2d2d',
    opacity: 0.9,
  },
  navBar: {
    display: 'flex',
    justifyContent: 'space-between',
    margin: 0,
    padding: 5,
    minHeight: 0,
  },
};

const mapStateToProps = (state) => {
  return {
    parametros: state.parametros,
  };
};

export default withOktaAuth(
  withStyles(styles)(connect(mapStateToProps, {})(CustomAppBar))
);

@GabrielMoscone
Copy link
Author

Maybe i discovered the error, when i add a button to the authService.login() the website start working again or with a wait function.

But exist someway to do that without use a button or a wait function?
Because my application just can used by authenticated persons and i need to call the function automatically

@shuowu
Copy link
Contributor

shuowu commented Sep 2, 2020

@Dark-Games Exactly. Looks like you introduced auth_okta.js to evaluate isAuthenticated based on only accessToken, but the login behavior is duplicated with the one from SecureRoute, which triggers the protection logic.

I would suggest to only keep one approach to handle app authState, the way from react-sdk to use <Security> and <SecureRoute> or your auth_okta.js, but not both together.

If you are using the okta-react way, you can customize how the sdk evaluate authState by providing customized isAuthenticated callback to component. https://github.com/okta/okta-oidc-js/tree/master/packages/okta-react#security

@ashokraghu14
Copy link

ashokraghu14 commented Sep 9, 2020

@Dark-Games Could you please explain what was the issue exactly, because I'm also getting the same issue when I clear my cache. Sometimes it works. I'm using both custom login and okta-hosted-log(tile-login).

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