Cannot connect to wss with Flutter

2,133

If you happen to bumped in this GitHub post, you can follow the temporary fix from this comment:

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}

void main(){
    HttpOverrides.global = new MyHttpOverrides();
    runApp(new MyApp());
}

It works on local ip with self signed certificate.

To elaborate, here is the same solution:

Just for the sake of clarity specially for the newcomers to Flutter/Dart, here is what you need to do in order to enable this option globally in your project:

  1. In your main.dart file, add or import the following class:
HttpClient createHttpClient(SecurityContext? context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;   } } ```
  1. In your main function, add the following line after function definition:

HttpOverrides.global = MyHttpOverrides();

This comment was very helpful to pass through this matter, and please note that...

This should be used while in development mode, do NOT do this when you want to release to production, the aim of this answer is to make the development a bit easier for you, for production, you need to fix your certificate issue and use it properly, look at the other answers for this as it might be helpful for your case.

Another thing worth mentioning, signed certificates are available for free now (https://letsencrypt.org/).

Also, I think the Flutter team is working to enhance the documentation for better reference regarding this issue. It is being tracked here.

Share:
2,133
CrystalSpider
Author by

CrystalSpider

Student at University of Milano-Bicocca (Università degli Studi di Milano-Bicocca, UNIMIB), Front-end developer at Lynx S.p.A., passionate about IT, programming, logic, AI and quantum computing.

Updated on December 16, 2022

Comments

  • CrystalSpider
    CrystalSpider over 1 year

    I wrote a wss server in Nodejs and now I'm trying to connect to such server using Flutter.

    Here's the code in NodeJS:

    //Dependencies
    const WebSocket = require('ws');
    const fs = require('fs');
    const https = require('https');
    //Dependencies
    
    //Server declarations
    const server = https.createServer({
        key: fs.readFileSync('pathTo/key.pem'),
        cert: fs.readFileSync('pathTo/cert.pem')
    });
    server.listen(xxxx);
    const wss = new WebSocket.Server({ server });
    //Server declarations
    
    wss.on('connection', function connection(ws)
    {
      ws.on('message', function incoming(message)
      {
          console.log('Received: ' + message);
          ws.send('echo: ' + message);
       });
       ws.send('Connected!');
    });
    

    Here's the code in Flutter:

    import 'package:flutter/material.dart';
    import 'package:flutter/foundation.dart';
    import 'package:flutter/services.dart';
    import 'package:web_socket_channel/io.dart';
    import 'package:connectivity/connectivity.dart';
    import 'package:web_socket_channel/web_socket_channel.dart';
    
    class MyApp extends StatelessWidget
    {
      @override
      Widget build(BuildContext context)
      {
        final title = 'LumenApp Prototype';
        IOWebSocketChannel channel;
        try
        {
          channel = new IOWebSocketChannel.connect('wss://xxxxxxxx.xxx.xxx:xxxx/');
          MyHomePageState.noResponse = false;
        }
        catch(e)
        {
          MyHomePageState.noResponse = true;
        }
        return MaterialApp(
          title: title,
          theme: ThemeData(
            primarySwatch: Colors.blue,
            primaryTextTheme: TextTheme(
              title: TextStyle(
                color: Colors.yellow[600],
              ),
            ),
          ),
          home: MyHomePage(
            title: title,
            channel: channel,
          ),
        );
      }
    }
    

    The error on Flutter is: WebSocketChannelException: WebSocketChannelException: HandshakeException: Handshake error in client (OS Error: CERTIFICATE_VERIFY_FAILED: self signed certificate(handshake.cc:354))

    This happens inside this function:

      void initPlatformState()
      {
        widget.channel.stream.listen((message)
        {
          setState(() { noResponse = false; });
          //Handle message...
        },
        onError: (error)
        {
          print(error);
          if(mounted)
          {
            setState((){ noResponse = true;});
          }
        },
        onDone: ()
        {
          if(mounted)
          {
            setState((){ noResponse = true; });
          }
        });
      }
    

    I used a self-signed certificate server-side made with openssl.
    Any idea how to solve this?