Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: lib/src/authorization_code_grant.dart

Issue 1308163004: Async-ify. (Closed) Base URL: git@github.com:dart-lang/oauth2.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « README.md ('k') | lib/src/client.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library authorization_code_grant; 5 library authorization_code_grant;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:http/http.dart' as http; 9 import 'package:http/http.dart' as http;
10 10
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 89
90 /// The current state of the grant object. One of [_INITIAL_STATE], 90 /// The current state of the grant object. One of [_INITIAL_STATE],
91 /// [_AWAITING_RESPONSE_STATE], or [_FINISHED_STATE]. 91 /// [_AWAITING_RESPONSE_STATE], or [_FINISHED_STATE].
92 int _state = _INITIAL_STATE; 92 int _state = _INITIAL_STATE;
93 93
94 /// Creates a new grant. 94 /// Creates a new grant.
95 /// 95 ///
96 /// [httpClient] is used for all HTTP requests made by this grant, as well as 96 /// [httpClient] is used for all HTTP requests made by this grant, as well as
97 /// those of the [Client] is constructs. 97 /// those of the [Client] is constructs.
98 AuthorizationCodeGrant( 98 AuthorizationCodeGrant(
99 this.identifier, 99 this.identifier,
100 this.secret, 100 this.secret,
101 this.authorizationEndpoint, 101 this.authorizationEndpoint,
102 this.tokenEndpoint, 102 this.tokenEndpoint,
103 {http.Client httpClient}) 103 {http.Client httpClient})
104 : _httpClient = httpClient == null ? new http.Client() : httpClient; 104 : _httpClient = httpClient == null ? new http.Client() : httpClient;
105 105
106 /// Returns the URL to which the resource owner should be redirected to 106 /// Returns the URL to which the resource owner should be redirected to
107 /// authorize this client. The resource owner will then be redirected to 107 /// authorize this client. The resource owner will then be redirected to
108 /// [redirect], which should point to a server controlled by the client. This 108 /// [redirect], which should point to a server controlled by the client. This
109 /// redirect will have additional query parameters that should be passed to 109 /// redirect will have additional query parameters that should be passed to
110 /// [handleAuthorizationResponse]. 110 /// [handleAuthorizationResponse].
111 /// 111 ///
112 /// The specific permissions being requested from the authorization server may 112 /// The specific permissions being requested from the authorization server may
113 /// be specified via [scopes]. The scope strings are specific to the 113 /// be specified via [scopes]. The scope strings are specific to the
114 /// authorization server and may be found in its documentation. Note that you 114 /// authorization server and may be found in its documentation. Note that you
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 /// It is a [StateError] to call this more than once, to call it before 150 /// It is a [StateError] to call this more than once, to call it before
151 /// [getAuthorizationUrl] is called, or to call it after 151 /// [getAuthorizationUrl] is called, or to call it after
152 /// [handleAuthorizationCode] is called. 152 /// [handleAuthorizationCode] is called.
153 /// 153 ///
154 /// Throws [FormatError] if [parameters] is invalid according to the OAuth2 154 /// Throws [FormatError] if [parameters] is invalid according to the OAuth2
155 /// spec or if the authorization server otherwise provides invalid responses. 155 /// spec or if the authorization server otherwise provides invalid responses.
156 /// If `state` was passed to [getAuthorizationUrl], this will throw a 156 /// If `state` was passed to [getAuthorizationUrl], this will throw a
157 /// [FormatError] if the `state` parameter doesn't match the original value. 157 /// [FormatError] if the `state` parameter doesn't match the original value.
158 /// 158 ///
159 /// Throws [AuthorizationException] if the authorization fails. 159 /// Throws [AuthorizationException] if the authorization fails.
160 Future<Client> handleAuthorizationResponse(Map<String, String> parameters) { 160 Future<Client> handleAuthorizationResponse(Map<String, String> parameters)
161 return async.then((_) { 161 async {
162 if (_state == _INITIAL_STATE) { 162 if (_state == _INITIAL_STATE) {
163 throw new StateError( 163 throw new StateError(
164 'The authorization URL has not yet been generated.'); 164 'The authorization URL has not yet been generated.');
165 } else if (_state == _FINISHED_STATE) { 165 } else if (_state == _FINISHED_STATE) {
Bob Nystrom 2015/08/24 21:36:51 Nit, but the "else" isn't useful.
nweiz 2015/08/24 23:58:34 I like using "else"s when they make the code terse
166 throw new StateError( 166 throw new StateError(
167 'The authorization code has already been received.'); 167 'The authorization code has already been received.');
168 }
169 _state = _FINISHED_STATE;
170
171 if (_stateString != null) {
172 if (!parameters.containsKey('state')) {
173 throw new FormatException('Invalid OAuth response for '
174 '"$authorizationEndpoint": parameter "state" expected to be '
175 '"$_stateString", was missing.');
176 } else if (parameters['state'] != _stateString) {
177 throw new FormatException('Invalid OAuth response for '
178 '"$authorizationEndpoint": parameter "state" expected to be '
179 '"$_stateString", was "${parameters['state']}".');
168 } 180 }
169 _state = _FINISHED_STATE; 181 }
170 182
171 if (_stateString != null) { 183 if (parameters.containsKey('error')) {
172 if (!parameters.containsKey('state')) { 184 var description = parameters['error_description'];
173 throw new FormatException('Invalid OAuth response for ' 185 var uriString = parameters['error_uri'];
174 '"$authorizationEndpoint": parameter "state" expected to be ' 186 var uri = uriString == null ? null : Uri.parse(uriString);
175 '"$_stateString", was missing.'); 187 throw new AuthorizationException(parameters['error'], description, uri);
176 } else if (parameters['state'] != _stateString) { 188 } else if (!parameters.containsKey('code')) {
177 throw new FormatException('Invalid OAuth response for ' 189 throw new FormatException('Invalid OAuth response for '
178 '"$authorizationEndpoint": parameter "state" expected to be ' 190 '"$authorizationEndpoint": did not contain required parameter '
179 '"$_stateString", was "${parameters['state']}".'); 191 '"code".');
180 } 192 }
181 }
182 193
183 if (parameters.containsKey('error')) { 194 return await _handleAuthorizationCode(parameters['code']);
184 var description = parameters['error_description'];
185 var uriString = parameters['error_uri'];
186 var uri = uriString == null ? null : Uri.parse(uriString);
187 throw new AuthorizationException(parameters['error'], description, uri);
188 } else if (!parameters.containsKey('code')) {
189 throw new FormatException('Invalid OAuth response for '
190 '"$authorizationEndpoint": did not contain required parameter '
191 '"code".');
192 }
193
194 return _handleAuthorizationCode(parameters['code']);
195 });
196 } 195 }
197 196
198 /// Processes an authorization code directly. Usually 197 /// Processes an authorization code directly. Usually
199 /// [handleAuthorizationResponse] is preferable to this method, since it 198 /// [handleAuthorizationResponse] is preferable to this method, since it
200 /// validates all of the query parameters. However, some authorization servers 199 /// validates all of the query parameters. However, some authorization servers
201 /// allow the user to copy and paste an authorization code into a command-line 200 /// allow the user to copy and paste an authorization code into a command-line
202 /// application, in which case this method must be used. 201 /// application, in which case this method must be used.
203 /// 202 ///
204 /// It is a [StateError] to call this more than once, to call it before 203 /// It is a [StateError] to call this more than once, to call it before
205 /// [getAuthorizationUrl] is called, or to call it after 204 /// [getAuthorizationUrl] is called, or to call it after
206 /// [handleAuthorizationCode] is called. 205 /// [handleAuthorizationCode] is called.
207 /// 206 ///
208 /// Throws [FormatError] if the authorization server provides invalid 207 /// Throws [FormatError] if the authorization server provides invalid
209 /// responses while retrieving credentials. 208 /// responses while retrieving credentials.
210 /// 209 ///
211 /// Throws [AuthorizationException] if the authorization fails. 210 /// Throws [AuthorizationException] if the authorization fails.
212 Future<Client> handleAuthorizationCode(String authorizationCode) { 211 Future<Client> handleAuthorizationCode(String authorizationCode) async {
213 return async.then((_) { 212 if (_state == _INITIAL_STATE) {
214 if (_state == _INITIAL_STATE) { 213 throw new StateError(
215 throw new StateError( 214 'The authorization URL has not yet been generated.');
216 'The authorization URL has not yet been generated.'); 215 } else if (_state == _FINISHED_STATE) {
217 } else if (_state == _FINISHED_STATE) { 216 throw new StateError(
218 throw new StateError( 217 'The authorization code has already been received.');
219 'The authorization code has already been received.'); 218 }
220 } 219 _state = _FINISHED_STATE;
221 _state = _FINISHED_STATE;
222 220
223 return _handleAuthorizationCode(authorizationCode); 221 return await _handleAuthorizationCode(authorizationCode);
224 });
225 } 222 }
226 223
227 /// This works just like [handleAuthorizationCode], except it doesn't validate 224 /// This works just like [handleAuthorizationCode], except it doesn't validate
228 /// the state beforehand. 225 /// the state beforehand.
229 Future<Client> _handleAuthorizationCode(String authorizationCode) { 226 Future<Client> _handleAuthorizationCode(String authorizationCode) async {
230 var startTime = new DateTime.now(); 227 var startTime = new DateTime.now();
231 return _httpClient.post(this.tokenEndpoint, body: { 228 var response = await _httpClient.post(this.tokenEndpoint, body: {
232 "grant_type": "authorization_code", 229 "grant_type": "authorization_code",
233 "code": authorizationCode, 230 "code": authorizationCode,
234 "redirect_uri": this._redirectEndpoint.toString(), 231 "redirect_uri": this._redirectEndpoint.toString(),
235 // TODO(nweiz): the spec recommends that HTTP basic auth be used in 232 // TODO(nweiz): the spec recommends that HTTP basic auth be used in
236 // preference to form parameters, but Google doesn't support that. Should 233 // preference to form parameters, but Google doesn't support that. Should
237 // it be configurable? 234 // it be configurable?
238 "client_id": this.identifier, 235 "client_id": this.identifier,
239 "client_secret": this.secret 236 "client_secret": this.secret
240 }).then((response) {
241 var credentials = handleAccessTokenResponse(
242 response, tokenEndpoint, startTime, _scopes);
243 return new Client(
244 this.identifier, this.secret, credentials, httpClient: _httpClient);
245 }); 237 });
238
239 var credentials = handleAccessTokenResponse(
240 response, tokenEndpoint, startTime, _scopes);
241 return new Client(
242 this.identifier, this.secret, credentials, httpClient: _httpClient);
246 } 243 }
247 244
248 /// Closes the grant and frees its resources. 245 /// Closes the grant and frees its resources.
249 /// 246 ///
250 /// This will close the underlying HTTP client, which is shared by the 247 /// This will close the underlying HTTP client, which is shared by the
251 /// [Client] created by this grant, so it's not safe to close the grant and 248 /// [Client] created by this grant, so it's not safe to close the grant and
252 /// continue using the client. 249 /// continue using the client.
253 void close() { 250 void close() {
254 if (_httpClient != null) _httpClient.close(); 251 if (_httpClient != null) _httpClient.close();
255 _httpClient = null; 252 _httpClient = null;
256 } 253 }
257 } 254 }
OLDNEW
« no previous file with comments | « README.md ('k') | lib/src/client.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698