Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to authenticate Game Center User from 3rd party node.js server

I've been trying to get the new iOS Game Center GKPlayer method, generateIdentityVerificationSignatureWithCompletionHandler, working so we can securely rely on the Game Center credentials for authentication. We're using Node.js as the backend server, and I've been trying to verify the signature but to no avail.

Here is the code on the server side that I have - if there's anyone who can chime in on what's missing, that'd be appreciated. The question has been answered somewhat here: How to authenticate the GKLocalPlayer on my 'third party server'?, but Node.js hasn't specifically been tackled. Note that the code below doesn't ensures the validity of the certificate with a signing authority (yet).

    //Client sends the payload below
    //json.playerId - UTF-8 string
    //json.bundleId - UTF-8 string
    //json.timestamp - Hex string
    //json.salt - base64 encoded
    //json.publicKeyURL - UTF-8 string
    //json.signature - base64 encoded
    var json = JSON.parse(req.body);
    console.log(JSON.stringify(json));
    //get the certificate
    getCertificate(json.publicKeyURL, function(cert){
        //read file from fs for now, since getCertificate returns cert in DER format
        fs = require('fs');
        fs.readFile('/gc-sb.pem', 'utf8', function (err,data) {
            if (err) {
                console.log(err);
            } else {
                console.log(data);
            var verifier = crypto.createVerify("sha1WithRSAEncryption");
            verifier.write(json.playerId, "utf8");
            verifier.write(json.bundleId, "utf8");
            verifier.write(json.hexTimestamp, "hex");
            verifier.write(json.salt, "base64");
            var isValid = verifier.verify(data, json.signature, "base64");

            console.log("isvalid: " + isValid);
            }
        });
    });

One thing I've found using the crypto module in node.js is that it seems to want the certificate in PEM format, and I believe the format retrieved from Apple is DER. Until I figure out how to convert the DER file to PEM, I've temporarily converted it using

openssl x509 -in gc-sb.cer -inform der -outform pem -out gc-sb.pem

The main thing for me is being able to validate the signature first. Conversion of the certificate and verifying it against a signing authority will come later :)

EDIT: I've figured it out - I was hashing the playerId, bundleId, timestamp and salt, and then using the hashed value as information to verify. I needed to just put those pieces of information into the verifier to verify without the SHA-1 hash (since the verifier will be taking care of it). I've modified the code above to "make it work". Hope this helps anyone that comes across this.

like image 841
Simon Tang Avatar asked Feb 05 '14 07:02

Simon Tang


People also ask

What is Node JS and how does it work?

One of the major functionalities of Node.js applications is that it never buffers any data. Node.js can be easily built and deployed on various platforms like Windows, MAC, and Linux. So, now let’s dig a little deeper into Node.js and understand its internal architecture further in this Node.js tutorial.

What are the local modules of Node JS?

The local modules of Node.js are custom modules that are created locally by user/developer in the application. These modules can include various functionalities bundled into distinct files and folders which can be easily distributed in the Node.js community using NPM. These modules are loaded in a similar way to core modules.

How to handle user authentication&authorization?

User authentication & authorization is one of the important part of any web application. There are several kinds of way to handle authentication, we can rely on third party service like Passport.

What is passport in Node JS?

What Is Passport.js? Passport.js (or Passport) is an authentication middleware for NodeJS that provides more than 500 strategies for authenticating users including passport-local which uses a username and password. This tutorial uses passport-local and passport-jwt to secure routes.


2 Answers

Here is how you can validate gamecenter identity using nodejs. It convert also the der certificate format to pem on the fly.

var crypto = require('crypto');
var request = require('request');
var ref = require('ref');

var token = require('./test.json');

request({url: token.publicKeyURL, encoding: null}, function (error, response, body) {
    if (!error && response.statusCode == 200) {

        var verifier = crypto.createVerify("sha1");
        verifier.update(token.playerId, "utf8");
        verifier.update(token.bundleId, "utf8");

        var buf = ref.alloc('uint64');
        ref.writeUInt64BE(buf, 0, token.timestamp.toString());

        verifier.update(buf);
        verifier.update(token.salt, 'base64');

        var pmd = '-----BEGIN CERTIFICATE-----';

        var base64 = body.toString('base64');
        var size = base64.length;

        for (var i = 0; i < size; i = i + 64) {
            var end = i + 64 < size ? i + 64 : size;
            pmd = pmd + '\n' + base64.substring(i, end);
        }

        pmd = pmd + '\n-----END CERTIFICATE-----';

        var valid = verifier.verify(pmd, token.signature, "base64");

        console.log(valid);

    }
});
like image 121
xjodoin Avatar answered Oct 21 '22 09:10

xjodoin


It's seems there's a npm package for it. https://github.com/maeltm/node-gamecenter-identity-verifier

like image 37
remaerd Avatar answered Oct 21 '22 08:10

remaerd