General

JavaScript / Backplane

Backplane Protocol – Overview

The Backplane Protocol is an open source protocol developed to simplify communications between multiple web elements and applications on the same web page. Instead of each element on the page or application using its own scheme to access user data, Backplane-enabled elements listen to a single, common Backplane server for updates.

The Backplane Protocol can publish many different types of messages:

  • Alerting web pages when users have authenticated
  • Activities the user is sharing with a social network

Janrain currently supports version 1.2 of the Backplane Protocol.

Backplane Server – Messages

Overview

The Backplane Server retrieves messages and sends them to Janrain elements on a website, as well as to other Backplane-enabled elements. In Backplane Protocol terms, a Scenario is a protocol extension that defines one or more message types and specifies their semantics, use, and so on.

The following Scenarios are available on the Backplane Protocol:

  • Identity Scenario – Updates all Backplane-compliant web elements with user data once Social Login publishes to a Backplane channel.

Identity Message Rules

Multiple Messages

If there are multiple messages posted to the Backplane Server (as might result from the user refreshing the pages where a sign-in resides), only the latest message will be sent to requesting elements.

Logging Out

Once the user logs out of the Identity Provider, a Logout message is normally sent to the Backplane Channel to update the elements to the user state. If the channel has both (an Identity message followed by a Logout message), the user is considered logged out, and no message will be sent to requesting elements.

Note: Currently, Social Login and Registration do not support the Logout message. The channel on the Backplane Server is reset instead. See the following section Resetting the Channel.

Resetting the Channel

Resetting the channel on the Backplane Server causes the same result as sending a Logout message to the web elements that are listening (the login state and session are ended). Administrators may want to use this method of logout when using Janrain solutions to log out the user independently of the Identity Provider state, or when forcing a new login when a user returns to the site.

Backplane – Add to Your Website

Registration has specific JavaScript settings for adding Backplane to a website. See the Registration JavaScript API backplane* settings for more information.

Demos

Additionally, there are live demos that implement Backplane integration:

Registration has specific JavaScript settings for adding Backplane to a website. See the  Registration JavaScript API Settings  topic for more information.

Demos

Additionally, there are live demos featuring Backplane integration:

Backplane – Add to your Application

Overview

These instructions are for application developers adding Backplane functionality to a standalone application or a web application (as opposed to a website). Once implemented, your element or web app will be configured to listen to a Backplane Server, and can be deployed in any Backplane-enabled site.

Integration Flow

  1. Obtain authentication credentials for your specific bus.
  2. Set up the application to listen for Backplane messages.
  3. Implement a logout.

Integration Instructions

1. Obtain authentication credentials for your specific bus

In the Dashboard, these values are listed as backplane_password and backplane_bus. Copy these values to a text file (or write them down)–you will need them later.

2. Set up the application to listen to Backplane messages

The following code example is used to listen to the Backplane channel; add it to the existing application code.

/* script block continued */
function bpListen() {
  window.escSubscription = Backplane.subscribe(function(backplaneMessage) {
    /*
     * This enclosed function runs when any message is received.
     * Sign in if the message type is correct.
     */
    if (backplaneMessage.type == 'identity/login') {
      yourSignIn(backplaneMessage.payload.identities.entry.accounts[0].openid); //Engage
      yourSignIn(backplaneMessage.payload.identities.entry.id); //Capture
      /*
       * If we had no further interest in Backplane events we could stop listening.
       * Most live deployments would stop listening after sign-in.
       * This would avoid running the sign-in again.
       * If other events are expected another subscription would be made or
       * conditionals would be added to this one for the other message types.
       */
      //Backplane.unsubscribe(window.escSubscription);
    }
  });
  /* Expecting a message type will increase the polling for that type
   * until it is received.
   */
  Backplane.expectMessages('identity/login');
}
/* script block continues */

The example listens for the Backplane identity/login event, which you can use with User Registration’s entity.find API call to get the full profile data. Make sure to use your client_id and client_secret for this call.

