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

Side by Side Diff: pkg/oauth2/lib/src/client.dart

Issue 11420025: Add a package for authenticating via OAuth2. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Misc fixes Created 8 years, 1 month 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library client;
6
7 import 'dart:uri';
8
9 import '../../../http/lib/http.dart' as http;
10
11 import 'credentials.dart';
12 import 'utils.dart';
13
14 /// An OAuth2 client. This acts as a drop-in replacement for an
15 /// [http.BaseClient], while sending OAuth2 authorization credentials along with
16 /// each request.
17 ///
18 /// The client also automatically refreshes its credentials if possible. When it
19 /// makes a request, if its credentials are expired, it will first refresh them.
20 /// This means that any request may throw an [AuthorizationException] if the
21 /// refresh is not authorized for some reason, a [FormatException] if the
22 /// authorization server provides ill-formatted responses, or a [StateError] if
23 /// the credentials are expired and can't be refreshed.
Bob Nystrom 2012/11/16 19:53:30 This shouldn't be a StateError, I think. StateErro
nweiz 2012/11/17 01:06:27 Done.
24 ///
25 /// Currently this client doesn't attempt to identify errors from the resource
26 /// server that are caused by authentication failure. However, it may throw
27 /// [AuthorizationException]s for such errors in the future.
28 ///
29 /// If you already have a set of [Credentials], you can construct a [Client]
30 /// directly. However, in order to first obtain the credentials, you must
31 /// authorize. At the time of writing, the only authorization method this
32 /// library supports is [AuthorizationCodeGrant].
33 class Client extends http.BaseClient {
34 /// The client identifier for this client. The authorization server will issue
35 /// each client a separate client identifier and secret, which allows the
36 /// server to tell which client is accessing it. Some servers may also have an
37 /// anonymous identifier/secret pair that any client may use.
38 ///
39 /// This is usually global to the program using this library.
40 final String identifier;
41
42 /// The client secret for this client. The authorization server will issue
43 /// each client a separate client identifier and secret, which allows the
44 /// server to tell which client is accessing it. Some servers may also have an
45 /// anonymous identifier/secret pair that any client may use.
46 ///
47 /// This is usually global to the program using this library.
48 ///
49 /// Note that clients whose source code or binary executable is readily
50 /// available may not be able to make sure the client secret is kept a secret.
51 /// This is fine; OAuth2 servers generally won't rely on knowing with
52 /// certainty that a client is who it claims to be.
53 final String secret;
54
55 /// The credentials this client uses to prove to the resource server that it's
56 /// authorized. This may change from request to request as the credentials
57 /// expire and the client refreshes them automatically.
58 Credentials get credentials => _credentials;
59 Credentials _credentials;
60
61 /// The underlying HTTP client.
62 final http.BaseClient _httpClient;
63
64 /// Creates a new client from a pre-existing set of credentials. When
65 /// authorizing a client for the first time, you should use
66 /// [AuthorizationCodeGrant] instead of constructing a [Client] directly.
67 ///
68 /// `httpClient` is the underlying client that this forwards requests to after
69 /// adding authorization credentials to them.
70 Client(
71 this.identifier,
72 this.secret,
73 this._credentials,
74 {http.BaseClient httpClient})
75 : _httpClient = httpClient == null ? new http.Client() : httpClient;
76
77 /// Sends an HTTP request with OAuth2 authorization credentials attached. This
78 /// will also automatically refresh this client's [Credentials] before sending
79 /// the request if necessary.
80 Future<http.Response> send(http.Request request) {
81 return async.chain((_) {
82 if (!credentials.isExpired) return new Future.immediate(null);
83 return refreshCredentials();
84 }).chain((_) {
85 request.headers['authorization'] = "Bearer ${credentials.accessToken}";
86 return _httpClient.send(request);
87 });
88 // TODO(nweiz): parse 401 errors that are caused by OAuth errors here.
89 }
90
91 /// Explicitly refreshes this client's credentials. Returns this client.
92 ///
93 /// This will throw a [StateError] if the [Credentials] can't be refreshed, an
Bob Nystrom 2012/11/16 19:53:30 Throwing a StateError here is OK if it's something
nweiz 2012/11/17 01:06:27 Yes.
94 /// [AuthorizationException] if refreshing the credentials fails, or a
95 /// [FormatError] if the authorization server returns invalid responses.
96 ///
97 /// You may request different scopes than the default by passing in
98 /// `newScopes`. These must be a subset of the scopes in the
99 /// [Credentials.scopes] field of [Client.credentials].
100 Future<Client> refreshCredentials([List<String> newScopes]) {
Bob Nystrom 2012/11/16 19:53:30 Any particular reason to complete with the client?
nweiz 2012/11/17 01:06:27 Yep.
101 return async.chain((_) {
102 if (!credentials.canRefresh) {
103 var prefix = "OAuth credentials";
104 if (credentials.isExpired) prefix = "$prefix have expired and";
105 throw new StateError("$prefix can't be refreshed.");
106 }
107
108 return credentials.refresh(identifier, secret,
109 newScopes: newScopes, httpClient: _httpClient);
110 }).transform((credentials) {
111 _credentials = credentials;
112 return this;
113 });
114 }
115
116 /// Closes this client and its underlying HTTP client.
117 void close() {
118 if (_httpClient != null) _httpClient.close();
119 _httpClient = null;
120 }
121 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698