5

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?

15
  • The first assumption would be that your websocket server doesn't have an SSL certificate, and as such cannot run WSS. Commented Jan 3, 2020 at 15:14
  • @JoãoSoares I got an ssl key and an ssl certificate using OpenSSL. Commented Jan 3, 2020 at 15:18
  • Have you tested that your WSS is working properly on a different client that isn't your Flutter app? Commented Jan 3, 2020 at 15:21
  • @JoãoSoares I tried with Postman, but it doesn't work either way, neither with ws nor with wss, even when with ws and Flutter it works. Commented Jan 3, 2020 at 15:34
  • There's definitely something odd going on there, but you need to make sure your server is working properly before moving on to seeing if there's a problem on your Flutter app. Commented Jan 3, 2020 at 15:36

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.