UNPKG

j-toker

Version:

Simple, secure token authentication for jQuery.

3 lines 15.5 kB
/*! j-toker - v0.0.10-beta3 - 2015-10-14 * Copyright (c) 2015 Lynn Dylan Hurley; Licensed WTFPL */ !function(a){"function"==typeof define&&define.amd?define(["jquery","jquery-deparam","pubsub-js","jquery.cookie"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("jquery-deparam"),require("pubsub-js"),require("jquery.cookie")):a(window.jQuery,window.deparam,window.PubSub)}(function(a,b,c){var d=Function("return this")();if(d.auth)return d.auth;var e=d.navigator,f="default",g="currentConfigName",h="authHeaders",i="firstTimeLogin",j="mustResetPassword",k="auth.validation.success",l="auth.validation.error",m="auth.emailRegistration.success",n="auth.emailRegistration.error",o="auth.passwordResetRequest.success",p="auth.passwordResetRequest.error",q="auth.emailConfirmation.success",r="auth.emailConfirmation.error",s="auth.passwordResetConfirm.success",t="auth.passwordResetConfirm.error",u="auth.emailSignIn.success",v="auth.emailSignIn.error",w="auth.oAuthSignIn.success",x="auth.oAuthSignIn.error",y="auth.signIn.success",z="auth.signIn.error",A="auth.signOut.success",B="auth.signOut.error",C="auth.accountUpdate.success",D="auth.accountUpdate.error",E="auth.destroyAccount.success",F="auth.destroyAccount.error",G="auth.passwordUpdate.success",H="auth.passwordUpdate.error",I=function(){this.configured=!1,this.configDfd=null,this.configs={},this.defaultConfigKey=null,this.firstTimeLogin=!1,this.mustResetPassword=!1,this.user={},this.oAuthDfd=null,this.oAuthTimer=null,this.configBase={apiUrl:"/api",signOutPath:"/auth/sign_out",emailSignInPath:"/auth/sign_in",emailRegistrationPath:"/auth",accountUpdatePath:"/auth",accountDeletePath:"/auth",passwordResetPath:"/auth/password",passwordUpdatePath:"/auth/password",tokenValidationPath:"/auth/validate_token",proxyIf:function(){return!1},proxyUrl:"/proxy",forceHardRedirect:!1,storage:"cookies",cookieExpiry:14,cookiePath:"/",initialCredentials:null,passwordResetSuccessUrl:function(){return d.location.href},confirmationSuccessUrl:function(){return d.location.href},tokenFormat:{"access-token":"{{ access-token }}","token-type":"Bearer",client:"{{ client }}",expiry:"{{ expiry }}",uid:"{{ uid }}"},parseExpiry:function(a){return 1e3*parseInt(a.expiry,10)||null},handleLoginResponse:function(a){return a.data},handleAccountUpdateResponse:function(a){return a.data},handleTokenValidationResponse:function(a){return a.data},authProviderPaths:{github:"/auth/github",facebook:"/auth/facebook",google:"/auth/google_oauth2"}}};I.prototype.reset=function(){this.destroySession(),this.configs={},this.defaultConfigKey=null,this.configured=!1,this.configDfd=null,this.mustResetPassword=!1,this.firstTimeLogin=!1,this.oAuthDfd=null,this.willRedirect=!1,this.oAuthTimer&&(clearTimeout(this.oAuthTimer),this.oAuthTimer=null);for(var b in this.user)delete this.user[b];a(document).unbind("ajaxComplete",this.updateAuthCredentials),d.removeEventListener&&d.removeEventListener("message",this.handlePostMessage),a.ajaxSetup({beforeSend:void 0})},I.prototype.invalidateTokens=function(){for(var a in this.user)delete this.user[a];this.deleteData(g),this.deleteData(h)},I.prototype.checkDependencies=function(){var e=[],f=[];if(!a)throw"jToker: jQuery not found. This module depends on jQuery.";if(d.localStorage||a.cookie||e.push("This browser does not support localStorage. You must install jquery-cookie to use jToker with this browser."),b||e.push("Dependency not met: jquery-deparam."),c||f.push("jquery.ba-tinypubsub.js not found. No auth events will be broadcast."),e.length){var g=e.join(" ");throw"jToker: Please resolve the following errors: "+g}if(f.length&&console&&console.warn){var h=f.join(" ");console.warn("jToker: Warning: "+h)}},I.prototype.destroySession=function(){var b=[h,g];for(var c in b)if(c=b[c],d.localStorage&&d.localStorage.removeItem(c),a.cookie){for(var e in this.configs){var f=this.configs[e].cookiePath;a.removeCookie(c,{path:f})}a.removeCookie(c,{path:"/"})}},I.prototype.configure=function(b,c){if(c&&this.reset(),this.configured)return this.configDfd;if(this.configured=!0,b||(b={}),b.constructor!==Array){this.defaultConfigKey=f;var e={};e[this.defaultConfigKey]=b,b=[e]}for(var g=0;g<b.length;g++){var k=J(b[g]);this.defaultConfigKey||(this.defaultConfigKey=k),this.configs[k]=a.extend({},this.configBase,b[g][k])}if(this.checkDependencies(),a(document).ajaxComplete(d.auth.updateAuthCredentials),a.ajaxSetup({beforeSend:d.auth.appendAuthHeaders}),d.addEventListener&&d.addEventListener("message",this.handlePostMessage,!1),this.processSearchParams(),this.willRedirect)return!1;if(this.getConfig().initialCredentials){var l=this.getConfig();return this.persistData(h,l.initialCredentials.headers),this.persistData(j,l.initialCredentials.mustResetPassword),this.persistData(i,l.initialCredentials.firstTimeLogin),this.setCurrentUser(l.initialCredentials.user),(new a.Deferred).resolve(l.initialCredentials.user)}return this.configDfd=this.validateToken({config:this.getCurrentConfigName()}),this.configDfd},I.prototype.getApiUrl=function(){var a=this.getConfig();return a.proxyIf()?a.proxyUrl:a.apiUrl},I.prototype.buildAuthHeaders=function(a){var b={},c=this.getConfig().tokenFormat;for(var d in c)b[d]=M(c[d],a);return b},I.prototype.setCurrentUser=function(b){for(var c in this.user)delete this.user[c];return a.extend(this.user,b),this.user.signedIn=!0,this.user.configName=this.getCurrentConfigName(),this.user},I.prototype.handlePostMessage=function(a){var b=!1;if("deliverCredentials"===a.data.message){delete a.data.message;var c=d.auth.normalizeTokenKeys(a.data),e=d.auth.buildAuthHeaders(c),f=d.auth.setCurrentUser(a.data);d.auth.persistData(h,e),d.auth.resolvePromise(w,d.auth.oAuthDfd,f),d.auth.broadcastEvent(y,f),d.auth.broadcastEvent(k,f),b=!0}"authFailure"===a.data.message&&(d.auth.rejectPromise(x,d.auth.oAuthDfd,a.data,"OAuth authentication failed."),d.auth.broadcastEvent(z,a.data),b=!0),b&&(clearTimeout(d.auth.oAuthTimer),d.auth.oAuthTimer=null)},I.prototype.normalizeTokenKeys=function(a){return a.token&&(a["access-token"]=a.token,delete a.token),a.auth_token&&(a["access-token"]=a.auth_token,delete a.auth_token),a.client_id&&(a.client=a.client_id,delete a.client_id),a.config&&(this.persistData(g,a.config,a.config),delete a.config),a},I.prototype.processSearchParams=function(){var a=this.getQs(),b=null;if(a=this.normalizeTokenKeys(a),a["access-token"]&&a.uid){b=this.buildAuthHeaders(a),this.persistData(h,b),a.reset_password&&this.persistData(j,!0),a.account_confirmation_success&&this.persistData(i,!0);var c=this.getLocationWithoutParams(["access-token","token","auth_token","config","client","client_id","expiry","uid","reset_password","account_confirmation_success"]);this.willRedirect=!0,this.setLocation(c)}return b},I.prototype.getLocationWithoutParams=function(b){var c=a.param(this.stripKeys(this.getSearchQs(),b)),e=a.param(this.stripKeys(this.getAnchorQs(),b)),f=d.location.hash.split("?")[0];c&&(c="?"+c),e&&(f+="?"+e),f&&!f.match(/^#/)&&(f="#/"+f);var g=d.location.protocol+"//"+d.location.host+d.location.pathname+c+f;return g},I.prototype.stripKeys=function(a,b){for(var c in b)delete a[b[c]];return a},I.prototype.broadcastEvent=function(a,b){c.publish&&c.publish(a,b)},I.prototype.resolvePromise=function(b,c,d){var e=this,f=a.Deferred();return setTimeout(function(){e.broadcastEvent(b,d),c.resolve(d),f.resolve()},0),f.promise()},I.prototype.rejectPromise=function(b,c,d,e){var f=this;return d=a.parseJSON(d&&d.responseText||"{}"),setTimeout(function(){f.broadcastEvent(b,d),c.reject({reason:e,data:d})},0),c},I.prototype.validateToken=function(b){if(b||(b={}),b.config||(b.config=this.getCurrentConfigName()),this.configDfd)return this.configDfd;var c=a.Deferred();if(this.retrieveData(h)){var d=this.getConfig(b.config),e=this.getApiUrl()+d.tokenValidationPath;a.ajax({url:e,context:this,success:function(a){var b=d.handleTokenValidationResponse(a);this.setCurrentUser(b),this.retrieveData(i)&&(this.broadcastEvent(q,a),this.persistData(i,!1),this.firstTimeLogin=!0),this.retrieveData(j)&&(this.broadcastEvent(s,a),this.persistData(j,!1),this.mustResetPassword=!0),this.resolvePromise(k,c,this.user)},error:function(a){this.invalidateTokens(),this.retrieveData(i)&&(this.broadcastEvent(r,a),this.persistData(i,!1)),this.retrieveData(j)&&(this.broadcastEvent(t,a),this.persistData(j,!1)),this.rejectPromise(l,c,a,"Cannot validate token; token rejected by server.")}})}else this.invalidateTokens(),this.rejectPromise(l,c,{},"Cannot validate token; no token found.");return c.promise()},I.prototype.emailSignUp=function(b){b||(b={});var c=this.getConfig(b.config),d=this.getApiUrl()+c.emailRegistrationPath,e=a.Deferred();return b.config_name=b.config,delete b.config,b.confirm_success_url=c.confirmationSuccessUrl(),a.ajax({url:d,context:this,method:"POST",data:b,success:function(a){this.resolvePromise(m,e,a)},error:function(a){this.rejectPromise(n,e,a,"Failed to submit email registration.")}}),e.promise()},I.prototype.emailSignIn=function(b){b||(b={});var c=this.getConfig(b.config),d=this.getApiUrl()+c.emailSignInPath,e=a.Deferred();return delete b.config,a.ajax({url:d,context:this,method:"POST",data:b,success:function(a){var b=c.handleLoginResponse(a);this.setCurrentUser(b),this.resolvePromise(u,e,a),this.broadcastEvent(y,b),this.broadcastEvent(k,this.user)},error:function(a){this.rejectPromise(v,e,a,"Invalid credentials."),this.broadcastEvent(z,a)}}),e.promise()},I.prototype.listenForCredentials=function(a){var b=this;a.closed?b.rejectPromise(x,b.oAuthDfd,null,"OAuth window was closed bofore registration was completed."):(a.postMessage("requestCredentials","*"),b.oAuthTimer=setTimeout(function(){b.listenForCredentials(a)},500))},I.prototype.openAuthWindow=function(a){if(this.getConfig().forceHardRedirect||d.isIE())this.setLocation(a);else{var b=this.createPopup(a);this.listenForCredentials(b)}},I.prototype.buildOAuthUrl=function(a,b,c){var e=this.getConfig().apiUrl+c+"?auth_origin_url="+encodeURIComponent(d.location.href)+"&config_name="+encodeURIComponent(a||this.getCurrentConfigName())+"&omniauth_window_type=newWindow";if(b)for(var f in b)e+="&",e+=encodeURIComponent(f),e+="=",e+=encodeURIComponent(b[f]);return e},I.prototype.oAuthSignIn=function(b){if(b||(b={}),!b.provider)throw"jToker: provider param undefined for `oAuthSignIn` method.";var c=this.getConfig(b.config),d=c.authProviderPaths[b.provider],e=this.buildOAuthUrl(b.config,b.params,d);if(!d)throw"jToker: providerPath not found for provider: "+b.provider;return this.oAuthDfd=a.Deferred(),this.openAuthWindow(e),this.oAuthDfd.promise()},I.prototype.signOut=function(b){b||(b={});var c=this.getConfig(b.config),d=this.getApiUrl()+c.signOutPath,e=a.Deferred();return a.ajax({url:d,context:this,method:"DELETE",success:function(a){this.resolvePromise(A,e,a)},error:function(a){this.rejectPromise(B,e,a,"Failed to sign out.")},complete:function(){this.invalidateTokens()}}),e.promise()},I.prototype.updateAccount=function(b){b||(b={});var c=this.getConfig(b.config),d=this.getApiUrl()+c.accountUpdatePath,e=a.Deferred();return delete b.config,a.ajax({url:d,context:this,method:"PUT",data:b,success:function(a){var b=c.handleAccountUpdateResponse(a);this.setCurrentUser(b),this.resolvePromise(C,e,a)},error:function(a){this.rejectPromise(D,e,a,"Failed to update user account")}}),e.promise()},I.prototype.destroyAccount=function(b){b||(b={});var c=this.getConfig(b.config),d=this.getApiUrl()+c.accountDeletePath,e=a.Deferred();return a.ajax({url:d,context:this,method:"DELETE",success:function(a){this.invalidateTokens(),this.resolvePromise(E,e,a)},error:function(a){this.rejectPromise(F,e,a,"Failed to destroy user account")}}),e.promise()},I.prototype.requestPasswordReset=function(b){if(b||(b={}),void 0===b.email)throw"jToker: email param undefined for `requestPasswordReset` method.";var c=this.getConfig(b.config),d=this.getApiUrl()+c.passwordResetPath,e=a.Deferred();return b.config_name=b.config,delete b.config,b.redirect_url=c.passwordResetSuccessUrl(),a.ajax({url:d,context:this,method:"POST",data:b,success:function(a){this.resolvePromise(o,e,a)},error:function(a){this.rejectPromise(p,e,a,"Failed to submit email registration.")}}),e.promise()},I.prototype.updatePassword=function(b){b||(b={});var c=this.getConfig(b.config),d=this.getApiUrl()+c.passwordUpdatePath,e=a.Deferred();return delete b.config,a.ajax({url:d,context:this,method:"PUT",data:b,success:function(a){this.resolvePromise(G,e,a)},error:function(a){this.rejectPromise(H,e,a,"Failed to update password.")}}),e.promise()},I.prototype.persistData=function(b,c,e){switch(c=JSON.stringify(c),this.getConfig(e).storage){case"localStorage":d.localStorage.setItem(b,c);break;default:a.cookie(b,c,{expires:this.getConfig(e).cookieExpiry,path:this.getConfig(e).cookiePath})}},I.prototype.retrieveData=function(b){var c=null;switch(this.getConfig().storage){case"localStorage":c=d.localStorage.getItem(b);break;default:c=a.cookie(b)}try{return a.parseJSON(c)}catch(e){return K(c)}},I.prototype.getCurrentConfigName=function(){var b=null;return this.getQs().config&&(b=this.getQs().config),a.cookie&&!b&&(b=a.cookie(g)),d.localStorage&&!b&&(b=d.localStorage.getItem(g)),b=b||this.defaultConfigKey||f,K(b)},I.prototype.deleteData=function(b){switch(this.getConfig().storage){case"cookies":a.removeCookie(b,{path:this.getConfig().cookiePath});break;default:d.localStorage.removeItem(b)}},I.prototype.getConfig=function(a){if(!this.configured)throw"jToker: `configure` must be run before using this plugin.";return a=a||this.getCurrentConfigName(),this.configs[a]},I.prototype.appendAuthHeaders=function(a,b){var c=d.auth.retrieveData(h);if(L(b.url)&&c){a.setRequestHeader("If-Modified-Since","Mon, 26 Jul 1997 05:00:00 GMT");for(var e in d.auth.getConfig().tokenFormat)a.setRequestHeader(e,c[e])}},I.prototype.updateAuthCredentials=function(a,b,c){if(L(c.url)){var e={},f=!0;for(var g in d.auth.getConfig().tokenFormat)e[g]=b.getResponseHeader(g),e[g]&&(f=!1);f||d.auth.persistData(h,e)}},I.prototype.getRawSearch=function(){return d.location.search},I.prototype.getRawAnchor=function(){return d.location.hash},I.prototype.setRawAnchor=function(a){d.location.hash=a},I.prototype.getAnchorSearch=function(){var a=this.getRawAnchor().split("?");return a.length>1?a[1]:null},I.prototype.setRawSearch=function(a){d.location.search=a},I.prototype.setSearchQs=function(b){return this.setRawSearch(a.param(b)),this.getSearchQs()},I.prototype.setAnchorQs=function(b){return this.setAnchorSearch(a.param(b)),this.getAnchorQs()},I.prototype.setLocation=function(a){d.location.replace(a)},I.prototype.createPopup=function(a){return d.open(a)},I.prototype.getSearchQs=function(){var a=this.getRawSearch().replace("?",""),c=a?b(a):{};return c},I.prototype.getAnchorQs=function(){var a=this.getAnchorSearch(),c=a?b(a):{};return c},I.prototype.getQs=function(){return a.extend(this.getSearchQs(),this.getAnchorQs())};var J=function(a){for(var b in a)return b},K=function(a){return a&&a.replace(/("|')/g,"")},L=function(a){return a.match(d.auth.getApiUrl())},M=function(a,b){for(var c=function(a,c){return void 0===b[c]?a:b[c]},d=new RegExp("{{\\s*([a-z0-9-_]+)\\s*}}","ig"),e="";e!==a;a=(e=a).replace(d,c));return a};return d.isOldIE=function(){var a=!1,b=e.userAgent.toLowerCase();if(b&&-1!==b.indexOf("msie")){var c=parseInt(b.split("msie")[1]);10>c&&(a=!0)}return a},d.isIE=function(){var a=d.isOldIE(),b=!!e.userAgent.match(/Trident.*rv\:11\./);return a||b},d.auth=a.auth=new I,d.auth});