Giter Site home page Giter Site logo

Comments (8)

lokesh-coder avatar lokesh-coder commented on August 28, 2024 2

Facing same issue. Temporarily I am using flutter_web_auth package for custom inline chrome tab.

import 'package:flutter_web_auth/flutter_web_auth.dart';

void signInWithGoogle() async {
    final url = Uri.https('DOMAIN', '/auth/v1/authorize', {
      'provider': 'google',
      'redirect_to': "myapp://callback",
    });

    final String callbackUri = await FlutterWebAuth.authenticate(
        url: url.toString(), callbackUrlScheme: "myapp");

    final session =
        await gotrueClient.getSessionFromUrl(Uri.parse(callbackUri));

    print("User email => ${session.data?.user?.email}");
  }
}

Redirect url myapp://callback should be added in either URI_ALLOW_LIST or Additional Redirect URLs in supabase Auth settings.

In android/app/src/main/AndroidManifest.xml, I added the schema for closing the tab and returning to app,

<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" >
    <intent-filter android:label="flutter_web_auth"  android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="myapp" />
    </intent-filter>
</activity>

from gotrue-dart.

matevarga avatar matevarga commented on August 28, 2024 2

So I got this working with some hacks -- I don't think this should be the way but leaving a comment here just in case someone needs it.
Goal: to acquire a GoTrue Session after using Google Auth through Supabase in a Flutter Web app.
Problem: we need to launch an OAuth2 login screen, then catch the callback, extract the parameters.

Tools:

  • url_launcher
  • auto_router

Flow:

  1. User initiates login by e.g. pressing a button

  2. Google OAuth login is initiated

  3. App receives a callback with access_token, etc.

  4. These tokens are parsed and used to create a GoTrue session

  5. is relatively simple:

void initiateSignIn() async {
    var po = ProviderOptions(redirectTo: "http://localhost:5000/callback.html");
    final response =
        await supabase.auth.signIn(provider: Provider.google, options: po);

    _logger.i("response: $response");

    if (await canLaunch(response.url!)) {
      print('response.url: ${response.url}');
      await launch(response.url!, webOnlyWindowName: "_self");
    } else {
      throw 'Could not launch ${response.url}';
    }
  }

Using this method in a service can help you starting the login process. The problem (that doesn't happen with e.g. Firebase) that you can't wait in the same method for the login to succeed.

What proved to be a bit tricky to me (I'm a Flutter novice): 3 and 4.

In order to receive a callback:

  • create a new widget, let's call it AuthPage
class AuthPage extends StatelessWidget {
  final String? accesstoken;
  final String? refreshtoken;
  final String? tokentype;
  final int? expiresin;
  final String? providertoken;
  final String? errordescription;

  AuthPage(
      {@QueryParam('access_token') this.accesstoken,
      @QueryParam('refresh_token') this.refreshtoken,
      @QueryParam('expires_in') this.expiresin,
      @QueryParam('token_type') this.tokentype,
      @QueryParam('provider_token') this.providertoken,
      @QueryParam('error_description') this.errordescription});
// other code follows

This will enable the AutoRouter to pass the callback parameters to the widget.

  • set up a new AutoRoute:
@MaterialAutoRouter(
  routes: [
    AutoRoute(page: AuthPage, path: "/auth")
// [.. etc ..]
  • put a new HTML file into the web folder, e.g. callback.html
<html>
    <body>
    </body>
    <script>
        var url = window.location.href
        var arr = url.split("/");
        var currentUrl = arr[0] + "//" + arr[2]
        let newUrl = currentUrl + "/#/auth?" + window.location.href.substring((window.location.origin+window.location.pathname).length+1);
        window.location.href = newUrl;
    </script>
</html>

This HTML will strip out the required query params and forward it to the /auth route (i.e. to the AuthPage widget).

In the build method of AuthPage, add a callback to go to some kind of service/etc. that can then use the tokens to create a GoTrue session.

@override
  Widget build(BuildContext context) {
    WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
      some_underlying_service.handleAuthCallback(accesstoken, refreshtoken,
            tokentype, expiresin, providertoken, errordescription);
      }
    });

from gotrue-dart.

lpylpyleo avatar lpylpyleo commented on August 28, 2024

@lokesh-coder Thanks for your solution!
From your idea, I think we can also use deep links on Android and universal links on iOS with uni_links package to capture the callback url. I will have a try.

from gotrue-dart.

matevarga avatar matevarga commented on August 28, 2024

@lokesh-coder thanks for that -- however, how would this work for web apps (where the callback scheme and base url can vary)? Any ideas?

from gotrue-dart.

lokesh-coder avatar lokesh-coder commented on August 28, 2024

@matevarga I haven't checked on web app, but custom callback scheme is only needed for mobile. For web apps, we can directly call the authorize url, like

<a href="https://<domain>/auth/v1/authorize?provider=google&redirect_url=https://callback_url">Login with Google</a>

This will go to OAuth2 consent page and once signed in, it will redirect to callback url with necessary oauth details in callback url query params. like,

https://callback_url?access_token=abc&refresh_token=xyz&type=bearer&...

Generally this callback url will be you app url. You can get the access token from query params and store it in cookie or localStorage and pass it as Authorization header in all calls.

from gotrue-dart.

matevarga avatar matevarga commented on August 28, 2024

@lokesh-coder yep, thanks -- calling the auth endpoint is okay, the issue is that the callback must be caught so some extra hacking is needed in the dart/flutter app so that it can listen for callbacks. (it's not that trivial, I actually don't know yet how to listen to callbacks in flutter web).

from gotrue-dart.

phamhieu avatar phamhieu commented on August 28, 2024

We released a new flutter package to support Supabase 3rd party deeplink authentication: https://pub.dev/packages/supabase_flutter

You can take a look at the example here for reference.

from gotrue-dart.

matevarga avatar matevarga commented on August 28, 2024

We released a new flutter package to support Supabase 3rd party deeplink authentication: https://pub.dev/packages/supabase_flutter

You can take a look at the example here for reference.

It's not clear to me (yet) how the changes solve the existing problems. I'm deciphering the example but the documentation clearly lacks the explanation about how the callback URL is parsed -- the problem has never been that it's difficult to open the provider-specific login page, it was always the callback handling that was painful.

It looks like that the requirement for handling callbacks is the usage of Supabase's own SupabaseAuthState -- the documentation says It helps you handle authentication with deeplink from 3rd party service like Google, Github, Twitter... -- while in reality it doesn't "help", it is "required" if you don't want to implement callback parsing from scratch.

(I am going to be a paid Supabase consumer, so I hope this doesn't come through as whining.)

from gotrue-dart.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.