Account Kit for Web (JavaScript)

Setting up Account Kit in your web app has the following steps:

1. Prerequisites

2. Configure Login HTML page

3. Example PHP implementation on your web server

4. Example Node.js implementation on your web server


Also see Next Steps for optional customizations you can perform.

1. Prerequisites

Before you begin integrating Account Kit into your app, make sure you have completed the following prerequisites.

A. Create a Developer Account

If you don't have a Facebook developer account, create one by clicking the button below.

Your Facebook developer account gives you access to developer tools and allows you to create Facebook apps.

Already have a Facebook developer account? Skip to the next step.

Create Developer Account

B. Get a Facebook App ID

Account Kit for the web requires a Facebook app ID. Follow the steps in the Getting Started, or to use Quick Start, click the button below.

Quick Start for Website

C. Choose Your App Settings

Choose whether to allow email and SMS login, and choose security settings for your app. For more information on choosing your acesss token setting, see Access Tokens, and for information on choosing your app secret setting, see Using the Graph API.

Choose Your App Settings

2. Configure Login HTML page

In the login page (for example, login.html) that your web application serves, you can set up Account Kit by following these configuration steps:

Import the Account Kit Javascript SDK by adding this line in your <head> tag:

<!-- HTTPS required. HTTP will give a 403 forbidden response -->
<script src="https://sdk.accountkit.com/en_US/sdk.js"></script>

Hotlinking SDK: We only support linking the JS SDK via the above URL. This script will fetch the SDK loader, which will load the latest SDK either from accountkit.com or from your browser's cache.

For cases where you want to host the SDK via your own server, there is a grace lifetime of 24 hours. After this grace period, the SDK will start issuing warnings, and stop working after 7 days.

You may change the localization of the Account Kit dialogs by specifying standard language and region codes in place of en_US in the <script> tag's url attribute. For a list of legal language and region values, see the list of supported languages.

Setup the UI input elements in your page in your <body> tag:

<input value="+1" id="country_code" />
<input placeholder="phone number" id="phone_number"/>
<button onclick="smsLogin();">Login via SMS</button>
<div>OR</div>
<input placeholder="email" id="email"/>
<button onclick="emailLogin();">Login via Email</button>

Initialize Account Kit, and set up JS handler for login callback. Note that version is the Account Kit API version, which is different from the Facebook API version. You can find the Account Kit API version in the Account Kit section of your app dashboard. For information about the AccountKit.init function used in this example, see Account Kit SDK for Javascript - Reference.

<script>
  // initialize Account Kit with CSRF protection
  AccountKit_OnInteractive = function(){
    AccountKit.init(
      {
        appId:"{{FACEBOOK_APP_ID}}", 
        state:"{{csrf}}", 
        version:"{{ACCOUNT_KIT_API_VERSION}}",
        fbAppEventsEnabled:true
      }
    );
  };

  // login callback
  function loginCallback(response) {
    if (response.status === "PARTIALLY_AUTHENTICATED") {
      var code = response.code;
      var csrf = response.state;
      // Send code to server to exchange for access token
    }
    else if (response.status === "NOT_AUTHENTICATED") {
      // handle authentication failure
    }
    else if (response.status === "BAD_PARAMS") {
      // handle bad parameters
    }
  }

  // phone form submission handler
  function smsLogin() {
    var countryCode = document.getElementById("country_code").value;
    var phoneNumber = document.getElementById("phone_number").value;
    AccountKit.login(
      'PHONE', 
      {countryCode: countryCode, phoneNumber: phoneNumber}, // will use default values if not specified
      loginCallback
    );
  }


  // email form submission handler
  function emailLogin() {
    var emailAddress = document.getElementById("email").value;
    AccountKit.login(
      'EMAIL',
      {emailAddress: emailAddress},
      loginCallback
    );
  }
</script>

CSRF protection: The {{csrf}} placeholder above should be replaced with a non-guessable value which should originate in the app's server, and be passed to the login flow. It is returned back to the app client unchanged, and the app client can pass it back to server to verify the match with the original value.

For extra explanatory information about errors you encounter during testing, you can add debug:true to the init() parameters.

3. Example PHP implementation on your web server

The following is an example PHP implementation for your web server.

You may choose to use any technology (such as Node.js or Python) to implement your server. The PHP implementation below is a suggested example.

Set up a page to handle successful logins and exchange authorization codes for access tokens (login_success.php).

<?php
// Initialize variables
$app_id = '<facebook_app_id>';
$secret = '<app_secret>';
$version = '<account_kit_api_version>'; // 'v1.1' for example

// Method to send Get request to url
function doCurl($url) {
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $data = json_decode(curl_exec($ch), true);
  curl_close($ch);
  return $data;
}

// Exchange authorization code for access token
$token_exchange_url = 'https://graph.accountkit.com/'.$version.'/access_token?'.
  'grant_type=authorization_code'.
  '&code='.$_POST['code'].
  "&access_token=AA|$app_id|$secret";
$data = doCurl($token_exchange_url);
$user_id = $data['id'];
$user_access_token = $data['access_token'];
$refresh_interval = $data['token_refresh_interval_sec'];

// Get Account Kit information
$me_endpoint_url = 'https://graph.accountkit.com/'.$version.'/me?'.
  'access_token='.$user_access_token;
$data = doCurl($me_endpoint_url);
$phone = isset($data['phone']) ? $data['phone']['number'] : '';
$email = isset($data['email']) ? $data['email']['address'] : '';
?>