3. Retrieve user profile data (Registration only)

When you receive a Backplane event, you’ll want to use the uuid from the event to retrieve the rest of the Janrain profile information. We’ve included a JavaScript example (for client-side) which calls the PHP example (for server-side). At this point, the variable profile will contain the information you need to authenticate the user for your app.

Client-side (JavaScript):

var idUrl = backplaneMessage.payload.identities.entry.accounts[0].identityUrl;
var uuid = idUrl.substr(idUrl.indexOf('uuid=')+5);
var profile = jQuery.get("https://yoursite.domain/getProfile?uuid="uuid"");

Server-side (PHP):

function getProfile ($uuid) {
  $post_data = array(
    'type_name'  => "user",
    'client_id' => [client_id],
    'client_secret' => [secret],
    'filter' => "uuid%3D".$uuid."'",
    'format' => 'json');

  $curl = curl_init();
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_URL, 'https://appname.janraincapture.com/entity.find');
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
  curl_setopt($curl, CURLOPT_HEADER, false);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($curl, CURLOPT_FAILONERROR, true);
  $result = curl_exec($curl);
  if ($result == false){
    echo "n".'Curl error: ' . curl_error($curl);
    echo "n".'HTTP code: ' . curl_errno($curl);
    echo "n"; var_dump($post_data);
  }
  curl_close($curl);

  /* Parse the JSON entity.find response */
  $profile = json_decode($result, true);
  return $profile
4. Implement a logout

One way to handle a logout is to close the channel when it’s no longer needed. This is typically done on user sign-out.

Close a channel by opening a new one to take its place:

/* script block continued */
function bpSignOut() {
  /*
  * Sign out just consists of requesting a new channel and reloading the page.
  */
  Backplane.resetCookieChannel();
  window.location.reload();
  return false;
}
/* finally */
view raw

Another way to handle a logout is to send a logout message on the current bus. For example, instead of changing the channel on logout, you could publish an identity/logout message on the channel.

User Database

Identity Services

Janrain Identity Services offers a website the ability to become a custom OpenID Identity Provider using the site’s existing user authentication framework. This functionality allows existing users to log in using their pre-existing username and password, and when used in conjunction with Janrain Social Login and Single Sign-On features, subsequently be recognized automatically by the site’s entire ecosystem of websites and partner properties.

Your website holds the parent user database, and Janrain Identity Services works behind the scenes, enabling your site to issue portable identities to your users. Identity Services integrates with your website through standard web redirects and HTTPS calls.

Your users’ portable identities can be used by any third party site that has implemented an OpenID consumer system or through Janrain Social Login. Both implementation methods are described in the following sections.

Glossary

  • Authenticating Website (AW) – A website that authenticates the user. An AW is a user interface that is connected to your authentication system.
  • Relying Party (RP) – A website that allows a user to sign in using an independent identity provider. An RP website can be one of your web properties or partner sites that accepts authentication through an independent identity provider.

Prerequisites

  • Website – The destination website.
  • A Janrain Social Login application – Identity Services may be deployed without this, but it requires that the end user implement an OpenID consumer system.
  • Endpoint – Located on the website that can be queried by a GET call.

Configuration Parameters

In order for Janrain to configure Identity Services, the following configuration parameters will need to be exchanged with the customer:

  • OpenID Identifier - The OpenID endpoint used to initiate the login. Example: https://demo.janrainfederate.com. This is usually provided by Janrain, but custom endpoints can be substituted if needed. Custom endpoints must be provided by the customer to Janrain prior to configuration.
  • API Key - A 32-character string used by the AW to identify itself. Provided by Janrain. Warning: This key is private and should not be disclosed.
  • Verify URL - The endpoint that will be used to validate the end user. Identity Services will send a GET to this URL with the authentication request. Must be provided by the customer.
  • PostBack URL - The Authenticating Website will POST to this URL after authenticating the user. Provided by Janrain.
  • Return URL - The customer will redirect the user to this URL after receiving confirmation of successful receipt of user data from Janrain. Provided by Janrain.
  • Home URL - Optional. The home page of the customer used internally by Janrain to identify the customer’s configuration. If not provided, the base URL of the verify URL will be used for identification. This parameter does not impact the user experience.

