tools icon indicating copy to clipboard operation
tools copied to clipboard

The authorization code has already been received

Open dumihi313 opened this issue 5 years ago • 4 comments

Unhandled Exception: Bad state: The authorization code has already been received

How to avoid this issue

dumihi313 avatar Jun 17 '20 10:06 dumihi313

I am facing the same issue. The process looks as follows:

  1. The user opens the app and is not authenticated.
  2. The logic to authenticated the user is triggered. This involves the following two calls:
    var grant = oauth2.AuthorizationCodeGrant(CLIENT_ID,
        Uri.parse(AUTHORIZATION_ENDPOINT), Uri.parse(TOKEN_ENDPOINT));

    var authorizationUrl = grant.getAuthorizationUrl(Uri.parse(REDIRECT_URL),
        scopes: ["openid", "offline_access"])
  1. The user is than redirected to the login page of the authentication server (in my case Keycloak)
  2. After providing the correct credentials the user is logged in and can start using the app.
  3. The user logs out
    I achieve this by deleting the locally stored credentials and calling .close() on the client.
  4. If the user logs in immediately again the exact same code as for the first login process is executed. The exception is thrown on the following call:
_client = await grant.handleAuthorizationResponse(
            Uri.parse(event.toString()).queryParameters);

If the user restarts the app between logging out and logging in again it works as expected. I assume the issue is that the logout is incomplete. Therefore the State of AuthorizationCodeGrant is finished and the exception is thrown.

How do I properly logout the user and reset the State?

The complete login method looks like this:

  @override
  Future<void> login() async {
    dev.log("start login process");

    var grant = oauth2.AuthorizationCodeGrant(CLIENT_ID,
        Uri.parse(AUTHORIZATION_ENDPOINT), Uri.parse(TOKEN_ENDPOINT));

    var authorizationUrl = grant.getAuthorizationUrl(Uri.parse(REDIRECT_URL),
        scopes: ["openid", "offline_access"]);

    dev.log("redirect user to login");
    if (await canLaunch(authorizationUrl.toString())) {
      await launch(authorizationUrl.toString());
    }

    dev.log("listening for authentication callback");
    getLinksStream().listen((event) async {
      if (event.toString().startsWith(REDIRECT_URL)) {
        _client = await grant.handleAuthorizationResponse(
            Uri.parse(event.toString()).queryParameters);
        dev.log("client created");
        await authDataSource.save(_client.credentials);
        _authEventsController.sink
            .add(UserAuthenticatedEvent(UserModel(name: "test")));
      }
    });
  }

ChristianHuff-DEV avatar Sep 13 '20 09:09 ChristianHuff-DEV

for anyone facing the same, you need to close the client, close the grant and the subscription, i.e.: with your every logout call the disponse() function:

  void dispose() {
    grant?.close();
    client?.close();
    sub?.cancel();
  }

ahmed-alshurafa avatar Dec 30 '23 23:12 ahmed-alshurafa

I am still having this problem even though doing this and I am using the same package. is there any other way?

bwaobikeze avatar Mar 10 '24 15:03 bwaobikeze

Any solution on this??

zoualmamy avatar Dec 20 '24 10:12 zoualmamy