Connecting to nakama linux server with SSL from client Javascript (browser)

Hello

Sorry for my many questions, but I am very new to Nakama - just discovered it yesterday.

I am trying to run Nakama server on Google Compute Engine as described in the tutorial on your site.
I want to have the secure connection from Unity and client Javascript (browser) with self-signed certificates.

I was able to install an run the server, but unable to connect. I ma getting 503 error.

In the tutorial the author was setting the certificate fingerprint with SSLValidKeyFingerprints, but this was on .NET. I am unable to find how to set these fingerprints in Javascript client.

Also how to do this with REST client? Should I use a request header or query string parameter?

Or should I use some other approach? Do I need to use proper certificate? If so could you please advise which one you would suggest for development.

Thank you

Regards
Darius

Hi @dariuspranskus. Welcome!

I want to have the secure connection from Unity and client Javascript (browser) with self-signed certificates.

I don’t think it’s possible to successfully verify a self-signed certificate within a browser. A certificate requires a chain to a root authority that provides the assurance that the destination is legitimate. You might be able to add an exception to your browser to accept the certificate but this will not be accepted by players.

I am unable to find how to set these fingerprints in Javascript client.

It’s not possible in the JavaScript client because the DOM API does not expose an option to trust particular SSL fingerprints.

Do I need to use proper certificate? If so could you please advise which one you would suggest for development.

Yes you’ll need a proper certificate unless you want to just set an exception in your browser for your self-signed cert. I suggest you use LetsEncrypt which provides free SSL certificates. You will need to get a domain name in that case.

Why do you need to test over an SSL connection at all right now for local development?

Hello.

Thank you for the quick response,

I just wanted to test that functionality. But now switched to unsecure mode and am trying to authenticate with authenticateEmail. I am getting the 400 response error, and the error message is “Bad request”. I just followed the example in the documentation and I am creating a client and am passing an object with email, password and create fields to the authenticateEmail method. I also enabled verbose mode. How can I see what is wrong with my request? I can’t see anything in nakama log on the server and the response error object do not have any detailed information about my error. Thanks for your help.

The server never returns a 400 Bad Request without a reason message. The response body will always contain a detailed error telling you what went wrong if the input was bad. Here’s an example using curl to make the exact request you’re trying to make:

âś— curl http://127.0.0.1:7350/v2/account/authenticate/email\?create\=true --user "defaultkey:" -d '{"email":"foo","password":"bar"}' -v
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 7350 (#0)
* Server auth using Basic with user 'defaultkey'
> POST /v2/account/authenticate/email?create=true HTTP/1.1
> Host: 127.0.0.1:7350
> Authorization: Basic ZGVmYXVsdGtleTo=
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 32
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 32 out of 32 bytes
< HTTP/1.1 400 Bad Request
< Cache-Control: no-store, no-cache, must-revalidate
< Content-Type: application/json
< Date: Fri, 20 Sep 2019 09:14:06 GMT
< Content-Length: 92
< 
* Connection #0 to host 127.0.0.1 left intact
{"error":"Invalid email address format.","code":3,"message":"Invalid email address format."}

The interesting part is the last line (the response body) which tells you exactly why the server rejected the request.

What version of the server and JavaScript client are you using?

Hi Andrei

I am using 2.6.0 version of Nakama server, for I was not able to find the latest 2.7.0 binary on the release page on github. And I am using version 2.01 of @heroiclabs/nakama-js package.

I also installed LetsEncrypt certificate and tried it. Browser identifies the site as secure, but when I try to authenticate I am getting the 503 error and the Response type is CORS. Do I need to include my client address on Nakama server so that it is included in the CORS response header?

Here you can see the error messages as they are consolled out in the browser
https://imgur.com/a/W4alpSp

As you can see the type of both responses is cors. Is this because I am running from browser. I wanna build a game level editor which runs in the browser or electron.

Thanks

Darius

Hello again

I did the request with the REST client, and the error was that the password must be at least 8 characters, and when I used a longer password, I was able to login using my browser app.

The question would be then, why the response object does not provide the detailed information about the error.

I also tried to do do send a request to the secure Nakama with the REST client, and the error was 503 and response was

{
  "error": "all SubConns are in TransientFailure, latest connection error: connection error: desc = \"transport: authentication handshake failed: x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs\"",
  "message": "all SubConns are in TransientFailure, latest connection error: connection error: desc = \"transport: authentication handshake failed: x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs\"",
  "code": 14
}

I was able to find how to retrieve the error message. Let’s close this for now.

For what it’s worth I believe you’re running into this issue https://github.com/heroiclabs/nakama/issues/348

We’re working on improvements as we speak but for now if you want to test SSL it’s best to run a more production-like setup with a SSL-terminating proxy or load balancer in front of Nakama.

1 Like

Just for reference purpose, the way to get the body is to use .json() on error object, and since it returned a promise, we have to wait for its value to become available

errorResponse.json().then(err => {
            console.log(err)
        });

If this is for customers, you are correct.
If this is for you and your development team, you can generate your own certificate authority (a bit of a pain) using openssl, create a cert/key pair, and tell your browser the CA chain is okay.
Just google for making your own CA with openssl.
And google how to add that CA to your browser (I use firefox and brave. Never tried it with IE or edge).