Authentication Service

Supporting multiple authentication platforms is a very daunting task for gamer server developers. iFun Engine provides server-side authentication for major platforms and features to retrieve friend lists and nicknames. Authenticating a user with external platforms such as Facebook requires a two-step implementation for the client-side and the server-side. Most external platforms provide client-side authentication, but not server-side user authentication. Thus, the game client must authenticate with the provided SDK of the platform and receive an authentication token from the authentication server, and send the token to the game server, which must validate the received token. The server-side implementation of authentication may become a burden for the game developer as the number of supported platforms increase. iFun Engine simplifies authentication and provides it as a service.

iFun Engine-Authenticator Agent

This agent is fully in charge of authentication in iFun Engine. When a iFun Engine game requires authentication, it sends an authentication request to this agent. The iFun Engine-authenticator agent supports the following external authentication platforms. (We plan to continuously increase the number of supported external platforms.)

  • Facebook

  • Twitter

Installation

When developing a game server with iFun Engine, you can set use_authenticator to false as explained here to work in test mode. You can install later if you are evaluating or in the early stages of development and don’t need real authentication.

Install the iFun Engine auto-configuration package as explained here and install with the following commands.

$ sudo apt-get update
$ sudo apt-get install funapi-authenticator1

Modify to enabled=1 in the file opened with the following command.

$ sudo vim /usr/share/funapi-authenticator/manifests/src/MANIFEST.json

Start the service with the following command. (The log is created in /var/log/funapi/funapi-authenticator1/)

$ sudo service funapi-authenticator1 start

Configuration

Open the configuration file as below and modify the appropriate values.

$ sudo vim /usr/share/funapi-authenticator/manifests/src/MANIFEST.json

Usage

You can either use the provided iFun Engine API (if developing the game server with iFun Engine) or the independent HTTP Interface (RESTful API). Refer to the following sections.

MANIFEST.json Configuration

To use the iFun Engine server-side authentication service, you need to start the funapi-authenticator agent, and configure the iFun Engine game to use this agent. See the MANIFEST.json section and the description below to configure authentication.

  • Component name: AuthenticationClient

  • Arguments

    • use_authenticator: Set as true or false. If set as false, funapi-authenticator will bypass authentication and deem all authentication requests as successful. This is useful for the developer to bypass authentication and test the game in a local environment.

    • remote_authenticator_ip_address: Set the IP address of funapi-authenticator. The default value is used if not set.

    • remote_authenticator_port: Set the port of iFun Engine-Authenticator. The default value is used if not set.

Usage Example

We’ll see how authentication works in iFun Engine games through an example. The following example is for Facebook authentication. For authentication with Facebook, the game client connects to the Facebook authentication server, inputs the Facebook ID and password, and receives an “access token”. When the game client sends the access token to the game server, the server can validate the access token in the following maner.

Facebook: Synchronous method to validate client authentication

To validate authentication at the server with the synchronous method, call the function AuthenticateSync() as below.

#include <funapi.h>

using namespace fun;

// Assume we receive the Facebook uid and access_token from the client.
void example(const string &fb_uid, const string &fb_access_token) {
  // With Facebook, you can get the authentication key from the access token.
  // Use the iFun Engine utility function MakeFacebookAuthencationKey.
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // iFun Engine provides a single authentication request interface regardless
  // of authentication type.
  // Below is to create an account authentication request.
  // The first argument is the type of the authentication platform.
  AccountAuthenticationRequest req("Facebook", fb_uid, auth_key);

  // The variable to receive the authentication response.
  AccountAuthenticationResponse rep;

  // Call the synchronous version of the function.
  if (not AuthenticateSync(req, &rep)) {
    // Error case.
    LOG(ERROR) << "authentication system error";
    return;
  }

  // Not an error, but failed authentication.
  // This includes cases where the client sends a fake access token.
  if (not rep.success) {
    // login failure
    LOG(INFO) << "login failed. code(" << rep.reason_code << "),"
              << "description(" << rep.reason_description << ")";
    return;
  }

  // Authentication succeeded.
  LOG(INFO) << "login success";
}
using funapi;

