flutter_cookie_bridge 1.3.1 copy "flutter_cookie_bridge: ^1.3.1" to clipboard
flutter_cookie_bridge: ^1.3.1 copied to clipboard

A Flutter plugin that synchronizes cookies between network requests and WebViews.

example/lib/main.dart

import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cookie_bridge/web_view_callback.dart';
import 'package:flutter_cookie_bridge/network_manager.dart';
import 'package:flutter_cookie_bridge/flutter_cookie_bridge.dart';
import 'package:flutter_cookie_bridge_example/DeviceInfoManager.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:package_info_plus/package_info_plus.dart';

final cookieBridge = FlutterCookieBridge();

void main() async {
  await dotenv.load(fileName: "lib/.env");
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

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

class MyHome extends StatefulWidget {
  const MyHome({super.key});

  @override
  MyHomeState createState() => MyHomeState();
}

class MyHomeState extends State<MyHome> {
  final String? baseUrl = dotenv.env['BASE_URL'];

  // Your controller
  final TextEditingController prospectIDcontrolller = TextEditingController();

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Login')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 420),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                TextField(
                  controller: prospectIDcontrolller,
                  textInputAction: TextInputAction.done,
                  decoration: const InputDecoration(
                    labelText: "Prospect ID",
                    border: OutlineInputBorder(),
                  ),
                ),
                const SizedBox(height: 16),
                SizedBox(
                  width: double.infinity,
                  child: ElevatedButton(
                    onPressed: () {
                      final id = prospectIDcontrolller.text.trim();
                      if (id.isEmpty) {
                        ScaffoldMessenger.of(context).showSnackBar(
                          const SnackBar(content: Text("Please enter Prospect ID")),
                        );
                        return;
                      }
                      _openWebView1(context,id);
                    },
                    child: const Text('Login'),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

  Future<String> createToken() async {
    final String clientId = dotenv.env['KID']!;

    final Map<String, Object> headers = {
      'kid': clientId,
      'typ': 'JWT',
      'alg': 'HS256',
    };


    final Map<String, String> attributes = {
      'name': "name",
      'photo': "",
    };
    const Duration expirationDuration = Duration(milliseconds: 300000);
    final clientSecret = dotenv.env['CLIENT_SECRET'];
    final jwt = JWT(
      {
        'email': "email",
        'phone': "phone",
        'attributes': attributes,
        'module': "module",
      },
      header: headers,
    );

    String token = await jwt.sign(
      SecretKey(clientSecret!),
      expiresIn: expirationDuration,
    );

    print("Token generated FROM client side is: $token");

    return token;
  }

  Future<void> open(BuildContext context, String module, String token,
      WebViewCallbackFunction? callback) async {
    try {
      String bank = "";

      if (module.contains("banking/")) {
        int startIndex = module.indexOf("banking/") + "banking/".length;
        String temp = module.substring(startIndex);
        int endIndex = temp.indexOf("/");
        bank = endIndex == -1 ? temp : temp.substring(0, endIndex);
      }
     // await _loginAndNavigateToWebView(module, bank, context, token, callback!);
    } catch (e) {
      debugPrint('Error opening webview: $e');
      rethrow;
    }
  }

  // Future<void> _loginAndNavigateToWebView(
  //   String module,
  //   String bank,
  //   BuildContext context,
  //   String token,
  //   WebViewCallbackFunction callback,
  // ) async {
  //   try {
  //     await cookieBridge.clearSession();
  //     final tokenResponse = await _networkManager.request(
  //         url: "tokenUrl",
  //         method: 'POST',
  //         body: {"token": token});
  //
  //     print("token Response is: $tokenResponse");
  //
  //     if (tokenResponse?.statusCode == 200 &&
  //         tokenResponse?.data['code'] == "USER_LOGIN_SUCCESS") {
  //       final cookies = await cookieBridge.checkSession();
  //
  //       if (cookies.isEmpty) {
  //         throw Exception('Session not established after login');
  //       }
  //
  //       await _checkDeviceBinding(context, bank, module, callback);
  //     } else {
  //       debugPrint('Error during login: $tokenResponse');
  //       // rethrow;
  //     }
  //   } catch (e) {
  //     debugPrint('Unexpected error: $e');
  //     rethrow;
  //   }
  // }

  Future<void> _checkDeviceBinding(BuildContext context, String bank,
      String url, WebViewCallbackFunction callback) async {
    // if (LibraryConstants.deviceBindingEnabled) {
    //   // TODO Build the device binding flow
    // } else {
    //Skip device binding and bind device to session
  //  await _setupDeviceSession(context, bank, url, callback);
    // }
  }

  // Future<void> _setupDeviceSession(BuildContext context, String bank,
  //     String url, WebViewCallbackFunction callback) async {
  //   try {
  //     Map<String, String> deviceInfo = await _deviceInfoManager.getDeviceInfo();
  //     final packageInfo = await PackageInfo.fromPlatform();
  //     if (kDebugMode) {
  //       print("Device Info: $deviceInfo");
  //       print("Package Info: $packageInfo");
  //     }
  //     final bindDeviceToSessionResponse = await _networkManager.request(
  //         url:
  //             "sessionUrl",
  //         method: 'POST',
  //         body: {
  //           "manufacturer": deviceInfo["manufacturer"]!,
  //           "model": deviceInfo["model"]!,
  //           "device_uuid": deviceInfo["device_uuid"]!,
  //           "os": Platform.isAndroid ? "Android" : "iOS",
  //           "os_version": deviceInfo["os_version"]!,
  //           "app_version": packageInfo.version,
  //         });
  //     print("bind device to session response $bindDeviceToSessionResponse");
  //     if (bindDeviceToSessionResponse?.statusCode == 200) {
  //       await _openWebView(prospectId);
  //     } else {
  //       debugPrint(
  //           'Error setting up device session: $bindDeviceToSessionResponse');
  //       await _openWebView(prospectId);
  //     }
  //   } catch (e) {
  //     debugPrint('Error setting up device session: $e');
  //     rethrow;
  //   }
  // }

  Future<void> _openWebView1(BuildContext context, String prospectId) async {
    final cookiesBefore = await cookieBridge.checkSession();
    print('Cookies before WebView: $cookiesBefore');
    final webView = await cookieBridge.getWebView(
      url:
        "https://uat2cbp.dcbbank.com/api/user/mock?prospect_id=6aa0a5c5-a813-4030-aa9e-fa9866cb826b&kid=PC7WzxKenHnnR58qkhGH4tt02WH1c1VI&redirect_url=https://spense.money&device_binded=true",
      callback: (WebViewCallback action) {
        switch (action.type) {
          case WebViewCallbackType.redirect:
            print(
                "--------------- Redirect Redirected with status main: ${action.status}");
            break;
          case WebViewCallbackType.logout:
            print("--------------- Redirect User logged out main");
            break;
        }
      },
      whitelistedUrlsAndroid: [
       "https://uat2cbp.dcbbank.com",
        "y",
        "https://10.210.176.124",
        "https://10.73.227.183"
        "api.razorpay.com",
        "https://sbmsmartbankinguat.sbm.bank.in",
        "https://10.38.23.183"
      ],
      whitelistedUrlsIos: [
        "whitlelistedUrls",
        "https://10.210.176.124",
        "api.razorpay.com",
        "https://sbmsmartbankinguat.sbm.bank.in",
        "https://10.38.23.183"
      ],
      hostName: "https://sbmsmartbankinguat.sbm.bank.in",
    );
    Navigator.of(context).push(MaterialPageRoute(
      builder: (context) => webView,
    ));
  }

  // Future<void> _loginAndNavigate(String prospectId) async {
  //   String token = await createToken();
  //
  //   open(context, "module", token,
  //       (WebViewCallback action) {
  //     switch (action.type) {
  //       case WebViewCallbackType.redirect:
  //         print("Redirected with status: ${action.status}");
  //         break;
  //       case WebViewCallbackType.logout:
  //         print("User logged out");
  //         break;
  //     }
  //   });
  //   _openWebView(prospectId);
  // }