Skip to content

Instantly share code, notes, and snippets.

@erikeldridge
Created October 11, 2010 03:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save erikeldridge/619947 to your computer and use it in GitHub Desktop.
Save erikeldridge/619947 to your computer and use it in GitHub Desktop.
A simple YUI 3 module for adding Yahoo! login to a page
YUI.add('login', function(Y) {
// This module assumes the openid flow takes place via a popup that cannot be accessed directly.
// Given this condition, and to maintain simplicity, it doesn't attempt to verfiy the assertion.
// If you modify this script to use a file that processes the assertion directly, you should verify the assertion.
// @see http://openid.net/specs/openid-authentication-2_0.html#verification
Y.namespace('login');
Y.login.cookieName = 'login_session';
Y.login.sessionReadyEventName = 'login:sessionReady';
// This function constructs an openid login url for Yahoo!, and opens a popup to this location
// @param {string} returnUrl is the url to redirect to after the user goes through the login flow. Defaults to document.location.href
Y.login.popup = function (returnUrl) {
returnUrl = returnUrl || document.location.href;
// @see http://openid.net/specs/openid-authentication-2_0.html#realms
var realm = returnUrl.match(/(http[s]?:\/\/[^\/?]+)/)[0];
// Load openid login flow in popup window
// @see http://developer.yahoo.com/openid/
var url = 'https://open.login.yahooapis.com/openid/op/auth?' + Y.QueryString.stringify({
'openid.return_to': returnUrl,
'openid.mode': 'checkid_setup',
'openid.identity': 'http://specs.openid.net/auth/2.0/identifier_select',
'openid.ns': 'http://specs.openid.net/auth/2.0',
'openid.realm': realm,
'openid.claimed_id': 'http://specs.openid.net/auth/2.0/identifier_select'
});
Y.log(url);
var name = 'login';
var params = 'toolbar=0,scrollbars=1,location=1,statusbar=1,menubar=0,resizable=1, width=500,height=500,left=200,top=200';
var popup = window.open(url, name, params);
// Poll popup every 300 msec to see if it's redirected back to this domain
// @see http://developer.yahoo.com/yui/3/api/YUI.html#method_later
var timer = Y.later(300, Y, function() {
// If user's closed window, stop timer
if (popup.closed) {
timer.cancel();
return;
}
// Wrap in try/catch to avoid fatal cross-domain exceptions
try {
// Openid's response is called the "assertion"
// @see http://openid.net/specs/openid-authentication-2_0.html#positive_assertions
var assertion = popup.location.href.split('?')[1];
assertion = Y.QueryString.parse(assertion);
// Extract the user-specific info
var session = {
'username': assertion['openid.identity']
};
// Cache the session in a cookie
Y.Cookie.set(Y.login.cookieName, JSON.stringify(assertion));
// Notify anyone who's listening in this yui sandbox that the session's ready
Y.fire(Y.login.sessionReadyEventName);
// Stop polling popup & close it
timer.cancel();
popup.close();
} catch(e) {
Y.log(e);
}
}, '', true);
// Self-close login window if user hasn't completed flow in 30 sec
Y.later(30000, Y, function () {
timer.cancel();
popup.close();
});
};
// This function creates markup and event handling for a login button
// @param {string} id is the id of the DOM element to insert login button into
// @param {string} html is an optional param for custom button markup
// @throws Error if an id is not passed in
// @throws Error if there is no DOM element with the id passed in
Y.login.renderLoginButton = function (id, html) {
if (!id) {
throw new Error ('Y.login.renderLoginButton - A DOM element id is a required argument');
}
var button = Y.one('#'+id);
if (!button) {
throw new Error('Y.login.renderLoginButton - No DOM element with id "'+id+'" found');
}
html = html || '<img src="http://l.yimg.com/a/i/reg/openid/buttons/1_new.png"/>';
button.set('innerHTML', html);
Y.on(Y.login.sessionReadyEventName, function () {
// login handling is async, so remove handler after auth is complete
Y.Event.purgeElement(button);
Y.login.renderLogoutButton(id);
});
// check for previously saved session
var session = Y.Cookie.get(Y.login.cookieName);
// if there is a session, fire session ready event and exit early
if (session) {
Y.fire(Y.login.sessionReadyEventName);
return;
}
button.on('click', function(e) {
Y.login.popup();
});
};
// This function creates markup and event handling for a logout button
// @param {string} id is the id of the DOM element to insert login button into
// @param {string} html is an optional param for custom button markup
// @throws Error if an id is not passed in
// @throws Error if there is no DOM element with the id passed in
Y.login.renderLogoutButton = function (id, html) {
if (!id) {
throw new Error ('Y.login.renderLogoutButton - A DOM element id is a required argument');
}
var button = Y.one('#'+id);
if (!button) {
throw new Error('Y.login.renderLogoutButton - No DOM element with id "'+id+'" found');
}
html = html || '<span id="'+id+'">log out</span>';
button.set('innerHTML', html);
var handler = button.on('click', function(e) {
// remove session cookie
Y.Cookie.remove(Y.login.cookieName);
// remove logout click handler
Y.Event.purgeElement(button);
// restore login button
Y.login.renderLoginButton(id);
});
};
}, '', {requires:['cookie', 'event', 'querystring', 'json', 'node']});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment