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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<!-- Licensed under Yahoo! BSD license http://gist.github.com/375593 -->
</head>
<body>
<span id="login"></span>
<p>This is a demonstration of Yahoo! login on a page. You can find <a href="http://gist.github.com/619947">the code</a> used in this demonstration on github.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p><a href="http://www.flickr.com/photos/tambako/1196453096/sizes/o/in/photostream/"><img src="http://farm2.static.flickr.com/1409/1196453096_a4d65ea3e9_z.jpg"></a><br>
Photo credit: <a href="http://www.flickr.com/photos/tambako/">Tambako the Jaguar</a></p>
<script type="text/javascript" src="http://yui.yahooapis.com/3.2.0pr2/build/yui/yui-min.js"></script>
<script type="text/javascript"src="http://gist.github.com/raw/619947/f344557a242fc987f95e7f5af3173a28ba94a58c/yui-login.js"></script>
<script>
YUI().use('login', function(Y) {
Y.login.renderLoginButton('login');
});
</script>
</body>
</html>
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
// Licensed under Yahoo! BSD
// @see http://gist.github.com/375593
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'
});
var name = 'login';
var params = 'toolbar=1,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']
};
var json = Y.JSON.stringify(session);
// Cache the session in a cookie
Y.Cookie.set(Y.login.cookieName, json);
// 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');
}
//fetch username for display to make the login/logout a bit more realistic
var json = Y.Cookie.get(Y.login.cookieName);
var session = Y.JSON.parse(json);
html = html || 'User id: '+session['username']+'<br><a href="#">log out</a>';
button.set('innerHTML', html);
var handler = button.on('click', function(e) {
e.preventDefault();
// 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