10

This dependency supposedly supports web, but the implementation to listen for the callback and retrieve the token is missing. After digging around for the last three days, a few people suggested that it would work using the dart:html library, with onMessage, and postMessage functions.

Here's my setup:

import 'dart:html' as html;
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:oauth2/oauth2.dart' as oauth2;
import 'package:url_launcher/url_launcher.dart';

class AuthYoutube {
var httpClient = http.Client();
  Future<oauth2.Client> getClient() async {
    var grant = new oauth2.AuthorizationCodeGrant(
        CLIENT_ID, AUTH_DOMAIN, AUTH_TOKEN,
        secret: secret);
    var authorizationUrl =
        grant.getAuthorizationUrl(REDIRECT_URI, scopes: scopes);

    html.window.open(authorizationUrl.toString(), "open");
    Completer<LinkedHashMap<dynamic, dynamic>> completer = Completer();
    html.window.onMessage.listen((event) async {
      completer.complete(event.data as LinkedHashMap<dynamic, dynamic>);
    });
    Uri responseUri;
    completer.future.then((value) {
      responseUri = Uri.parse(value.toString());
      return grant.handleAuthorizationResponse(responseUri.queryParameters);
    });
  }

} And the separate route set as the callback URL:

class Special extends StatelessWidget {
  static String route = "/special";
  @override
  Widget build(BuildContext context) {
    final loc = Uri.parse(html.window.location.href);
    final code = loc.queryParameters["code"];
    print("code $code");
    html.window.postMessage(code, html.window.location.origin);
    return Text("All done");
  }
}

What ends up happening is the auth token shows up in the address bar at the last step. I can see it in there after ?code=, but it doesn't get printed out. The listen method gets triggered 5-6 times throughout the entire flow (while clicking on "allow" in the other window). In the console, I only get this one error:

Uncaught (in promise) Error: Bad state: Future already completed
    at Object.throw_ [as throw] (errors.dart:212)
    at _AsyncCompleter.new.complete (future_impl.dart:43)
    at authYT.dart:41
    at Generator.next (<anonymous>)
    at runBody (async_patch.dart:84)
    at Object._async [as async] (async_patch.dart:123)
    at authYT.dart:40
    at Object._checkAndCall (operations.dart:324)
    at Object.dcall (operations.dart:329)
    at html_dart2js.dart:37246
Eight Rice
  • 816
  • 7
  • 24
  • I have the same issue to figure out so thanks! Can the '$code' be set into a cookie or local storage if it can't be printed out? – javshak Dec 14 '20 at 17:40
  • How did you implement the navigation for your SpecialPage, usually when you are redirecting to your flutter web app it loads everything from scratch even if you mentionned a specific URL. – Guillaume Roux Feb 20 '21 at 22:46
  • 1
    These might help: https://robinjanke1.medium.com/oauth2-with-flutter-web-e7a2b0dac7f3 and https://dev.to/okrad/oauth2client-implement-oauth2-clients-with-flutter-4jjl – Nigel Sheridan-Smith Mar 24 '21 at 20:03
  • Also https://github.com/MaikuB/flutter_appauth/issues/70#issuecomment-783382765 with a sample ZIP – Nigel Sheridan-Smith Mar 24 '21 at 20:21
  • 1
    Did you get this working? I am having a similar issue. The linked pages in the other comments look promising but ultimately don't have enough detail or the code doesn't even compile. – Stephen Gibson May 14 '21 at 20:07

2 Answers2

1

You can capture the access token in the onGenerateRoute method through the URL.

Here’s a link to the blog that does it properly: https://aws.plainenglish.io/oauth2-in-flutter-web-using-aws-cognito-f7051be92bdf

  • Thanks for the article. How can I pass a Cognito username and password using this method? – gurnisht Jan 25 '22 at 14:07
  • 1
    You will be able to pass username and password through the Cognito Hosted UI which will be presented to you when the app directs to auth URL after pressing sign in. This makes me realise I should add visual aids in that blog. Will update it soon – Muhammad Shahrukh Jan 26 '22 at 18:30
1

There is a new plugin Flutter plugin that supports the complete authentication flow in web and also on mobile:

https://pub.dev/packages/flutter_web_auth

Jeff S.
  • 888
  • 12
  • 17