I was working on a Flutter web app that stores the backend API authentication credentials as cookies. The web app is hosted on localhost
during development, but the API backend is still hosted on the production web server. Chrome blocks the cookies from the API backend according to the production web server's CORS policy. The production web server also requires automatic upgrade of HTTP to HTTPS.
Motivation - I needed a proxy that can:
- Redirect the Flutter dev server URL for the web app to HTTPS.
- Use a self-signed CA to dynamically generate a TLS certificate for the production web server's domain.
- Intercept and redirect URL's for the web app to Flutter's dev server
- Forward API backend URL's to the production web server
I want to be able to start the proxy from a single command so I did not want to use any existing man-in-the-middle HTTPS proxies that may require complicated install and setup, so I wrote a new proxy in Go, tailored for the Flutter web app development use case.
go install github.com/erdichen/flutterproxy@latest
flutterproxy genca --cert=secret/cert.pem --key=secret/key.pem
Chrome on Linux uses the nssdb
certificate database from Firefox.
- Install
certutil
sudo apt install libnss3-tools
- Add the fake CA's certificate to the current user's CA certificate store
certutil -d $HOME/.pki/nssdb -A -n "Fake CA" -t "CT,c,c" < secret/cert.pem
- Delete the fake CA after testing
certutil -d $HOME/.pki/nssdb -D -n "Fake CA"
Import the fake CA's certificate by pressing Shift-Command-I
(⇧⌘I) or clicking the Create a new keychain item.
button to select the secret/cert.pem
file.
NOTE: The new CA certificate applies to all applications. Keep the secret/key.pem
file safe or remove the fake CA certficate after testing.
flutterproxy run --cert=secret/cert.pem --key=secret/key.pem --host_pair=yoursite.com:443,127.0.0.1:7777 --prefix_pair=yoursite.com:443,/api
Explanation of the flags:
--cert=secret/cert.pem
- the fake CA certificate--key=secret/key.pem
- the fake CA private key--host_pair=yoursite.com:443,127.0.0.1:7777
- redirectyoursite.com
to the Flutter dev server--prefix_pair=yoursite.com:443,/api
- forward requests with the/api
path prefix to the production web server
flutter run -d chrome --web-port=7777 \
--web-browser-flag=--proxy-server=http://127.0.0.1:9999 \
--web-browser-flag=--proxy-bypass-list="<-loopback>" \
--web-browser-flag=--disable-web-security \
--web-browser-flag=--allow-running-insecure-content
Explanation of the flags:
-d chrome
- run the app on Chrome--web-port=7777
- start the dev server at port 7777--web-browser-flag=--proxy-server=http://127.0.0.1:9999
- set the Chrome proxy server URL--web-browser-flag=--proxy-bypass-list="<-loopback>"
- do not proxy the proxy server URL--web-browser-flag=--disable-web-security
- enable the--allow-running-insecure-content
flag--web-browser-flag=--allow-running-insecure-content
- allow mixed content since the Flutter debugger connection is an insecure WebSocket endpoint