Search code examples
flutterdartcookieswebviewflutterwebviewplugin

Pass auth cookie to WebView - Flutter


I'm building a WebView based app.
Authenticating occurs inside the app without using webview. I'm making a request to server and getting a session token from auth cookie.
When user passes authentication page the app pushes him to the main page. There are some buttons that leads to the WebView.

The problem is that I need to pass my auth cookie to the WebView.

However when WebView appears it immediately redirects me to web app authentication page instead of catalog page. But I need catalog page.

I used webview_flutter plugin to pass cookies:

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:skin_technology/core/session_data/repo/session_data_service.dart';
import 'package:webview_flutter/webview_flutter.dart';

class CatalogWebView extends StatelessWidget {
  CatalogWebView({Key? key}) : super(key: key);

  final Completer<WebViewController> _controller =
      Completer<WebViewController>();

  static const url = 'https://clubskt.ru/client/catalog';

  Future<String?> _getToken() async {
    final token = (await SessionDataService.sessionData)?.token;
    if (token == null) return null;
    return token;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
      bottom: false,
      child: FutureBuilder<String?>(
          future: _getToken(),
          builder: (BuildContext context, AsyncSnapshot<String?> snapshot) {
            if (snapshot.hasData) {
              final token = snapshot.data;
              if (token == null) return Container();

              return WebView(
                debuggingEnabled: true,
                initialUrl: url,
                javascriptMode: JavascriptMode.unrestricted,
                initialCookies: const [
                  WebViewCookie(
                    name: 'auth',
                    value:
                        'eyJhbGciOzI1NiJ9.eyJzd...',
                    domain: 'https://clubskt.ru',
                  ),
                ],
                onWebViewCreated: (controller) async {
                  _controller.complete(controller);
                },
              );
            }
            return Container();
          }),
    ));
  }
}

I also tried to pass cookie throw the headers in the same plugin:

return WebView(
                debuggingEnabled: true,
                javascriptMode: JavascriptMode.unrestricted,
                onWebViewCreated: (controller) async {
                  controller.loadUrl(url, headers: {
                    'Cookie': 'auth=eyJhbGciOiJIUzI1NiJ9.eyJzd...'
                  });
                  _controller.complete(controller);
                },
              );
            }

but the result is the same.

I opened developer tools in order to test request. Status code is 304.
enter image description here But when I'm trying to reproduce the same request in postman, I get a status code 200. I'm passing a valid token throw auth_cookie.
enter image description here Is this a problem?


Solution

  • Finally I found a solution!

    import 'dart:async';
    import 'dart:io';
    
    import 'package:flutter/material.dart';
    
    import 'package:skin_technology/core/session_data/repo/session_data_service.dart';
    import 'package:webview_cookie_manager/webview_cookie_manager.dart';
    import 'package:webview_flutter/webview_flutter.dart';
    
    class WebViewScreen extends StatelessWidget {
      WebViewScreen({Key? key, required this.url}) : super(key: key);
    
      final String url;
      WebViewController? webController;
    
      final cookieManager = WebviewCookieManager();
    
      Future<String?> _getToken() async {
        final token = (await SessionDataService.sessionData)?.token;
        if (token == null) return null;
        return token;
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              elevation: 0,
              backgroundColor: Colors.transparent,
            ),
            body: Stack(
              children: [
                Container(
                  color: Colors.amber,
                ),
                SafeArea(
                  bottom: false,
                  child: FutureBuilder<String?>(
                      future: _getToken(),
                      builder:
                          (BuildContext context, AsyncSnapshot<String?> snapshot) {
                        if (snapshot.hasData) {
                          final token = snapshot.data;
                          if (token == null) return Container();
    
                          return WebView(
                            javascriptMode: JavascriptMode.unrestricted,
                            initialUrl: url,
                            onWebViewCreated: (controller) {
                              cookieManager.setCookies([
                                Cookie('auth', token)
                                  ..domain = 'clubskt.ru'
                                  ..httpOnly = false,
                              ]);
                              webController = controller;
                            },
                          );
                        }
                        return Container();
                      }),
                ),
              ],
            ));
      }
    }