| OLD | NEW | 
|---|
| 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 oauth2_client; | 5 library oauth2.client; | 
| 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 | 
| 11 import 'authorization_exception.dart'; | 11 import 'authorization_exception.dart'; | 
| 12 import 'credentials.dart'; | 12 import 'credentials.dart'; | 
| 13 import 'expiration_exception.dart'; | 13 import 'expiration_exception.dart'; | 
| 14 import 'utils.dart'; | 14 import 'utils.dart'; | 
| 15 | 15 | 
| 16 // TODO(nweiz): Add an onCredentialsRefreshed event once we have some event | 16 // TODO(nweiz): Add an onCredentialsRefreshed event once we have some event | 
| 17 // infrastructure. | 17 // infrastructure. | 
| 18 /// An OAuth2 client. This acts as a drop-in replacement for an [http.Client], | 18 /// An OAuth2 client. | 
| 19 /// while sending OAuth2 authorization credentials along with each request. | 19 /// | 
|  | 20 /// This acts as a drop-in replacement for an [http.Client], while sending | 
|  | 21 /// OAuth2 authorization credentials along with each request. | 
| 20 /// | 22 /// | 
| 21 /// The client also automatically refreshes its credentials if possible. When it | 23 /// The client also automatically refreshes its credentials if possible. When it | 
| 22 /// makes a request, if its credentials are expired, it will first refresh them. | 24 /// makes a request, if its credentials are expired, it will first refresh them. | 
| 23 /// This means that any request may throw an [AuthorizationException] if the | 25 /// This means that any request may throw an [AuthorizationException] if the | 
| 24 /// refresh is not authorized for some reason, a [FormatException] if the | 26 /// refresh is not authorized for some reason, a [FormatException] if the | 
| 25 /// authorization server provides ill-formatted responses, or an | 27 /// authorization server provides ill-formatted responses, or an | 
| 26 /// [ExpirationException] if the credentials are expired and can't be refreshed. | 28 /// [ExpirationException] if the credentials are expired and can't be refreshed. | 
| 27 /// | 29 /// | 
| 28 /// The client will also throw an [AuthorizationException] if the resource | 30 /// The client will also throw an [AuthorizationException] if the resource | 
| 29 /// server returns a 401 response with a WWW-Authenticate header indicating that | 31 /// server returns a 401 response with a WWW-Authenticate header indicating that | 
| 30 /// the current credentials are invalid. | 32 /// the current credentials are invalid. | 
| 31 /// | 33 /// | 
| 32 /// If you already have a set of [Credentials], you can construct a [Client] | 34 /// If you already have a set of [Credentials], you can construct a [Client] | 
| 33 /// directly. However, in order to first obtain the credentials, you must | 35 /// directly. However, in order to first obtain the credentials, you must | 
| 34 /// authorize. At the time of writing, the only authorization method this | 36 /// authorize. At the time of writing, the only authorization method this | 
| 35 /// library supports is [AuthorizationCodeGrant]. | 37 /// library supports is [AuthorizationCodeGrant]. | 
| 36 class Client extends http.BaseClient { | 38 class Client extends http.BaseClient { | 
| 37   /// The client identifier for this client. The authorization server will issue | 39   /// The client identifier for this client. | 
| 38   /// each client a separate client identifier and secret, which allows the | 40   /// | 
| 39   /// server to tell which client is accessing it. Some servers may also have an | 41   /// The authorization server will issue each client a separate client | 
| 40   /// anonymous identifier/secret pair that any client may use. | 42   /// identifier and secret, which allows the server to tell which client is | 
|  | 43   /// accessing it. Some servers may also have an anonymous identifier/secret | 
|  | 44   /// pair that any client may use. | 
| 41   /// | 45   /// | 
| 42   /// This is usually global to the program using this library. | 46   /// This is usually global to the program using this library. | 
| 43   final String identifier; | 47   final String identifier; | 
| 44 | 48 | 
| 45   /// The client secret for this client. The authorization server will issue | 49   /// The client secret for this client. | 
| 46   /// each client a separate client identifier and secret, which allows the | 50   /// | 
| 47   /// server to tell which client is accessing it. Some servers may also have an | 51   /// The authorization server will issue each client a separate client | 
| 48   /// anonymous identifier/secret pair that any client may use. | 52   /// identifier and secret, which allows the server to tell which client is | 
|  | 53   /// accessing it. Some servers may also have an anonymous identifier/secret | 
|  | 54   /// pair that any client may use. | 
| 49   /// | 55   /// | 
| 50   /// This is usually global to the program using this library. | 56   /// This is usually global to the program using this library. | 
| 51   /// | 57   /// | 
| 52   /// Note that clients whose source code or binary executable is readily | 58   /// Note that clients whose source code or binary executable is readily | 
| 53   /// available may not be able to make sure the client secret is kept a secret. | 59   /// available may not be able to make sure the client secret is kept a secret. | 
| 54   /// This is fine; OAuth2 servers generally won't rely on knowing with | 60   /// This is fine; OAuth2 servers generally won't rely on knowing with | 
| 55   /// certainty that a client is who it claims to be. | 61   /// certainty that a client is who it claims to be. | 
| 56   final String secret; | 62   final String secret; | 
| 57 | 63 | 
| 58   /// The credentials this client uses to prove to the resource server that it's | 64   /// The credentials this client uses to prove to the resource server that it's | 
| 59   /// authorized. This may change from request to request as the credentials | 65   /// authorized. | 
| 60   /// expire and the client refreshes them automatically. | 66   /// | 
|  | 67   /// This may change from request to request as the credentials expire and the | 
|  | 68   /// client refreshes them automatically. | 
| 61   Credentials get credentials => _credentials; | 69   Credentials get credentials => _credentials; | 
| 62   Credentials _credentials; | 70   Credentials _credentials; | 
| 63 | 71 | 
| 64   /// The underlying HTTP client. | 72   /// The underlying HTTP client. | 
| 65   http.Client _httpClient; | 73   http.Client _httpClient; | 
| 66 | 74 | 
| 67   /// Creates a new client from a pre-existing set of credentials. When | 75   /// Creates a new client from a pre-existing set of credentials. | 
| 68   /// authorizing a client for the first time, you should use | 76   /// | 
|  | 77   /// When authorizing a client for the first time, you should use | 
| 69   /// [AuthorizationCodeGrant] instead of constructing a [Client] directly. | 78   /// [AuthorizationCodeGrant] instead of constructing a [Client] directly. | 
| 70   /// | 79   /// | 
| 71   /// [httpClient] is the underlying client that this forwards requests to after | 80   /// [httpClient] is the underlying client that this forwards requests to after | 
| 72   /// adding authorization credentials to them. | 81   /// adding authorization credentials to them. | 
| 73   Client( | 82   Client( | 
| 74       this.identifier, | 83       this.identifier, | 
| 75       this.secret, | 84       this.secret, | 
| 76       this._credentials, | 85       this._credentials, | 
| 77       {http.Client httpClient}) | 86       {http.Client httpClient}) | 
| 78     : _httpClient = httpClient == null ? new http.Client() : httpClient; | 87     : _httpClient = httpClient == null ? new http.Client() : httpClient; | 
| 79 | 88 | 
| 80   /// Sends an HTTP request with OAuth2 authorization credentials attached. This | 89   /// Sends an HTTP request with OAuth2 authorization credentials attached. | 
| 81   /// will also automatically refresh this client's [Credentials] before sending | 90   /// | 
| 82   /// the request if necessary. | 91   /// This will also automatically refresh this client's [Credentials] before | 
|  | 92   /// sending the request if necessary. | 
| 83   Future<http.StreamedResponse> send(http.BaseRequest request) async { | 93   Future<http.StreamedResponse> send(http.BaseRequest request) async { | 
| 84     if (credentials.isExpired) { | 94     if (credentials.isExpired) { | 
| 85       if (!credentials.canRefresh) throw new ExpirationException(credentials); | 95       if (!credentials.canRefresh) throw new ExpirationException(credentials); | 
| 86       await refreshCredentials(); | 96       await refreshCredentials(); | 
| 87     } | 97     } | 
| 88 | 98 | 
| 89     request.headers['authorization'] = "Bearer ${credentials.accessToken}"; | 99     request.headers['authorization'] = "Bearer ${credentials.accessToken}"; | 
| 90     var response = await _httpClient.send(request); | 100     var response = await _httpClient.send(request); | 
| 91 | 101 | 
| 92     if (response.statusCode != 401) return response; | 102     if (response.statusCode != 401) return response; | 
| 93     if (!response.headers.containsKey('www-authenticate')) return response; | 103     if (!response.headers.containsKey('www-authenticate')) return response; | 
| 94 | 104 | 
| 95     var authenticate; | 105     var authenticate; | 
| 96     try { | 106     try { | 
| 97       authenticate = new AuthenticateHeader.parse( | 107       authenticate = new AuthenticateHeader.parse( | 
| 98           response.headers['www-authenticate']); | 108           response.headers['www-authenticate']); | 
| 99     } on FormatException catch (e) { | 109     } on FormatException catch (_) { | 
| 100       return response; | 110       return response; | 
| 101     } | 111     } | 
| 102 | 112 | 
| 103     if (authenticate.scheme != 'bearer') return response; | 113     if (authenticate.scheme != 'bearer') return response; | 
| 104 | 114 | 
| 105     var params = authenticate.parameters; | 115     var params = authenticate.parameters; | 
| 106     if (!params.containsKey('error')) return response; | 116     if (!params.containsKey('error')) return response; | 
| 107 | 117 | 
| 108     throw new AuthorizationException( | 118     throw new AuthorizationException( | 
| 109         params['error'], params['error_description'], | 119         params['error'], params['error_description'], | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 132 | 142 | 
| 133     return this; | 143     return this; | 
| 134   } | 144   } | 
| 135 | 145 | 
| 136   /// Closes this client and its underlying HTTP client. | 146   /// Closes this client and its underlying HTTP client. | 
| 137   void close() { | 147   void close() { | 
| 138     if (_httpClient != null) _httpClient.close(); | 148     if (_httpClient != null) _httpClient.close(); | 
| 139     _httpClient = null; | 149     _httpClient = null; | 
| 140   } | 150   } | 
| 141 } | 151 } | 
| OLD | NEW | 
|---|