// Assume we receive the Facebook uid and access_token from the client.
public void example(string fb_uid, string fb_access_token)
{
  // With Facebook, you can get the authentication key from the access token.
  // Use the iFun Engine utility function MakeFacebookAuthencationKey.
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // iFun Engine provides a single authentication request interface regardless
  // of authentication type.
  // Below is to create an account authentication request.
  // The first argument is the type of the authentication platform.
  Authentication.AccountAuthRequest req =
      new Authentication.AccountAuthRequest (
          "Facebook", fb_uid, auth_key);

  // The variable to receive the authentication response.
  Authentication.AccountAuthResponse rep;

  // Call the synchronous version of the function.
  if (!Authentication.AuthenticateSync (req, out rep))
  {
    // Error case.
    Log.Error ("authentication system error");
    return;
  }

  // Not an error, but failed authentication.
  // This includes cases where the client sends a fake access token.
  if (!rep.Success)
  {
    Log.Info ("login failed. code({0}), description({1})",
              rep.ReasonCode, rep.ReasonDescription);
    return;
  }

  // Authentication succeeded.
  Log.Info ("login success");
}

Facebook: Asynchronous method to validate client authentication

Developers who prefer asynchronous calls can use Authenticate() instead of AuthenticateSync() as below.

#include <funapi.h>

using namespace fun;


// In the asynchronous method, iFun Engine calls the registered callback
// function when the result is ready.
// Define the callback function.
void OnLogin(
    const string &fb_uid,
    const AccountAuthenticationRequest &request,
    const AccountAuthenticationResponse &response,
    const bool &error) {
  // This is an error at the authentication server.
  if (error) {
    // system error
    LOG(ERROR) << "authentication system error";
    return;
  }

  // Not an error, but failed authentication.
  // This includes cases where the client sends a fake access token.
  if (not response.success) {
    // login failure
    LOG(INFO) << "login failed. code(" << response.reason_code << "),"
              << "description(" << response.reason_description << ")";
    return;
  }

  // Authentication succeeded.
  LOG(INFO) << "login success: " << fb_uid;
}


// Assume we receive the Facebook uid and access_token from the client.
void example(const string &fb_uid, const string &fb_access_token) {
  // With Facebook, you can get the authentication key from the access token.
  // Use the iFun Engine utility function MakeFacebookAuthencationKey as in the
  // synchronized version.
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // iFun Engine provides a single authentication request interface regardless
  // of authentication type.
  // Below is to create an account authentication request.
  AccountAuthenticationRequest req("Facebook", fb_uid, auth_key);

  // Define the callback function to be called when the authentication result is ready.
  // Create a functor with bind().
  AuthenticationResponseHandler callback = bind(&OnLogin, fb_uid, _1, _2, _3);

  // Request authentication validation with the asynchronous method. Send the authentication request and callback function as arguments.
  Authenticate(request, callback);
}
using funapi;

// In the asynchronous method, iFun Engine calls the registered callback
// function when the result is ready.
// Define the callback function.
public void OnLogin(
    string fb_uid,
    Authentication.AccountAuthRequest request,
    Authentication.AccountAuthResponse response,
    bool error)
{
  if (error)
  {
    // system error
    Log.Error ("authentication system error");
    return;
  }

  if (!response.Success)
  {
    // Not an error, but failed authentication.
    // This includes cases where the client sends a fake access token.
    Log.Info ("login failed. code({0}), description({1})",
              response.ReasonCode, response.ReasonDescription);
    return;
  }

  // Authentication succeeded.
  Log.Info ("login success");
}

// Assume we receive the Facebook uid and access_token from the client.
public void example(string fb_uid, string fb_access_token)
{
  // With Facebook, you can get the authentication key from the access token.
  // Use the iFun Engine utility function MakeFacebookAuthencationKey as in the
  // synchronized version.
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // iFun Engine provides a single authentication request interface regardless
  // of authentication type.
  // Below is to create an account authentication request.
  Authentication.AccountAuthRequest req = new
      Authentication.AccountAuthRequest ("Facebook", fb_uid, auth_key);

  // Request authentication validation with the asynchronous method. Send the authentication request and callback lambda function as arguments.
  Authentication.Authenticate (
      req,
      (Authentication.AccountAuthRequest request,
       Authentication.AccountAuthResponse response,
       bool error) => {
    OnLogin(fb_uid, request, response, error);
  });
}

Facebook: Synchronous method to retrieve the friend list

Now, let’s retrieve the friend list. The example below uses the synchronous method. The asynchronous method is similar, but call GetPersonalInfo() instead of GetPersonalInfoSync().

#include <funapi.h>

using namespace fun;

