| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * OAuth2 API flow implementations. | 7 * OAuth2 API flow implementations. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 'use strict'; | 10 'use strict'; |
| 11 | 11 |
| 12 /** @suppress {duplicate} */ | 12 /** @suppress {duplicate} */ |
| 13 var remoting = remoting || {}; | 13 var remoting = remoting || {}; |
| 14 | 14 |
| 15 /** @constructor */ | 15 /** |
| 16 remoting.OAuth2Api = function() { | 16 * @constructor |
| 17 * @implements {remoting.OAuth2Api} |
| 18 */ |
| 19 remoting.OAuth2ApiImpl = function() { |
| 17 }; | 20 }; |
| 18 | 21 |
| 19 /** @private | 22 /** @private |
| 20 * @return {string} OAuth2 token URL. | 23 * @return {string} OAuth2 token URL. |
| 21 */ | 24 */ |
| 22 remoting.OAuth2Api.prototype.getOAuth2TokenEndpoint_ = function() { | 25 remoting.OAuth2ApiImpl.prototype.getOAuth2TokenEndpoint_ = function() { |
| 23 return remoting.settings.OAUTH2_BASE_URL + '/token'; | 26 return remoting.settings.OAUTH2_BASE_URL + '/token'; |
| 24 }; | 27 }; |
| 25 | 28 |
| 26 /** @private | 29 /** @private |
| 27 * @return {string} OAuth2 userinfo API URL. | 30 * @return {string} OAuth2 userinfo API URL. |
| 28 */ | 31 */ |
| 29 remoting.OAuth2Api.prototype.getOAuth2ApiUserInfoEndpoint_ = function() { | 32 remoting.OAuth2ApiImpl.prototype.getOAuth2ApiUserInfoEndpoint_ = function() { |
| 30 return remoting.settings.OAUTH2_API_BASE_URL + '/v1/userinfo'; | 33 return remoting.settings.OAUTH2_API_BASE_URL + '/v1/userinfo'; |
| 31 }; | 34 }; |
| 32 | 35 |
| 33 | 36 |
| 34 /** | 37 /** |
| 35 * Interprets HTTP error responses in authentication XMLHttpRequests. | 38 * Interprets HTTP error responses in authentication XMLHttpRequests. |
| 36 * | 39 * |
| 37 * @private | 40 * @private |
| 38 * @param {number} xhrStatus Status (HTTP response code) of the XMLHttpRequest. | 41 * @param {number} xhrStatus Status (HTTP response code) of the XMLHttpRequest. |
| 39 * @return {remoting.Error} An error code to be raised. | 42 * @return {remoting.Error} An error code to be raised. |
| 40 */ | 43 */ |
| 41 remoting.OAuth2Api.prototype.interpretXhrStatus_ = | 44 remoting.OAuth2ApiImpl.prototype.interpretXhrStatus_ = |
| 42 function(xhrStatus) { | 45 function(xhrStatus) { |
| 43 // Return AUTHENTICATION_FAILED by default, so that the user can try to | 46 // Return AUTHENTICATION_FAILED by default, so that the user can try to |
| 44 // recover from an unexpected failure by signing in again. | 47 // recover from an unexpected failure by signing in again. |
| 45 /** @type {remoting.Error} */ | 48 /** @type {remoting.Error} */ |
| 46 var error = remoting.Error.AUTHENTICATION_FAILED; | 49 var error = remoting.Error.AUTHENTICATION_FAILED; |
| 47 if (xhrStatus == 400 || xhrStatus == 401 || xhrStatus == 403) { | 50 if (xhrStatus == 400 || xhrStatus == 401 || xhrStatus == 403) { |
| 48 error = remoting.Error.AUTHENTICATION_FAILED; | 51 error = remoting.Error.AUTHENTICATION_FAILED; |
| 49 } else if (xhrStatus == 502 || xhrStatus == 503) { | 52 } else if (xhrStatus == 502 || xhrStatus == 503) { |
| 50 error = remoting.Error.SERVICE_UNAVAILABLE; | 53 error = remoting.Error.SERVICE_UNAVAILABLE; |
| 51 } else if (xhrStatus == 0) { | 54 } else if (xhrStatus == 0) { |
| 52 error = remoting.Error.NETWORK_FAILURE; | 55 error = remoting.Error.NETWORK_FAILURE; |
| 53 } else { | 56 } else { |
| 54 console.warn('Unexpected authentication response code: ' + xhrStatus); | 57 console.warn('Unexpected authentication response code: ' + xhrStatus); |
| 55 } | 58 } |
| 56 return error; | 59 return error; |
| 57 }; | 60 }; |
| 58 | 61 |
| 59 /** | 62 /** |
| 60 * Asynchronously retrieves a new access token from the server. | 63 * Asynchronously retrieves a new access token from the server. |
| 61 * | 64 * |
| 62 * @param {function(string, number): void} onDone Callback to invoke when | 65 * @param {function(string, number): void} onDone Callback to invoke when |
| 63 * the access token and expiration time are successfully fetched. | 66 * the access token and expiration time are successfully fetched. |
| 64 * @param {function(remoting.Error):void} onError Callback invoked if an | 67 * @param {function(remoting.Error):void} onError Callback invoked if an |
| 65 * error occurs. | 68 * error occurs. |
| 66 * @param {string} clientId OAuth2 client ID. | 69 * @param {string} clientId OAuth2 client ID. |
| 67 * @param {string} clientSecret OAuth2 client secret. | 70 * @param {string} clientSecret OAuth2 client secret. |
| 68 * @param {string} refreshToken OAuth2 refresh token to be redeemed. | 71 * @param {string} refreshToken OAuth2 refresh token to be redeemed. |
| 69 * @return {void} Nothing. | 72 * @return {void} Nothing. |
| 70 */ | 73 */ |
| 71 remoting.OAuth2Api.prototype.refreshAccessToken = function( | 74 remoting.OAuth2ApiImpl.prototype.refreshAccessToken = function( |
| 72 onDone, onError, clientId, clientSecret, refreshToken) { | 75 onDone, onError, clientId, clientSecret, refreshToken) { |
| 73 /** @param {XMLHttpRequest} xhr */ | 76 /** @param {XMLHttpRequest} xhr */ |
| 74 var onResponse = function(xhr) { | 77 var onResponse = function(xhr) { |
| 75 if (xhr.status == 200) { | 78 if (xhr.status == 200) { |
| 76 try { | 79 try { |
| 77 // Don't use base.jsonParseSafe here unless you also include base.js, | 80 // Don't use base.jsonParseSafe here unless you also include base.js, |
| 78 // otherwise this won't work from the OAuth trampoline. | 81 // otherwise this won't work from the OAuth trampoline. |
| 79 // TODO(jamiewalch): Fix this once we're no longer using the trampoline. | 82 // TODO(jamiewalch): Fix this once we're no longer using the trampoline. |
| 80 var tokens = JSON.parse(xhr.responseText); | 83 var tokens = JSON.parse(xhr.responseText); |
| 81 onDone(tokens['access_token'], tokens['expires_in']); | 84 onDone(tokens['access_token'], tokens['expires_in']); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 108 * invoke when the refresh token, access token and access token expiration | 111 * invoke when the refresh token, access token and access token expiration |
| 109 * time are successfully fetched. | 112 * time are successfully fetched. |
| 110 * @param {function(remoting.Error):void} onError Callback invoked if an | 113 * @param {function(remoting.Error):void} onError Callback invoked if an |
| 111 * error occurs. | 114 * error occurs. |
| 112 * @param {string} clientId OAuth2 client ID. | 115 * @param {string} clientId OAuth2 client ID. |
| 113 * @param {string} clientSecret OAuth2 client secret. | 116 * @param {string} clientSecret OAuth2 client secret. |
| 114 * @param {string} code OAuth2 authorization code. | 117 * @param {string} code OAuth2 authorization code. |
| 115 * @param {string} redirectUri Redirect URI used to obtain this code. | 118 * @param {string} redirectUri Redirect URI used to obtain this code. |
| 116 * @return {void} Nothing. | 119 * @return {void} Nothing. |
| 117 */ | 120 */ |
| 118 remoting.OAuth2Api.prototype.exchangeCodeForTokens = function( | 121 remoting.OAuth2ApiImpl.prototype.exchangeCodeForTokens = function( |
| 119 onDone, onError, clientId, clientSecret, code, redirectUri) { | 122 onDone, onError, clientId, clientSecret, code, redirectUri) { |
| 120 /** @param {XMLHttpRequest} xhr */ | 123 /** @param {XMLHttpRequest} xhr */ |
| 121 var onResponse = function(xhr) { | 124 var onResponse = function(xhr) { |
| 122 if (xhr.status == 200) { | 125 if (xhr.status == 200) { |
| 123 try { | 126 try { |
| 124 // Don't use base.jsonParseSafe here unless you also include base.js, | 127 // Don't use base.jsonParseSafe here unless you also include base.js, |
| 125 // otherwise this won't work from the OAuth trampoline. | 128 // otherwise this won't work from the OAuth trampoline. |
| 126 // TODO(jamiewalch): Fix this once we're no longer using the trampoline. | 129 // TODO(jamiewalch): Fix this once we're no longer using the trampoline. |
| 127 var tokens = JSON.parse(xhr.responseText); | 130 var tokens = JSON.parse(xhr.responseText); |
| 128 onDone(tokens['refresh_token'], | 131 onDone(tokens['refresh_token'], |
| (...skipping 23 matching lines...) Expand all Loading... |
| 152 /** | 155 /** |
| 153 * Get the user's email address. | 156 * Get the user's email address. |
| 154 * | 157 * |
| 155 * @param {function(string):void} onDone Callback invoked when the email | 158 * @param {function(string):void} onDone Callback invoked when the email |
| 156 * address is available. | 159 * address is available. |
| 157 * @param {function(remoting.Error):void} onError Callback invoked if an | 160 * @param {function(remoting.Error):void} onError Callback invoked if an |
| 158 * error occurs. | 161 * error occurs. |
| 159 * @param {string} token Access token. | 162 * @param {string} token Access token. |
| 160 * @return {void} Nothing. | 163 * @return {void} Nothing. |
| 161 */ | 164 */ |
| 162 remoting.OAuth2Api.prototype.getEmail = function(onDone, onError, token) { | 165 remoting.OAuth2ApiImpl.prototype.getEmail = function(onDone, onError, token) { |
| 163 /** @param {XMLHttpRequest} xhr */ | 166 /** @param {XMLHttpRequest} xhr */ |
| 164 var onResponse = function(xhr) { | 167 var onResponse = function(xhr) { |
| 165 if (xhr.status == 200) { | 168 if (xhr.status == 200) { |
| 166 try { | 169 try { |
| 167 var result = JSON.parse(xhr.responseText); | 170 var result = JSON.parse(xhr.responseText); |
| 168 onDone(result['email']); | 171 onDone(result['email']); |
| 169 } catch (err) { | 172 } catch (err) { |
| 170 console.error('Invalid "userinfo" response from server:', | 173 console.error('Invalid "userinfo" response from server:', |
| 171 /** @type {*} */ (err)); | 174 /** @type {*} */ (err)); |
| 172 onError(remoting.Error.UNEXPECTED); | 175 onError(remoting.Error.UNEXPECTED); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 185 /** | 188 /** |
| 186 * Get the user's email address and full name. | 189 * Get the user's email address and full name. |
| 187 * | 190 * |
| 188 * @param {function(string, string):void} onDone Callback invoked when the email | 191 * @param {function(string, string):void} onDone Callback invoked when the email |
| 189 * address and full name are available. | 192 * address and full name are available. |
| 190 * @param {function(remoting.Error):void} onError Callback invoked if an | 193 * @param {function(remoting.Error):void} onError Callback invoked if an |
| 191 * error occurs. | 194 * error occurs. |
| 192 * @param {string} token Access token. | 195 * @param {string} token Access token. |
| 193 * @return {void} Nothing. | 196 * @return {void} Nothing. |
| 194 */ | 197 */ |
| 195 remoting.OAuth2Api.prototype.getUserInfo = function(onDone, onError, token) { | 198 remoting.OAuth2ApiImpl.prototype.getUserInfo = |
| 199 function(onDone, onError, token) { |
| 196 /** @param {XMLHttpRequest} xhr */ | 200 /** @param {XMLHttpRequest} xhr */ |
| 197 var onResponse = function(xhr) { | 201 var onResponse = function(xhr) { |
| 198 if (xhr.status == 200) { | 202 if (xhr.status == 200) { |
| 199 try { | 203 try { |
| 200 var result = JSON.parse(xhr.responseText); | 204 var result = JSON.parse(xhr.responseText); |
| 201 onDone(result['email'], result['name']); | 205 onDone(result['email'], result['name']); |
| 202 } catch (err) { | 206 } catch (err) { |
| 203 console.error('Invalid "userinfo" response from server:', | 207 console.error('Invalid "userinfo" response from server:', |
| 204 /** @type {*} */ (err)); | 208 /** @type {*} */ (err)); |
| 205 onError(remoting.Error.UNEXPECTED); | 209 onError(remoting.Error.UNEXPECTED); |
| 206 } | 210 } |
| 207 } else { | 211 } else { |
| 208 console.error('Failed to get user info. Status: ' + xhr.status + | 212 console.error('Failed to get user info. Status: ' + xhr.status + |
| 209 ' response: ' + xhr.responseText); | 213 ' response: ' + xhr.responseText); |
| 210 onError(remoting.Error.fromHttpError(xhr.status)); | 214 onError(remoting.Error.fromHttpError(xhr.status)); |
| 211 } | 215 } |
| 212 }; | 216 }; |
| 213 var headers = { 'Authorization': 'OAuth ' + token }; | 217 var headers = { 'Authorization': 'OAuth ' + token }; |
| 214 remoting.xhr.get(this.getOAuth2ApiUserInfoEndpoint_(), | 218 remoting.xhr.get(this.getOAuth2ApiUserInfoEndpoint_(), |
| 215 onResponse, '', headers); | 219 onResponse, '', headers); |
| 216 }; | 220 }; |
| 217 | 221 |
| 218 /** @type {remoting.OAuth2Api} */ | 222 /** @type {remoting.OAuth2Api} */ |
| 219 remoting.oauth2Api = new remoting.OAuth2Api(); | 223 remoting.oauth2Api = new remoting.OAuth2ApiImpl(); |
| OLD | NEW |