nhost / nhost-dart

Nhost Dart & Flutter packages
https://nhost.io
MIT License
90 stars 33 forks source link

OAuth redirect URI mismatch #111

Closed totzk9 closed 1 year ago

totzk9 commented 1 year ago

I was using Facebook OAuth provider but it's returning a .../facebook/callback?code=... instead of .../facebook/callback?refreshToken=...

completeOAuthProviderSignIn()'s if (!queryArgs.containsKey(refreshTokenQueryParamName)) check returns true because the refreshTokenQueryParamName is incorrect.

const refreshTokenQueryParamName = 'refreshToken'; <~ this should be code instead of refreshToken

dbarrosop commented 1 year ago

callback?code is correct. You can test this sample-website:

https://react-apollo.example.nhost.io/sign-in

if you login with google the last step involves a redirection with the code argument.

I am closing this issue as I think there is nothing to do here but feel free to reopen otherwise.

totzk9 commented 1 year ago

hi @dbarrosop

Allow me to correct you that notice in this Flutter sdk via auth_client.dart::line 570

  @override
  Future<void> completeOAuthProviderSignIn(Uri redirectUrl) async {
    final queryArgs = redirectUrl.queryParameters;
    if (!queryArgs.containsKey(refreshTokenQueryParamName)) {
      return;
    }

    await _refreshSession(queryArgs[refreshTokenQueryParamName]);
  }

the function actually do nothing because the if (!queryArgs.containsKey(refreshTokenQueryParamName)) called since refreshTokenQueryParamName still has refreshToken which is inside types.dart::line 25

which is why I created this PR https://github.com/nhost/nhost-dart/issues/111

but again, I also created a fork of it but ended up a 400 error which I raised in the discord channel

statusCode=400, responseBody={status: 400, message: "refreshToken" with value "AQBRZWt.....4-dHewN-TLo7AwiVFyu1B5n0......AKcAiNE1WOwmxAGlTzUm-..........zd4QioHRVxAuO62H.....n7bkpMIDyTzRTbqUshutcw" fails to match the required pattern: /\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b/, error: invalid-request}
dbarrosop commented 1 year ago

I am reopening the issue to keep with the discussion but I think this is a misunderstanding of how oauth flow works.

  1. When the oauth provider authenticates the users it sends a callback to hasura-auth with the ?code parameter you are referring to.
  2. hasura-auth then validates the code, does a couple of other things and then finally it redirects to the application with the refresh token

You can see the flow here:

https://github.com/nhost/hasura-auth/blob/main/docs/workflows/oauth-providers.md

And you can test the flow yourself here:

https://react-apollo.example.nhost.io/sign-in

So to me what the dart code is doing looks completely fine. I think the actual issue is that you misunderstood which callback was which and you are sending the callback that should go to hasura-auth to your application instead.

If you read this:

https://docs.nhost.io/authentication/sign-in-with-google#create-credentials

You have:

Under Authorized redirect URIs add your OAuth Callback URL from Nhost.

For example:

Screenshot 2023-09-24 at 14 00 47
totzk9 commented 1 year ago

Yes, I've already added the client ID, client Secret and as well as Authorized redirect URIs.

here's sample of the redirectURIs I receive after authenticating with Google or Facebook. https://___.auth.ap-southeast-1.nhost.run/v1/signin/provider/google/callback?code=4%2F0AfJohXmw7p6_mkrvyIpz0G0CWKBWSUvRvZM4LgBptwk2SMeqgGOcKhndRiUzLLZCXVcDfg&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid&authuser=0&prompt=consent#

Everytime I authenticate with a new user, it automatically creates a new user in the auth so that would mean my implementation was correct.

I think the problem is within refreshTokenQueryParamName

dbarrosop commented 1 year ago

I think the problem is within refreshTokenQueryParamName

Why? We have established already that code goes to hasura-auth and refreshToken goes to your dart application, so this is fine:

const refreshTokenQueryParamName = 'refreshToken';

Your dart application should never see the ?code query arg.

totzk9 commented 1 year ago

Ah i see. that makes sense

dbarrosop commented 1 year ago

Ok, cool. Glad we are now on the same page :) I am closing the issue but feel free to reopen if you still think there is an issue here or open a new one if you find something else.