Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / remoting / webapp / oauth2_api.js
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6  * @fileoverview
7  * OAuth2 API flow implementations.
8  */
9
10 'use strict';
11
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
14
15 /** @constructor */
16 remoting.OAuth2Api = function() {
17 };
18
19 /** @private
20  *  @return {string} OAuth2 token URL.
21  */
22 remoting.OAuth2Api.getOAuth2TokenEndpoint_ = function() {
23   return remoting.settings.OAUTH2_BASE_URL + '/token';
24 };
25
26 /** @private
27  *  @return {string} OAuth2 userinfo API URL.
28  */
29 remoting.OAuth2Api.getOAuth2ApiUserInfoEndpoint_ = function() {
30   return remoting.settings.OAUTH2_API_BASE_URL + '/v1/userinfo';
31 };
32
33
34 /**
35  * Interprets HTTP error responses in authentication XMLHttpRequests.
36  *
37  * @private
38  * @param {number} xhrStatus Status (HTTP response code) of the XMLHttpRequest.
39  * @return {remoting.Error} An error code to be raised.
40  */
41 remoting.OAuth2Api.interpretXhrStatus_ =
42     function(xhrStatus) {
43   // Return AUTHENTICATION_FAILED by default, so that the user can try to
44   // recover from an unexpected failure by signing in again.
45   /** @type {remoting.Error} */
46   var error = remoting.Error.AUTHENTICATION_FAILED;
47   if (xhrStatus == 400 || xhrStatus == 401 || xhrStatus == 403) {
48     error = remoting.Error.AUTHENTICATION_FAILED;
49   } else if (xhrStatus == 502 || xhrStatus == 503) {
50     error = remoting.Error.SERVICE_UNAVAILABLE;
51   } else if (xhrStatus == 0) {
52     error = remoting.Error.NETWORK_FAILURE;
53   } else {
54     console.warn('Unexpected authentication response code: ' + xhrStatus);
55   }
56   return error;
57 };
58
59 /**
60  * Asynchronously retrieves a new access token from the server.
61  *
62  * @param {function(string, number): void} onDone Callback to invoke when
63  *     the access token and expiration time are successfully fetched.
64  * @param {function(remoting.Error):void} onError Callback invoked if an
65  *     error occurs.
66  * @param {string} clientId OAuth2 client ID.
67  * @param {string} clientSecret OAuth2 client secret.
68  * @param {string} refreshToken OAuth2 refresh token to be redeemed.
69  * @return {void} Nothing.
70  */
71 remoting.OAuth2Api.refreshAccessToken = function(
72     onDone, onError, clientId, clientSecret, refreshToken) {
73   /** @param {XMLHttpRequest} xhr */
74   var onResponse = function(xhr) {
75     if (xhr.status == 200) {
76       try {
77         // Don't use jsonParseSafe here unless you move the definition out of
78         // remoting.js, otherwise this won't work from the OAuth trampoline.
79         // TODO(jamiewalch): Fix this once we're no longer using the trampoline.
80         var tokens = JSON.parse(xhr.responseText);
81         onDone(tokens['access_token'], tokens['expires_in']);
82       } catch (err) {
83         console.error('Invalid "token" response from server:',
84                       /** @type {*} */ (err));
85         onError(remoting.Error.UNEXPECTED);
86       }
87     } else {
88       console.error('Failed to refresh token. Status: ' + xhr.status +
89                     ' response: ' + xhr.responseText);
90       onError(remoting.OAuth2Api.interpretXhrStatus_(xhr.status));
91     }
92   };
93
94   var parameters = {
95     'client_id': clientId,
96     'client_secret': clientSecret,
97     'refresh_token': refreshToken,
98     'grant_type': 'refresh_token'
99   };
100
101   remoting.xhr.post(remoting.OAuth2Api.getOAuth2TokenEndpoint_(),
102                     onResponse, parameters);
103 };
104
105 /**
106  * Asynchronously exchanges an authorization code for access and refresh tokens.
107  *
108  * @param {function(string, string, number): void} onDone Callback to
109  *     invoke when the refresh token, access token and access token expiration
110  *     time are successfully fetched.
111  * @param {function(remoting.Error):void} onError Callback invoked if an
112  *     error occurs.
113  * @param {string} clientId OAuth2 client ID.
114  * @param {string} clientSecret OAuth2 client secret.
115  * @param {string} code OAuth2 authorization code.
116  * @param {string} redirectUri Redirect URI used to obtain this code.
117  * @return {void} Nothing.
118  */
119 remoting.OAuth2Api.exchangeCodeForTokens = function(
120     onDone, onError, clientId, clientSecret, code, redirectUri) {
121   /** @param {XMLHttpRequest} xhr */
122   var onResponse = function(xhr) {
123     if (xhr.status == 200) {
124       try {
125         // Don't use jsonParseSafe here unless you move the definition out of
126         // remoting.js, otherwise this won't work from the OAuth trampoline.
127         // TODO(jamiewalch): Fix this once we're no longer using the trampoline.
128         var tokens = JSON.parse(xhr.responseText);
129         onDone(tokens['refresh_token'],
130                tokens['access_token'], tokens['expires_in']);
131       } catch (err) {
132         console.error('Invalid "token" response from server:',
133                       /** @type {*} */ (err));
134         onError(remoting.Error.UNEXPECTED);
135       }
136     } else {
137       console.error('Failed to exchange code for token. Status: ' + xhr.status +
138                     ' response: ' + xhr.responseText);
139       onError(remoting.OAuth2Api.interpretXhrStatus_(xhr.status));
140     }
141   };
142
143   var parameters = {
144     'client_id': clientId,
145     'client_secret': clientSecret,
146     'redirect_uri': redirectUri,
147     'code': code,
148     'grant_type': 'authorization_code'
149   };
150   remoting.xhr.post(remoting.OAuth2Api.getOAuth2TokenEndpoint_(),
151                     onResponse, parameters);
152 };
153
154 /**
155  * Get the user's email address.
156  *
157  * @param {function(string):void} onDone Callback invoked when the email
158  *     address is available.
159  * @param {function(remoting.Error):void} onError Callback invoked if an
160  *     error occurs.
161  * @param {string} token Access token.
162  * @return {void} Nothing.
163  */
164 remoting.OAuth2Api.getEmail = function(onDone, onError, token) {
165   /** @param {XMLHttpRequest} xhr */
166   var onResponse = function(xhr) {
167     if (xhr.status == 200) {
168       try {
169         var result = JSON.parse(xhr.responseText);
170         onDone(result['email']);
171       } catch (err) {
172         console.error('Invalid "userinfo" response from server:',
173                       /** @type {*} */ (err));
174         onError(remoting.Error.UNEXPECTED);
175       }
176     } else {
177       console.error('Failed to get email. Status: ' + xhr.status +
178                     ' response: ' + xhr.responseText);
179       onError(remoting.OAuth2Api.interpretXhrStatus_(xhr.status));
180     }
181   };
182   var headers = { 'Authorization': 'OAuth ' + token };
183   remoting.xhr.get(remoting.OAuth2Api.getOAuth2ApiUserInfoEndpoint_(),
184                    onResponse, '', headers);
185 };