(function($) {
Sammy = Sammy || {}; // Sammy.OAuth2 is a plugin for using OAuth 2.0 to authenticate users and // access your application's API. Requires Sammy.Session. // // Triggers the following events: // - oauth.connected -- Access token set and ready to use. Triggered when new // access token acquired, of when application starts and already has access // token. // - oauth.disconnected -- Access token reset. Triggered by // loseAccessToken(). // - oauth.denied -- Authorization attempt rejected. // // ### Example // this.use(Sammy.Storage); // this.use(Sammy.OAuth2); // this.oauthorize = "/oauth/authorize"; // // // The quick & easy way // this.requireOAuth(); // // Specific path // this.requireOAuth("/private"); // // Filter you can apply to specific URLs // this.before(function(context) { return context.requireOAuth(); }) // // Apply to specific request // this.get("/private", function(context) { // this.requireOAuth(function() { // // Do something // }) // }) // // // Sign in/sign out. // this.bind("oauth.connected", function() { $("#signin").hide() }); // this.bind("oauth.disconnected", function() { $("#signin").show() }); // // // Handle access denied and other errors // this.bind("oauth.denied", function(evt, error) { // this.partial("admin/views/no_access.tmpl", { error: error.message }); // }); // // // Sign out. // this.get("#/signout", function(context) { // context.loseAccessToken(); // context.redirect("#/"); // }); // Sammy.OAuth2 = function(app) { app.use(Sammy.JSON); this.authorize = "/oauth/authorize"; // Use this on request that require OAuth token. You can use this in a // filter: it will redirect and return false if the access token is missing. // You can use it in a route, it will redirect to get the access token, or // call the callback function if it has an access token. this.helper("requireOAuth", function(cb) { if (this.app.getAccessToken()) { if (cb) cb.apply(this); } else { this.redirect(this.app.authorize + "?state=" + escape(this.path)); return false; } }); // Use this to sign out. this.helper("loseAccessToken", function() { this.app.loseAccessToken(); }); // Use this in your application to require an OAuth access token on all, or // the specified paths. It sets up a before filter on the specified paths. this.requireOAuth = function(options) { this.before(options || {}, function(context) { return context.requireOAuth(); }); } // Returns the access token. Uses Sammy.Session to store the token. this.getAccessToken = function() { return this.session("oauth.token"); } // Stores the access token in the session. this.setAccessToken = function(token) { this.session("oauth.token", token); this.trigger("oauth.connected"); } // Lose access token: use this to sign out. this.loseAccessToken = function() { this.session("oauth.token", null); this.trigger("oauth.disconnected"); } // Add OAuth 2.0 access token to all XHR requests. $(document).ajaxSend(function(evt, xhr) { var token = app.getAccessToken(); if (token) xhr.setRequestHeader("Authorization", "OAuth " + token); }); // Converts query string parameters in fragment identifier to object. function parseParams(hash) { var pairs = hash.substring(1).split("&"), params = {}; for (var i in pairs) { var splat = pairs[i].split("="); params[splat[0]] = splat[1].replace(/\+/g, " "); } return params; } var start_url; // Capture the application's start URL, we'll need that later on for // redirection. this.bind("run", function(evt, params) { start_url = params.start_url || "#"; if (this.app.getAccessToken()) this.trigger("oauth.connected"); }); // Intercept OAuth authorization response with access token, stores it and // redirects to original URL, or application root. this.before(/^#(access_token=|[^\\].*\&access_token=)/, function(context) { var params = parseParams(context.path); this.app.setAccessToken(params.access_token); // When the filter redirected the original request, it passed the original // request's URL in the state parameter, which we get back after // authorization. context.redirect(params.state.length == 0 ? this.app.start_url : unescape(params.state)); return false; }).get(/^#(access_token=|[^\\].*\&access_token=)/, function(context) { }); // Intercept OAuth authorization response with error (typically access // denied). this.before(/^#(error=|[^\\].*\&error=)/, function(context) { var params = parseParams(context.path); var message = params.error_description || "Access denined"; context.trigger("oauth.denied", { code: params.error, message: message }); return false; }).get(/^#(error=|[^\\].*\&error=)/, function(context) { }); }
})(jQuery);