Adding support for other IDPs


July 2012 update: This article was publicized to describe how to to extend the GITKit widget if a website also does a lot of additional work to add custom RP server side support for additional IDPs.  However the technique is too complicated to be reasonably implemented.  We are instead working on a major re-write of GITKit that will make this easier for sites

Objective
GITKit has built in support for some identity providers, but your website may want to add other identity provider (IDPs).  This article describes how to do that.  

If that identity provider asserts email addresses that it does not host, we suggest you also implement additional account linking logic. A future version of GITKit will add support for these type of identity providers, such as social networks, which will avoid the need to implement that logic. Google has a sample site that demonstrates the type of extra work required by the website owner.

Overview

The general method to do this involves the RP website creating APIs that are similar to the two GITKit APIs but which will handle the other IDPs. The RP then needs to modify the JavaScript account chooser widget to include a button for those IDPs.

For IDPs that use a protocol like OAuth 2.0 it is pretty simple (~60 lines of code) to implement those APIs, but other IDPs may be harder.

Details

Widget JavaScript
Now in widget the create auth URL request is directly sent from the JavaScript widget. The interface exposed is as follows.

google.identitytoolkit.addCustomIdp( {'providerId': '', 'imageUrl': '', 'label': '', 'createAuthUriHandler': function(callbackUrl, callbackHandler){}} )


The fields of the custom IDP object is as follows:

Name

Value

providerId

The provider ID. If the IDP is email provider it’s the email domain. So that when non registered user comes in we know we can do federated login. If the IDP is not email provider the ID can be any unique string. One good option it’s the IDP domain name e.g. www.example.com.

imageUrl

The URL of the IDP logo in the nascar list. The size should be 147*50. We may need to add another param to specify the small IDP logo for the account avatar.

label

The provider name. It’s displayed if the image is not available.

createAuthUriHandler

The function to handle the create auth URL request. When the user clicks the IDP logo this function is invoked with 2 params: callbackUrl and callbackHandler. The callbackUrl is the URL the IDP should redirect the user after authentication. The callbackHandler is a function that needs to be invoked when the createAuthUrlHandler function finishes. In this way the control is passed back to the widget and the widget will pop up the window to do the fedreated login.

Example:

google.identitytoolkit.addCustomIdp({

     'providerId': 'OtherIdp',

     'imageUrl': 'http://www.otheridp.com/images/loginbutton.jpg',

'label': 'www.otheridp.com',

     'createAuthUriHandler': function(callbackUrl, callbackHandler) {

       callbackHandler({ 'authUri': 'http://www.otheridp.com/dialog/oauth?client_id=122939221135439&display=popup&scope=email&redirect_uri=' + encodeURIComponent(callbackUrl) });

     }});

The createAuthUrlHandler field is optional. e.g. If you want to add some Google apps domain to the nascar list. Note: the providerId must be the Google apps domain name.
You can simply write the following code:

google.identitytoolkit.addCustomIdp({

     'providerId': 'samplegoogleappsdomain.com',

     'imageUrl': 'http://www.samplegoogleappsdomain.com/images/loginbutton.jpg',

'createAuthUriHandler': 'Sample Google Apps domain',

});


Under the hood a URL param “rp_custom_idp=providerId” is appended to the callback URL so the client library knows for this request the specific RP implemented verifyAssertion method should be invoked instead of talking to the GITkit API.

RP server side
For the RP server side, the custom IDP interface should be implemented. It only contains one method verifyAssertion. If we move the createAuthUrl call to the server side we can just simply add that to this interface. That means the widget sends the create auth URL request to the RP server side and the RP server sends the request to the GITkit API endpoint or the IDP endpoint directly. In this way we don’t need the cross domain RPC, the devconsole API key is kept on the RP server side and RP does not need to implement JS create auth URL code which is hard for OAuth 1.0a.

interface gitCustomIdp {

 /**

  * Verifies the assertion returned by the IDP.

  * @param string $url The URL which is requested by the IDP.

  * @param string $postBody The post body which is posted by the IDP.

  * @return mixed: gitAssertion object.

  */

 function verifyAssertion($url, $postBody);

}


As the same in the JavaScript the RP needs to tell the implementation to the GITkit clientlibrary.

gitContext::addCustomIdp('www.otheridp.com', new OtherIDP());


For an OAuth 2.0 provider. The verifyAsesrtion is quite easy. The pseudo code is as follows:

class OtherIDP implements gitCustomIdp {

 function verifyAssertion(url, postBody) {

   code = getUrlParam(‘code’);

   accessTokenUrl = makeAccessTokenUrl(appId, appSecret, url, code);

   accessToken = httpGet(accessTokenUrl);

   resourceUrl = ‘https://loginapi.otheridp.com/me?access_token=’ + accessToken;

   return httpGet(resourceUrl);

 }

}


Comments