1 2 /** 3 *@namespace Sfdc.canvas.oauth 4 *@name Sfdc.canvas.oauth 5 */ 6 (function ($$) { 7 8 "use strict"; 9 10 var module = (function() { 11 12 var accessToken, 13 instUrl, 14 instId, 15 tOrigin, 16 childWindow; 17 18 function init() { 19 // Get the access token from the cookie (needed to survive refresh), 20 // and then remove the cookie per security's request. 21 accessToken = $$.cookies.get("access_token"); 22 $$.cookies.remove("access_token"); 23 } 24 25 function query(params) { 26 var r = [], n; 27 if (!$$.isUndefined(params)) { 28 for (n in params) { 29 if (params.hasOwnProperty(n)) { 30 // probably should encode these 31 r.push(n + "=" + params[n]); 32 } 33 } 34 return "?" + r.join('&'); 35 } 36 return ''; 37 } 38 /** 39 *@private 40 */ 41 function refresh() { 42 // Temporarily set the oauth token in a cookie and then remove it 43 // after the refresh. 44 $$.cookies.set("access_token", accessToken); 45 self.location.reload(); 46 } 47 /** 48 * @name Sfdc.canvas.oauth#login 49 * @function 50 * @description Opens the OAuth popup window to retrieve an OAuth token. 51 * @param {Object} ctx The context object that contains the URL, the response type, the client ID, and the callback URL 52 * @docneedsimprovement 53 * @example 54 * function clickHandler(e) 55 * { 56 * var uri; 57 * if (! connect.oauth.loggedin()) 58 * { 59 * uri = connect.oauth.loginUrl(); 60 * connect.oauth.login( 61 * {uri : uri, 62 * params: { 63 * response_type : "token", 64 * client_id : "<%=consumerKey%>", 65 * redirect_uri : encodeURIComponent("/sdk/callback.html") 66 * }}); 67 * } else { 68 * connect.oauth.logout(); 69 * } 70 * return false; 71 * } 72 */ 73 function login(ctx) { 74 var uri; 75 76 ctx = ctx || {}; 77 uri = ctx.uri || "/rest/oauth2"; 78 ctx.params = ctx.params || {state : ""}; 79 ctx.params.state = ctx.params.state || ctx.callback || window.location.pathname; // @TODO REVIEW THIS 80 ctx.params.display= ctx.params.display || 'popup'; 81 uri = uri + query(ctx.params); 82 childWindow = window.open(uri, 'OAuth', 'status=0,toolbar=0,menubar=0,resizable=0,scrollbars=1,top=50,left=50,height=500,width=680'); 83 } 84 85 /** 86 * @name Sfdc.canvas.oauth#token 87 * @function 88 * @description Sets, gets, or removes the <code>access_token</code> from this JavaScript object. <br> 89 <p>This function does one of three things: <br> 90 1) If the 't' parameter isn't passed in, the current value for the <code>access_token</code> value is returned. <br> 91 2) If the the 't' parameter is null, the <code>access_token</code> value is removed. <br> 92 3) Otherwise the <code>access_token</code> value is set to the 't' parameter and then returned.<br><br> 93 Note: for longer-term storage of the OAuth token, store it server-side in the session. Access tokens 94 should never be stored in cookies. 95 * @param {String} [t] The OAuth token to set as the <code>access_token</code> value 96 * @returns {String} The resulting <code>access_token</code> value if set; otherwise null 97 */ 98 function token(t) { 99 if (arguments.length === 0) { 100 if (!$$.isNil(accessToken)) {return accessToken;} 101 } 102 else { 103 accessToken = t; 104 } 105 106 return accessToken; 107 } 108 109 /** 110 * @name Sfdc.canvas.oauth#instance 111 * @function 112 * @description Sets, gets, or removes the <code>instance_url</code> cookie. <br> 113 <p> This function does one of three things: <br> 114 1) If the 'i' parameter is not passed in, the current value for the <code>instance_url</code> cookie is returned. <br> 115 2) If the 'i' parameter is null, the <code>instance_url</code> cookie is removed. <br> 116 3) Otherwise, the <code>instance_url</code> cookie value is set to the 'i' parameter and then returned. 117 * @param {String} [i] The value to set as the <code>instance_url</code> cookie 118 * @returns {String} The resulting <code>instance_url</code> cookie value if set; otherwise null 119 */ 120 function instanceUrl(i) { 121 if (arguments.length === 0) { 122 if (!$$.isNil(instUrl)) {return instUrl;} 123 instUrl = $$.cookies.get("instance_url"); 124 } 125 else if (i === null) { 126 $$.cookies.remove("instance_url"); 127 instUrl = null; 128 } 129 else { 130 $$.cookies.set("instance_url", i); 131 instUrl = i; 132 } 133 return instUrl; 134 } 135 136 /** 137 *@private 138 */ 139 // Example Results of tha hash.... 140 // Name [access_token] Value [00DU0000000Xthw!ARUAQMdYg9ScuUXB5zPLpVyfYQr9qXFO7RPbKf5HyU6kAmbeKlO3jJ93gETlJxvpUDsz3mqMRL51N1E.eYFykHpoda8dPg_z] 141 // Name [instance_url] Value [https://na12.salesforce.com] 142 // Name [id] Value [https://login.salesforce.com/id/00DU0000000XthwMAC/005U0000000e6PoIAI] 143 // Name [issued_at] Value [1331000888967] 144 // Name [signature] Value [LOSzVZIF9dpKvPU07icIDOf8glCFeyd4vNGdj1dhW50] 145 // Name [state] Value [/crazyrefresh.html] 146 function parseHash(hash) { 147 var i, nv, nvp, n, v; 148 149 if (! $$.isNil(hash)) { 150 if (hash.indexOf('#') === 0) { 151 hash = hash.substr(1); 152 } 153 nvp = hash.split("&"); 154 155 for (i = 0; i < nvp.length; i += 1) { 156 nv = nvp[i].split("="); 157 n = nv[0]; 158 v = decodeURIComponent(nv[1]); 159 if ("access_token" === n) { 160 token(v); 161 } 162 else if ("instance_url" === n) { 163 instanceUrl(v); 164 } 165 else if ("target_origin" === n) { 166 tOrigin = decodeURIComponent(v); 167 } 168 else if ("instance_id" === n) { 169 instId = v; 170 } 171 } 172 } 173 } 174 175 /** 176 * @name Sfdc.canvas.oauth#checkChildWindowStatus 177 * @function 178 * @description Refreshes the parent window only if the child window is closed. 179 */ 180 function checkChildWindowStatus() { 181 if (!childWindow || childWindow.closed) { 182 refresh(); 183 } 184 } 185 186 /** 187 * @name Sfdc.canvas.oauth#childWindowUnloadNotification 188 * @function 189 * @description Parses the hash value that is passed in and sets the 190 <code>access_token</code> and <code>instance_url</code> cookies if they exist. Use this method during 191 User-Agent OAuth Authentication Flow to pass the OAuth token. 192 * @param {String} hash A string of key-value pairs delimited by 193 the ampersand character. 194 * @example 195 * Sfdc.canvas.oauth.childWindowUnloadNotification(self.location.hash); 196 */ 197 function childWindowUnloadNotification(hash) { 198 // Here we get notification from child window. Here we can decide if such notification is 199 // raised because user closed child window, or because user is playing with F5 key. 200 // NOTE: We can not trust on "onUnload" event of child window, because if user reload or refresh 201 // such window in fact he is not closing child. (However "onUnload" event is raised!) 202 //checkChildWindowStatus(); 203 parseHash(hash); 204 setTimeout(window.Sfdc.canvas.oauth.checkChildWindowStatus, 50); 205 } 206 207 /** 208 * @name Sfdc.canvas.oauth#logout 209 * @function 210 * @description Removes the <code>access_token</code> OAuth token from this object. 211 */ 212 function logout() { 213 // Remove the oauth token and refresh the browser 214 token(null); 215 // @todo: do we want to do this? 216 //var home = $$.cookies.get("home"); 217 //window.location = home || window.location; 218 } 219 220 /** 221 * @name Sfdc.canvas.oauth#loggedin 222 * @function 223 * @description Returns the login state. 224 * @returns {Boolean} <code>true</code> if the <code>access_token</code> is available in this JS object. 225 * Note: <code>access tokens</code> (for example, OAuth tokens) should be stored server-side for more durability. 226 * Never store OAuth tokens in cookies as this can lead to a security risk. 227 */ 228 function loggedin() { 229 return !$$.isNil(token()); 230 } 231 232 /** 233 * @name Sfdc.canvas.oauth#loginUrl 234 * @function 235 * @description Returns the URL for the OAuth authorization service. 236 * @returns {String} The URL for the OAuth authorization service or default if there's 237 * no value for loginUrl in the current URL's query string 238 */ 239 function loginUrl() { 240 var i, nvs, nv, q = self.location.search; 241 242 if (q) { 243 q = q.substring(1); 244 nvs = q.split("&"); 245 for (i = 0; i < nvs.length; i += 1) 246 { 247 nv = nvs[i].split("="); 248 if ("loginUrl" === nv[0]) { 249 return decodeURIComponent(nv[1]) + "/services/oauth2/authorize"; 250 } 251 } 252 } 253 return "https://login.salesforce.com/services/oauth2/authorize"; 254 } 255 256 function targetOrigin(to) { 257 258 if (!$$.isNil(to)) { 259 tOrigin = to; 260 return to; 261 } 262 263 if (!$$.isNil(tOrigin)) {return tOrigin;} 264 265 // This relies on the parent passing it in. This may not be there as the client can do a 266 // redirect or link to another page 267 parseHash(document.location.hash); 268 return tOrigin; 269 } 270 271 function instanceId(id) { 272 273 if (!$$.isNil(id)) { 274 instId = id; 275 return id; 276 } 277 278 if (!$$.isNil(instId)) {return instId;} 279 280 // This relies on the parent passing it in. This may not be there as the client can do a 281 // redirect or link to another page 282 parseHash(document.location.hash); 283 return instId; 284 } 285 286 function client() { 287 return {oauthToken : token(), instanceId : instanceId(), targetOrigin : targetOrigin()}; 288 } 289 290 return { 291 init : init, 292 login : login, 293 logout : logout, 294 loggedin : loggedin, 295 loginUrl : loginUrl, 296 token : token, 297 instance : instanceUrl, 298 client : client, 299 checkChildWindowStatus : checkChildWindowStatus, 300 childWindowUnloadNotification: childWindowUnloadNotification 301 }; 302 }()); 303 304 $$.module('Sfdc.canvas.oauth', module); 305 306 $$.oauth.init(); 307 308 }(Sfdc.canvas));