getUserMedia - Secure Origins

In the latest release of Google Chrome, Google has enforced a rule that they had previously stated they would which requires that any page requesting camera or microphone access through "getUserMedia" be delivered from localhost or a server serving pages with HTTPS. [1], [2]

HTTPS

HTTPS is a "secure" version of HTTP. It uses SSL or TLS to encrypt the contents of HTTP. Traditionally it has been used for banking and other more sensitive content, now it's use is widespread.

Normally to serve pages with HTTPS you need to get certificate that verifies your identity from a Certificate Authority.

More about Public Key Cryptography: Public Key Cryptography: Diffie-Hellman Key Exchange

Unfortunately, a real certificate form a CA requires time, money, and a domain for your site. Being that these are 3 things that we don't have at the moment.. let's use a "self-signed certificate". Here are the steps:

Create a private key:

openssl genrsa -out my-key.pem 2048
This command generates a 2048 bit key (saved as my-key.pem) that can be used to encrypt data (such as web pages)

Create a Certificate Signing Request:

openssl req -new -sha256 -key my-key.pem -out my-csr.pem
This command generates a file which is normally sent to a Certificate Authority to have them verify your identity and issue you an SSL certificate. We are going to be confirming our own identity to the information here doesn't have to be as accurate as it would otherwise have to be.

Here is how I answered the questions:
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:Brooklyn
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Live Web
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:Live Web
Email Address []:Shawn.Van.Every@nyu.edu

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:			
		
The CSR will be saved as my-csr.pem.

Finally we "self-sign" by running this command:

openssl x509 -req -in my-csr.pem -signkey my-key.pem -out my-cert.pem
This generates a certificate file called my-cert.pem that we can use in combination with the private key to enable SSL/HTTPS on our Node.js servers.

Using HTTPS with Node.js

Fortunately, node has a drop in replacement for the "http" library called "https". Here is a basic https webserver example:

var https = require('https');
var fs = require('fs'); // Using the filesystem module
var url =  require('url');

var options = {
  key: fs.readFileSync('my-key.pem'),
  cert: fs.readFileSync('my-cert.pem')
};

function handleIt(req, res) {
	var parsedUrl = url.parse(req.url);

	var path = parsedUrl.pathname;
	if (path == "/") {
		path = "index.html";
	}

	fs.readFile(__dirname + path,

		// Callback function for reading
		function (err, fileContents) {
			// if there is an error
			if (err) {
				res.writeHead(500);
				return res.end('Error loading ' + req.url);
			}
			// Otherwise, send the data, the contents of the file
			res.writeHead(200);
			res.end(fileContents);
  		}
  	);	
	
	// Send a log message to the console
	console.log("Got a request " + req.url);
}

var httpServer = https.createServer(options, handleIt);
httpServer.listen(8080);


			
If you use this in place of a regular http version of our servers, and the user allows the self-signed certificate, the getUserMedia requests will work once again.