Identity Services Authentication Flow

  1. INITIATE — RP initiates login by redirecting the user to Janrain’s Identity Services.
  2. GET — A GET redirect to the AW.
  3. UI — The AW performs interaction to authenticate (ask for password).
  4. POST — AW performs an HTTPS POST to Janrain’s Identity Services.
  5. RESPONSE — Janrain returns an HTTP status to the AW (200 or retry).
  6. REDIRECT — The AW performs a redirect to Janrain’s Identity Services.
  7. OPTIONAL — If no_prompt is set to false, the end user has the opportunity to prevent user data from being sent to RP.
  8. RESPONSE — Janrain will redirect the user to the RP with an assertion of success or failure.

    Traditional Login Integration

Initiate

The RP initiates login by redirecting the user to Janrain’s Identity Services.

If the RP is using Janrain Social Login, the RP accomplishes this by adding the OpenID button to Social Login.

If the RP is not using Janrain Social Login, the RP must redirect the user to the OpenID endpoint and include all necessary OpenID parameters. For more information on this redirect, see the Appendix.

GET

Identity Services will redirect the user’s browser to the AW with a GET request and a set of parameters. The AW needs to accept the GET from the user’s browser at the Verification URL and will need to save or process some of these parameters:

  • request_id — This identifies the request and will need to be returned by the AW in the response to Janrain.
  • requested_attributes — These are the attributes requested by Janrain Social Login or by the RP. These should be retrieved by the AW and returned in the response to Janrain.

Here is an example GET request sent from Janrain to the AW:

http://localhost/login.php?realm=http://localhost/&request_id=123456&requested_attributes=sreg_nickname,sreg_email,sreg_fullname,sreg_dob,sreg_gender,sreg_postcode,sreg_country,sreg_language,sreg_timezone

Open UI

The AW must determine if user interface interaction is necessary. For example, if the user is already logged in, then no UI may be necessary. If the user is not logged in, the user should be presented with a password screen (like the one shown below).

Traditional Login Screen

Note: Proceed to step 4 only if the user has successfully authenticated (entered the correct password).

POST

The AW needs to send a POST HTTPS call to the PostBack Url containing the following possible values.

Parameter Description
request_id Required The request identifier sent from Janrain in step 2.
api_key Required The API key you receive from Janrain.
no_prompt Required If this value is set to false, Identity Services displays a page that asks for confirmation to log in to the RP and for permission to send user data. If this value is set to true, Identity Services does not display a confirmation page to the user.

Note: Many customers set the no_prompt value to true when using Identity Services between a set of trusted sites, where user permission has already been implicitly granted.
username The user name of the authenticated user. Do not send this parameter if the service sends a cancel value.
cancel The presence of this parameter means that either the user or your website did not authenticate. The authentication transaction should be canceled.
sreg_nickname Any UTF-8 string that an end user wants to use as a nickname.
sreg_email The email address of the end user as specified in section 3.4.1 of RFC2822 (Resnick, P., Internet Message Format).
sreg_fullname A UTF-8 string free text representation of the end user’s full name.
sreg_dob The end user’s date of birth as SERVICE-MM-DD. Any values whose representation uses fewer than the specified number of digits should be zero-padded. The length of this value MUST always be 10. If the end user user does not want to reveal any particular component of this value, it MUST be set to zero. For instance, if an end user wants to specify that his or her date of birth is 1980, but not the month or day, the value returned will be 1980-00-00.
sreg_gender The end user’s gender (M or F).
sreg_postcode UTF-8 string free text that should conform to the end user’s country’s postal system.
sreg_country The end user’s country of residence as specified by ISO3166.
sreg_language The end user’s preferred language as specified by ISO639.
sreg_timezone The end user’s timezone, as defined by the Simple Registration specification (which references this site).
blob You can pass back arbitrary fields through Identity Services by using the blob field. The value of this field is a concatenated list of key/value pairs separated by ampersands (&). See the code example at the end of this topic.

Response

Identity Services will send a response to the AW. This response status must be 200. If you receive anything other than a 200 status, the status should be logged and the transaction stopped. A text error message will be included in the response body, but it is not intended for end user presentation. The only error that can be shown to the user at this point is that the authentication transaction did not complete. It is valid for the AW to pause and retry (starting at step 3) multiple times, but this is not an endless loop.

Redirect

The AW must redirect the user back to Identity Services at the Return Url supplied by Janrain. Identity Services expects the authenticated request ID to be provided in one of the following ways:

  • As a query parameter named request_id. This is URL-encoded if the user was redirected via a standard HTTP GET 302.
  • As an HTTP request body parameter named request_id. This is www-form-encoded if the user was redirected via a HTTP POST.

Optional

If no_prompt is set to false, the user will be prompted to approve login to the RP and asked to share user information.

Login Approval

Response

Janrain will redirect the user back to the RP with an assertion of success or failure.

If the customer is using Social Login, the user will be directed to the RP and Janrain will create and return an access token that can be used to retrieve user information (per the standard Social Login process).

If the customer is not using Social Login, the RP must handle the returned OpenID response. The Appendix contains an example response.

Example Code

The following code sample is a Ruby implementation of Identity Services:

def Janrain_login(user, request_id, remember_me, auth_method)
    http = Net::HTTP.new POST_BACK_URL, Net::HTTP.https_default_port
    http.use_ssl = true
    query_data = {
        'request_id' => request_id,
        'api_key' => Janrain_KEY,
        'no_prompt' => 'true',
        'username' => user.id,
        'sreg_email' => user.attributes['email'],
        'blob' => "remember_me=#{remember_me}&auth_method=#{auth_method}"
    }
    query_data = query_data.collect{ |key,value| "#{key}=#{CGI.escape( value.to_s )}"
    }.join(Service&Service)

    http.request_post("/ows_auth", query_data, {'User-Agent' => 'JanRainProServ/1.0
    (Automated)Service'})

    redirect_to "https://#{RETURN_TO_URL}?request_id=#{params[:request_id]}"
end

def Janrain_cancel(request_id)
    http = Net::HTTP.new POST_BACK_URL, Net::HTTP.https_default_port
    http.use_ssl = true
    query_data = {
        'request_id' => request_id,
        'api_key' => Janrain_KEY,
        'no_prompt' => 'true',
        'cancel' => 'true'
    }

    query_data = query_data.collect{ |key,value| "#{key}=#{CGI.escape( value.to_s )}"
    }.join(Service&Service)

    http.request_post("/ows_auth", query_data, {'User-Agent' => 'JanRainProServ/1.0
    (Automated)Service})
    redirect_to "https://#{RETURN_TO_URL}?request_id=#{params[:request_id]}"
end

Appendix

If an RP is not using Social Login, the RP must initiate the login and handle the response.

RP Initiating the Login

The following code sample is a generic redirect to the Identity Services endpoint that starts the OpenID flow.

https://demo.opx.janrain.ws/server?
openid.ns=http://specs.openid.net/auth/2.0&
openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select&
openid.identity=http://specs.openid.net/auth/2.0/identifier_select&
openid.return_to=http://localhost/&
openid.ns.sreg=http://openid.net/extensions/sreg/1.1&
openid.mode=checkid_setup&
openid.sreg.optional=nickname,email,fullname,dob,gender,postcode,country,language,timezone

RP Handling the Response

This is a generic response from the Identity Service that the RP must parse to obtain the user information and OpenID claim.

http://localhost/?openid.assoc_handle={HMAC-SHA1}{50ff6f14}{eeyFTg==}&openid.claimed_id=https://stoich-test.opx.janrain.ws/user/foo&openid.identity=https://stoich-test.opx.janrain.ws/user/foo&openid.mode=id_res&openid.ns=http://specs.openid.net/auth/2.0&openid.ns.sreg=http://openid.net/extensions/sreg/1.1&openid.op_endpoint=https://stoich-test.opx.janrain.ws/server&openid.response_nonce=2013-01-23T05:03:16ZVZmdZ2&openid.return_to=http://localhost/&openid.sig=FQLYB5dh2o0wnSwFJbhViStA5R8=&openid.signed=assoc_handle,claimed_id,identity,mode,ns,ns.sreg,op_endpoint,response_nonce,return_to,signed,sreg.email&openid.sreg.email=myname@idp.com

Gamification / Loyalty

Badgeville (Gamification)

Demos are provided for example integrations of Janrain with Badgeville.

Actual integrations will vary by environment, and these are provided as a reference blueprint for building your own solution using the same basic concepts illustrated in the demos. All deployments are different, and this blueprint is provided to show one approach to combining these two services.

Prerequisites

For the sake of these demos, the following elements are already in place:

  • A deployed, standard Registration solution.
  • A deployed Badgeville solution.
  • Badgeville code (delivered from their Solution Engineering team).

Installation

To see the demo code, view the page source. The demo code is embedded with comments on the integration points between Badgeville and Janrain.

These demos are hosted on Janrain’s external demo site:

Analytics

Adobe Analytics

Overview

Social Sharing

A number of events are fired through the Janrain login process that can be used to track login activity in your Adobe Analytics Account:

  • onProviderLoginStart
  • onProviderLoginError
  • onProviderLoginSuccess
  • onProviderLoginComplete
  • onProviderLoginToken (we are including this here to show the code but this event fires only when using client-side login)
  • onReturnExperienceFound

We add handlers for each of these events in the janrainWidgetOnload function. Adobe provides two functions you can use after the page loads to record activity:

  • t()
  • tl()

We use tl() because it does not cause a page view to be counted, but if you would like to count a page view for each login event, t() works as well (keep in mind that if you attach a handler to each event you could end up counting an extra five page views per successful login). Our finished janrainWidgetOnload function looks like this:

function janrainWidgetOnload() {
  var submitOmnitureEvent = function(event, provider, linktitle){
    var s = s_gi(s_account);
    s.linkTrackVars = 'prop19,events,eVar19';
    s.linkTrackEvents = event;
    s.events = event;
    s.prop19 = provider;
    s.eVar19 = provider;
    s.tl(true, 'o', linktitle);
  };
  janrain.events.onProviderLoginStart.addHandler(function(response) {
    //event1
    submitOmnitureEvent('event1', response.provider, 'onProviderLoginStart');
  });
  janrain.events.onProviderLoginError.addHandler(function(response) {
    //event2
    submitOmnitureEvent('event2', response.provider, 'onProviderLoginError');
  });
  janrain.events.onProviderLoginSuccess.addHandler(function(response) {
    //event3
    submitOmnitureEvent('event3', response.provider, 'onProviderLoginSuccess');
  });
  janrain.events.onProviderLoginComplete.addHandler(function(response) {
    //event4
    submitOmnitureEvent('event4', response.provider, 'onProviderLoginComplete');
  });
  janrain.events.onProviderLoginToken.addHandler(function(response) {
    //event5
    submitOmnitureEvent('event5', response.provider, 'onProviderLoginToken');
  });
  janrain.events.onReturnExperienceFound.addHandler(function(response) {
    //event6
    submitOmnitureEvent('event6', response.returnProvider, 'onReturnExperienceFound');
  });
}

For each event we are calling the submitOmnitureEvent function to which we pass the name of the event, the provider the user is attempting to log in with, and a name for the link that was clicked. The submitOmnitureEvent function then creates a new s object by passing the global s_account variable in to s_gi(), and on that s object we set the variables we would like to track. We are tracking an event and setting a traffic variable (prop19) and a conversion variable (eVar19) with the name of the provider. This allows us to break down events by provider in SiteCatalyst. The tl() function actually stands for tracklinks and can be used to track file downloads and exit links, but here we are passing it a second argument (o) which is used when tracking custom links. The custom links setting allows us to repurpose this function to meet our needs.

Custom Success Events

SiteCatalyst allows you to create up to 100 custom events. Here we are using event1 through event6, but you can set it up using any six events you like. In order to give your events friendlier and more useful names you need to do some configuration in your SiteCatalyst account. You can find the setup for custom events by going to Admin > Admin Console > Report Suites > Edit Settings > Conversion > Success Events.

Setup for Custom Events

Traffic Variable

To give useful names to your traffic variable (prop19), go to Admin > Admin Console > Report Suites > Edit Settings > Traffic > Traffic Variables.

Traffic Variables

Conversion Variable

To give useful names to your conversion variable (eVar19), go to Admin > Admin Console > Report Suites > Edit Settings > Conversion > Conversion Variables.

Conversion Variables

Your New Report Suite

Once you configure your report suite and log out and back in to SiteCatalyst, all these newly-named variables are displayed in your report navigation.

Newly-named Variables Displayed in Report Navigation

You can now display a report of how many times somebody has started the login process.

Count of Login Process Starts

You can break that report down further and look at how many logins started with each provider.

Count of Login Process Starts Broken Down by Provider
Count of Login Process Starts Broken Down by Provider

The following code (along with the Adobe code that you are required to add to every page) is the minimum you need to get this example up and running on your site. Note: JavaScript in the <head> section runs asynchronously (it does not slow the page load).

<!doctype html>
<html>
<head>
<script type="text/javascript">
(function() {
  if (typeof window.janrain !== 'object') window.janrain = {};
  window.janrain.settings = {};

  janrain.settings.tokenUrl = 'http://examples.janrain.com/auth-widget/tokenurl.php';

  function isReady() { janrain.ready = true; };
  if (document.addEventListener) {
    document.addEventListener("DOMContentLoaded", isReady, false);
  } else {
    window.attachEvent('onload', isReady);
  }

  var e = document.createElement('script');
  e.type = 'text/javascript';
  e.id = 'janrainAuthWidget';

  if (document.location.protocol === 'https:') {
    e.src = 'https://rpxnow.com/js/lib/widget-examples-basic/engage.js';
  } else {
    e.src = 'http://widget-cdn.rpxnow.com/js/lib/widget-examples-basic/engage.js';
  }

  var s = document.getElementsByTagName('script')[0];
  s.parentNode.insertBefore(e, s);
})();
function janrainWidgetOnload() {
  var submitOmnitureEvent = function(event, provider, linktitle){
    var s = s_gi(s_account);
    s.linkTrackVars = 'prop19,events,eVar19';
    s.linkTrackEvents = event;
    s.events = event;
    s.prop19 = provider;
    s.eVar19 = provider;
    s.tl(true, 'o', linktitle);
  };
  janrain.events.onProviderLoginStart.addHandler(function(response) {
    submitOmnitureEvent('event1', response.provider, 'onProviderLoginStart');
  });
  janrain.events.onProviderLoginError.addHandler(function(response) {
    submitOmnitureEvent('event2', response.provider, 'onProviderLoginError');
  });
  janrain.events.onProviderLoginSuccess.addHandler(function(response) {
    submitOmnitureEvent('event3', response.provider, 'onProviderLoginSuccess');
  });
  janrain.events.onProviderLoginComplete.addHandler(function(response) {
    submitOmnitureEvent('event4', response.provider, 'onProviderLoginComplete');
  });
  janrain.events.onProviderLoginToken.addHandler(function(response) {
    submitOmnitureEvent('event5', response.provider, 'onProviderLoginToken');
  });
  janrain.events.onReturnExperienceFound.addHandler(function(response) {
    submitOmnitureEvent('event6', response.returnProvider, 'onReturnExperienceFound');
  });
}
</script>
</head>
<body>
<div id="janrainEngageEmbed"></div>
</body>
</html>
Scroll ↓