Sick of Acronyms Archive Pages Categories Tags

Solving WAYF via Bookmarklets

11 June 2008

The power of bookmarklets is still to be seen in many situations. Consider the "Where Are You From?" (WAYF) problem, a common issue with federation technologies. The simple question of where to send the user to complete a federated authentication is one of the more complicated and error prone issues in identity federation. The key metrics for any WAYF solution are that the user should have the opportunity to choose any relevant identity context and the process should be hard for a RP to subvert.

-SAML 1 tokens can be retrieved from an IDP with a specially formed HTTP GET request and a TARGET parameter pointing back to the RP site, though a pre-existing relationship must exist in order to allow this to work since most of the request (attributes, authN) is implicit and expressed in the SAML metadata.

-SAML2 tokens can be retrieved from an IDP with a HTTP POST request which articulates the request parameters (attributes, authN), but still requires the RP to be explicitly aware of supported IDP(s). While there are some tricks in the specification regarding the use of domain cookies, the approach is not very dynamic and is still prone to spoofing and other problems.

-InfoCard solves the problem through the user's selection of a card. The card is indicative of the location of the target identity provider. This is the best approach thus far, though it lacks ubiquity at the moment.

-OpenID addresses the problem by the user being prompted to input their OpenID url. This is the most straightforward approach, as the user is compelled to identify the IDP explicitly (or at least a pointer). Aside from a steeper learning curve, this approach suffers from spoofability assuming a malicious RP (as does SAML).

While all address the problem with varying levels of success, I believe that the bookmarklet approach maintains the benefits of wide interoperability while reducing spoofability of the IDP's interface. The provisioning process would work like so:
  1. The user logs into the IDP for the first time.
  2. The IDP validates user's credentials, offers bookmarklet which can be stored in the user's browser. The bookmarklet has sufficient logic to parse the protocol specific parameters from the RP site required to issue a token.
  3. The user accesses an RP site and navigates to the login page.
  4. The user clicks the IDP's bookmarklet. The bookmarklet's Javascript parses the RP's information and redirects the browser to the IDP's site with the RP's parameters encoded into the URL.
This approach works with all modern browsers. (except IE7, though IE8 works!) It preserves the user centricity of the interaction because the user has to choose an identity bookmarklet to log in, and it reduces spoofability since we are not depending on the RP to preform the redirection. This profile is sufficiently abstract enough that it could be used to improve existing SAML enterprises and could easily be integrated to OpenID.

The bookmarklet code itself is extremely simple. If we use Infocard as our example, we can easily search for the embedded object type of "applicationx/infocard," gather the required/optional claims, and redirect the user's browser to the IDP's site. Assuming the browser supports the "infocard://" protocol:

var idp="infocard://";

var objects = document.getElementsByTagName("object");

var infocardObject;

for(var i = 0; i < objects.length && infocardObject == null; i++){

if(objects[i].type == "application/x-informationCard")

infocardObject = objects[i];

}

if(infocardObject == null){

alert("It appears there is no InfoCard login on this page.");

}else{

var parentElement = infocardObject;

while(parentElement != null && !parentElement.action)

parentElement = parentElement.parentNode;

var target = parentElement == null ? window.location.pathname: parentElement.action;

var requiredClaims=(document.getElementsByName("requiredClaims")[0].value).replace(/\s+/g,'%20');

document.location.href=idp+"requiredClaims="+requiredClaims+"&paramName="+infocardObject.name+"&respondToUrl="+target;

}


If the browser isn't cooperative, then we can replace the idp variable with the hard-coded URL for the IDP, though the user is then forced to have multiple bookmarklets.

Fork me on GitHub