Configure an HTML Page for Successful Login

In the successful login page (login_success.php), you can display Account Kit information as follows:

<head>
  <title>Account Kit PHP App</title>
</head>
<body>
  <div>User ID: <?php echo $user_id; ?></div>
  <div>Phone Number: <?php echo $phone; ?></div>
  <div>Email: <?php echo $email; ?></div>
  <div>Access Token: <?php echo $user_access_token; ?></div>
  <div>Refresh Interval: <?php echo $refresh_interval; ?></div>
</body>

In the login callback on your login page (login.html), send a Post request to your successful login page (login_success.php).

<form id="login_success" method="post" action="/login_success.php">
  <input id="csrf" type="hidden" name="csrf" />
  <input id="code" type="hidden" name="code" />
</form>

<script>
  function loginCallback(response) {
    if (response.status === "PARTIALLY_AUTHENTICATED") {
      document.getElementById("code").value = response.code;
      document.getElementById("csrf").value = response.state;
      document.getElementById("login_success").submit();
    }
  }
</script>

4. Example Node.js implementation on your web server

The following is an example Node.js implementation for your web server.

Configure Node.js packages in package.json:

{
  "name": "ServeStaticContent",
  "version": "0.0.1",
  "dependencies": {
    "body-parser": "^1.15.0",
    "express": "3.x",
    "guid": "0.0.12",
    "mustache": "^2.2.1",
    "querystring": "^0.2.0",
    "request": "^2.69.0"
  }
}

Initialize variables in server.js:

const fs = require('fs');
const Guid = require('guid');
const express = require('express');
const bodyParser = require("body-parser");
const Mustache  = require('mustache');
const Request  = require('request');
const Querystring  = require('querystring');
const app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
  
var csrf_guid = Guid.raw();
const account_kit_api_version = '{{ACCOUNT_KIT_API_VERSION}}';
const app_id = '{{FACEBOOK_APP_ID}}';
const app_secret = '{{ACCOUNT_KIT_APP_SECRET}}';
const me_endpoint_base_url = 'https://graph.accountkit.com/{{ACCOUNT_KIT_API_VERSION}}/me';
const token_exchange_base_url = 'https://graph.accountkit.com/{{ACCOUNT_KIT_API_VERSION}}/access_token'; 

In server.js, define the logic to serve your login page (login.html):

function loadLogin() {
  return fs.readFileSync('dist/login.html').toString();
}

app.get('/', function(request, response){
  var view = {
    appId: app_id,
    csrf: csrf_guid,
    version: account_kit_api_version,
  };

  var html = Mustache.to_html(loadLogin(), view);
  response.send(html);
});

Next, in server.js, define the logic to serve a page for a successful login (login_success.html).

Note that the JS SDK for the web supports only authentication by authorization code. (For information about authorization by access tokens, available for Android and iOS, see Access Tokens.)

function loadLoginSuccess() {
  return fs.readFileSync('dist/login_success.html').toString();
}

app.post('/login_success', function(request, response){

  // CSRF check
  if (request.body.csrf === csrf_guid) {
    var app_access_token = ['AA', app_id, app_secret].join('|');
    var params = {
      grant_type: 'authorization_code',
      code: request.body.code,
      access_token: app_access_token
    };
  
    // exchange tokens
    var token_exchange_url = token_exchange_base_url + '?' + Querystring.stringify(params);
    Request.get({url: token_exchange_url, json: true}, function(err, resp, respBody) {
      var view = {
        user_access_token: respBody.access_token,
        expires_at: respBody.expires_at,
        user_id: respBody.id,	
      };

      // get account details at /me endpoint
      var me_endpoint_url = me_endpoint_base_url + '?access_token=' + respBody.access_token;
      Request.get({url: me_endpoint_url, json:true }, function(err, resp, respBody) {
        // send login_success.html
        if (respBody.phone) {
          view.phone_num = respBody.phone.number;
        } else if (respBody.email) {
          view.email_addr = respBody.email.address;
        }
        var html = Mustache.to_html(loadLoginSuccess(), view);
        response.send(html);
      });
    });
  } 
  else {
    // login failed
    response.writeHead(200, {'Content-Type': 'text/html'});
    response.end("Something went wrong. :( ");
  }
});

Configure an HTML Page for Successful Login

In the login successful page (e.g. login_success.html) that your web application serves, you can display Account Kit information as follows:

<!doctype html>
<head>
  <meta charset="utf-8">
  <title>AccountKitJS App</title>
</head>

<body>
  <div>Logged In to Account Kit:</div>
  <div>User Token {{user_access_token}}</div>
  <div>User Token Expires at {{expires_at}}</div>
  <div>User Id {{user_id}}</div>
  <div>User phone: {{phone_num}}</div>
  <div>User email: {{email_addr}}</div>
</body>

In the login callback on your login page (login.html), send a Post request to your successful login page (login_success.html).

<form id="login_success" method="post" action="/login_success">
  <input id="csrf" type="hidden" name="csrf" />
  <input id="code" type="hidden" name="code" />
</form>

<script>
  function loginCallback(response) {
    if (response.status === "PARTIALLY_AUTHENTICATED") {
      document.getElementById("code").value = response.code;
      document.getElementById("csrf").value = response.state;
      document.getElementById("login_success").submit();
    }
  }
</script>

Finally, in server.js, configure your web server to listen for requests:

app.listen(process.env.PORT);