How to properly create a secure web server with Dart?

Issue

This a typical code provided by Dart for a server using Shelf package :

import 'dart:io';

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_router/shelf_router.dart';

// Configure routes.
final _router = Router()
  ..get('/', _rootHandler)
  ..get('/echo/<message>', _echoHandler);

Response _rootHandler(Request req) {
  return Response.ok('Hello, World!\n');
}

Response _echoHandler(Request request) {
  final message = request.params['message'];
  return Response.ok('$message\n');
}

void main(List<String> args) async {
  // Use any available host or container IP (usually `0.0.0.0`).
  final ip = InternetAddress.anyIPv4;

  // Configure a pipeline that logs requests.
  final _handler = Pipeline().addMiddleware(logRequests()).addHandler(_router);

  // For running in containers, we respect the PORT environment variable.
  final port = int.parse(Platform.environment['PORT'] ?? '8080');
  final server = await serve(_handler, ip, port);
  print('Server listening on port ${server.port}');
}

What/How should it need to be modified to support secure connections (HTTPS) only?

I don’t really understand about certificates, so if you could give a detail explanation about how to generate/buy them and how to link them to server or any reference for dummies it’d be great.

P.S.: My host is a Linux distro (Manjaro) running the following Docker containers: a file server (Dart with Shelf) and GraphQL server (Postgraphile). Do I need to make configurations for every service running in my host?

Solution

First, my thanks to @KevinMoore for his answer, but it is not complete as I wished, so this is my answer:

According to Dart help the above code is modified like this:

import 'dart:io';

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_router/shelf_router.dart';

// Configure routes.
final _router = Router()
  ..get('/', _rootHandler)
  ..get('/echo/<message>', _echoHandler);

Response _rootHandler(Request req) {
  return Response.ok('Hello, World!\n');
}

Response _echoHandler(Request request) {
  final message = request.params['message'];
  return Response.ok('$message\n');
}

SecurityContext getSecurityContext() { // Bind with a secure HTTPS connection
  final chain = Platform.script.resolve('certificates/server_chain.pem').toFilePath();
  final key = Platform.script.resolve('certificates/server_key.pem').toFilePath();
  
  return SecurityContext()
  ..useCertificateChain(chain)
  ..usePrivateKey(key, password: 'dartdart');
}

void main(List<String> args) async {
  // Use any available host or container IP (usually `0.0.0.0`).
  final ip = InternetAddress.anyIPv4;

  // Configure a pipeline that logs requests.
  final _handler = Pipeline().addMiddleware(logRequests()).addHandler(_router);

  // For running in containers, we respect the PORT environment variable.
  final port = int.parse(Platform.environment['PORT'] ?? '443');
  final server = await serve(_handler, ip, port, securityContext: getSecurityContext());
  print('Server listening on port ${server.port}');
}

For that code I’m using certificates and password provided by Dart Team in its repository for educational purposes only.

If you need certificates for your server in production, you can get them for free with Let’s Encrypt.

These videos can be useful about how to get and use these certificates:

This tutorial (in Japanese) also is a good reference.

Answered By – Ουιλιαμ Αρκευα

Answer Checked By – Jay B. (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *