Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: login through a webview

I'm pretty new to Flutter. Is there a way to login through a webview into our app?

e.g. In the first page there is this webview where we can do the login. After we logged in, the app takes us in a second page where we can do other stuff.

like image 434
Little Monkey Avatar asked Jul 26 '18 14:07

Little Monkey


People also ask

How do I use WebView to Flutter?

With the WebView Flutter plugin you can add a WebView widget to your Android or iOS Flutter app. On iOS the WebView widget is backed by a WKWebView, while on Android the WebView widget is backed by a WebView. The plugin can render Flutter widgets over the web view.

Is Flutter based on WebView?

WebView for FlutterA Flutter plugin that provides a WebView widget. On iOS the WebView widget is backed by a WKWebView; On Android the WebView widget is backed by a WebView.


2 Answers

In my app I use instagram implicit authentification, which implies to login user in webview and get token from redirect url. I use flutter_webview_plugin Next code builds WebviewScaffold with login url. And it listen for url changes. So when response is redirected to my redirectUrl it parses url to get token. Then you need to save token for following requests in app.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => new _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final flutterWebviewPlugin = new FlutterWebviewPlugin();

  StreamSubscription _onDestroy;
  StreamSubscription<String> _onUrlChanged;
  StreamSubscription<WebViewStateChanged> _onStateChanged;

  String token;

  @override
  void dispose() {
    // Every listener should be canceled, the same should be done with this stream.
    _onDestroy.cancel();
    _onUrlChanged.cancel();
    _onStateChanged.cancel();
    flutterWebviewPlugin.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();

    flutterWebviewPlugin.close();

    // Add a listener to on destroy WebView, so you can make came actions.
    _onDestroy = flutterWebviewPlugin.onDestroy.listen((_) {
      print("destroy");
    });

    _onStateChanged =
        flutterWebviewPlugin.onStateChanged.listen((WebViewStateChanged state) {
      print("onStateChanged: ${state.type} ${state.url}");
    });

    // Add a listener to on url changed
    _onUrlChanged = flutterWebviewPlugin.onUrlChanged.listen((String url) {
      if (mounted) {
        setState(() {
          print("URL changed: $url");
          if (url.startsWith(Constants.redirectUri)) {
            RegExp regExp = new RegExp("#access_token=(.*)");
            this.token = regExp.firstMatch(url)?.group(1);
            print("token $token");

            saveToken(token);
            Navigator.of(context).pushNamedAndRemoveUntil(
                "/home", (Route<dynamic> route) => false);
            flutterWebviewPlugin.close();
          }
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    String loginUrl = "someservise.com/auth";

    return new WebviewScaffold(
        url: loginUrl,
        appBar: new AppBar(
          title: new Text("Login to someservise..."),
        ));
  }
}
like image 66
Marica Avatar answered Sep 20 '22 13:09

Marica


You can use my plugin flutter_inappwebview, which is a Flutter plugin that allows you to add inline WebViews or open an in-app browser window and has a lot of events, methods, and options to control WebViews.

You can use onLoadStart or onLoadStop events to detect URL changes. For example, you can get the token:

  • from the url
  • from cookies
  • from localStorage

Full example:

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  runApp(new MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: InAppWebViewPage()
    );
  }
}

class InAppWebViewPage extends StatefulWidget {
  @override
  _InAppWebViewPageState createState() => new _InAppWebViewPageState();
}

class _InAppWebViewPageState extends State<InAppWebViewPage> {
  InAppWebViewController webView;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("InAppWebView")
        ),
        body: Container(
            child: Column(children: <Widget>[
              Expanded(
                child: Container(
                  child: InAppWebView(
                    initialUrl: "https://myUrl.com",
                    initialHeaders: {},
                    initialOptions: InAppWebViewWidgetOptions(
                      inAppWebViewOptions: InAppWebViewOptions(
                        debuggingEnabled: true,
                      ),
                      androidInAppWebViewOptions: AndroidInAppWebViewOptions(
                        domStorageEnabled: true,
                        databaseEnabled: true,
                      ),
                    ),
                    onWebViewCreated: (InAppWebViewController controller) {
                      webView = controller;
                    },
                    onLoadStart: (InAppWebViewController controller, String url) {

                    },
                    onLoadStop: (InAppWebViewController controller, String url) async {
                      if (url.startsWith("https://myUrl.com/auth-response")) {
                        // get your token from url
                        RegExp regExp = new RegExp("access_token=(.*)");
                        String token = regExp.firstMatch(url)?.group(1);
                        print(token);

                        // or using CookieManager
                        CookieManager cookieManager = CookieManager.instance();
                        Cookie token = await cookieManager.getCookie(url: "https://myUrl.com/auth-response", name: "access_token");
                        print(token.value);

                        // or using javascript to get access_token from localStorage
                        String token = await controller.evaluateJavascript(source: "localStorage.getItem('access_token')");
                        print(token);
                      }
                    },
                  ),
                ),
              ),
            ]))
    );
  }
}
like image 22
Lorenzo Pichilli Avatar answered Sep 22 '22 13:09

Lorenzo Pichilli