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));