// Assume we receive the Facebook uid and access_token from the client.
void example(const string &fb_uid, const string &fb_access_token) {
  // With Facebook, you can get the authentication key from the access token.
  // Use the iFun Engine utility function MakeFacebookAuthencationKey.
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // Create the personal info request message.
  // The first argument is the type of the authentication platform.
  AccountPersonalInfoRequest req("Facebook", fb_uid, auth_key);
  AccountPersonalInfoResponse rep;

  // Retrieve personal info with the synchronous method.
  if (not GetPersonalInfoSync(req, &rep)) {
    // A system error has occurred.
    LOG(ERROR) << "authentication system error";
    return;
  }

  // Not an error, but failed authentication.
  // This includes cases where the client sends a fake access token.
  if (not rep.success) {
    // login failure
    LOG(INFO) << "request failed. code(" << rep.reason_code << "),"
              << "description(" << rep.reason_description << ")";
    return;
  }

  // The request was successful.
  for (int i = 0; i < rep.friends.size(); ++i) {
    LOG(INFO) << "friend : " << rep.friends[i].id();
  }
}
using funapi;

// Assume we receive the Facebook uid and access_token from the client.
public void example(string fb_uid, string fb_access_token)
{
  // With Facebook, you can get the authentication key from the access token.
  // Use the iFun Engine utility function MakeFacebookAuthencationKey.
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // Create the personal info request message.
  // The first argument is the type of the authentication platform.
  Authentication.AccountPersonalInfoRequest req =
      new Authentication.AccountPersonalInfoRequest (
          "Facebook", fb_uid, auth_key);

  Authentication.AccountPersonalInfoResponse rep;

  // Retrieve personal info with the synchronous method.
  if (!Authentication.GetPersonalInfoSync(req, out rep))
  {
    // A system error has occurred.
    Log.Error ("authentication system error");
    return;
  }


  // Not an error, but failed authentication.
  // This includes cases where the client sends a fake access token.
  if (!rep.Success) {
    // login failure
    Log.Info ("login failed. code({0}), description({1})",
              rep.ReasonCode, rep.ReasonDescription);
    return;
  }

  // The request was successful.
  foreach (PlayerAccount account in rep.Friends)
  {
    Log.Info (account.Id);
  }
}

iFun Engine-Authenticator HTTP Interface

You can use the funapi-authenticator agent independently, without using the iFun Engine API. As specified below, you can set each parameter in JSON format in the body of an HTTP post request and send it to the funapi-authenticator.

Test authentication

POST /v1/authentication/test
Request JSON Object
  • player_id (string) – player_id. all id value will be authenticated

Response JSON Object
  • result (integer) –

    • 0: authentication success

    • 1: authentication failure

    • 2: incorrect parameters

    • other: other errors

  • description (string) – error description

Facebook authentication

POST /v1/authentication/facebook
Request JSON Object
  • player_id (string) – Facebook uid

  • access_token (string) – Facebook access token

Response JSON Object
  • result (integer) –

    • 0: authentication success

    • 1: authentication failure

    • 2: incorrect parameters

    • other: other errors

  • description (string) – error description

IP authentication

POST /v1/authentication/ipaddress
Request JSON Object
  • player_id (string) – All id value will be authenticated

  • ip (string) – IP address

Response JSON Object
  • result (integer) –

    • 0: authentication success

    • 1: authentication failure

    • 2: incorrect parameters

    • other: other errors

Example - Facebook Authentication

$ telnet localhost 12801
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
POST /v1/authentication/facebook HTTP/1.1
Content-Length: xx

{"player_id": "123...456", "access_token": "CAACEdEose0cBANPFe..........tIyVFo09wZDZD"}
HTTP/1.1 200 OK
content-length: 32
content-type: application/json

{"result": 0, "description": ""}

Test friend list retrieval

POST /v1/personalinfo/test
Request JSON Object
  • player_id (string) – player id, in test authentication, any id value is successful

Response JSON Object
  • result (integer) –

    • 0: success

    • 1: authentication failure

    • 2: incorrect parameters

    • other: other errors

  • description (string) – error description

  • friends (string[]) – friend list

Facebook friend list retrieval

POST /v1/personalinfo/facebook
Request JSON Object
  • player_id (string) – Facebook uid

  • access_token (string) – Facebook access token

Response JSON Object
  • result (integer) –

    • 0: success

    • 1: authentication failure

    • 2: incorrect parameters

    • other: other errors

  • description (string) – error description

  • friends (string[]) – friend list

Example - Facebook friend list retrieval

$ telnet localhost 12801
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
POST /v1/personalinfo/facebook HTTP/1.1
Content-Length: xx

{"player_id": "123...456", "access_token": "CAACEdEose0cBANPFe..........tIyVFo09wZDZD"}
HTTP/1.1 200 OK
content-length: 32
content-type: application/json

{"result": 0, "description": "", "friends": ["xx...x", "xx...x", ...,"xx...x"]}