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

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

Issue 812253002: Delete a bunch of packages that are now on GitHub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Un-delete http Created 6 years 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
« no previous file with comments | « pkg/oauth2/lib/src/client.dart ('k') | pkg/oauth2/lib/src/expiration_exception.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 credentials;
6
7 import 'dart:async';
8 import 'dart:convert';
9
10 import 'package:http/http.dart' as http;
11
12 import 'handle_access_token_response.dart';
13 import 'utils.dart';
14
15 /// Credentials that prove that a client is allowed to access a resource on the
16 /// resource owner's behalf. These credentials are long-lasting and can be
17 /// safely persisted across multiple runs of the program.
18 ///
19 /// Many authorization servers will attach an expiration date to a set of
20 /// credentials, along with a token that can be used to refresh the credentials
21 /// once they've expired. The [Client] will automatically refresh its
22 /// credentials when necessary. It's also possible to explicitly refresh them
23 /// via [Client.refreshCredentials] or [Credentials.refresh].
24 ///
25 /// Note that a given set of credentials can only be refreshed once, so be sure
26 /// to save the refreshed credentials for future use.
27 class Credentials {
28 /// The token that is sent to the resource server to prove the authorization
29 /// of a client.
30 final String accessToken;
31
32 /// The token that is sent to the authorization server to refresh the
33 /// credentials. This is optional.
34 final String refreshToken;
35
36 /// The URL of the authorization server endpoint that's used to refresh the
37 /// credentials. This is optional.
38 final Uri tokenEndpoint;
39
40 /// The specific permissions being requested from the authorization server.
41 /// The scope strings are specific to the authorization server and may be
42 /// found in its documentation.
43 final List<String> scopes;
44
45 /// The date at which these credentials will expire. This is likely to be a
46 /// few seconds earlier than the server's idea of the expiration date.
47 final DateTime expiration;
48
49 /// Whether or not these credentials have expired. Note that it's possible the
50 /// credentials will expire shortly after this is called. However, since the
51 /// client's expiration date is kept a few seconds earlier than the server's,
52 /// there should be enough leeway to rely on this.
53 bool get isExpired => expiration != null &&
54 new DateTime.now().isAfter(expiration);
55
56 /// Whether it's possible to refresh these credentials.
57 bool get canRefresh => refreshToken != null && tokenEndpoint != null;
58
59 /// Creates a new set of credentials.
60 ///
61 /// This class is usually not constructed directly; rather, it's accessed via
62 /// [Client.credentials] after a [Client] is created by
63 /// [AuthorizationCodeGrant]. Alternately, it may be loaded from a serialized
64 /// form via [Credentials.fromJson].
65 Credentials(
66 this.accessToken,
67 [this.refreshToken,
68 this.tokenEndpoint,
69 this.scopes,
70 this.expiration]);
71
72 /// Loads a set of credentials from a JSON-serialized form. Throws
73 /// [FormatException] if the JSON is incorrectly formatted.
74 factory Credentials.fromJson(String json) {
75 void validate(bool condition, String message) {
76 if (condition) return;
77 throw new FormatException(
78 "Failed to load credentials: $message.\n\n$json");
79 }
80
81 var parsed;
82 try {
83 parsed = JSON.decode(json);
84 } on FormatException catch (e) {
85 validate(false, 'invalid JSON');
86 }
87
88 validate(parsed is Map, 'was not a JSON map');
89 validate(parsed.containsKey('accessToken'),
90 'did not contain required field "accessToken"');
91 validate(parsed['accessToken'] is String,
92 'required field "accessToken" was not a string, was '
93 '${parsed["accessToken"]}');
94
95
96 for (var stringField in ['refreshToken', 'tokenEndpoint']) {
97 var value = parsed[stringField];
98 validate(value == null || value is String,
99 'field "$stringField" was not a string, was "$value"');
100 }
101
102 var scopes = parsed['scopes'];
103 validate(scopes == null || scopes is List,
104 'field "scopes" was not a list, was "$scopes"');
105
106 var tokenEndpoint = parsed['tokenEndpoint'];
107 if (tokenEndpoint != null) {
108 tokenEndpoint = Uri.parse(tokenEndpoint);
109 }
110 var expiration = parsed['expiration'];
111 if (expiration != null) {
112 validate(expiration is int,
113 'field "expiration" was not an int, was "$expiration"');
114 expiration = new DateTime.fromMillisecondsSinceEpoch(expiration);
115 }
116
117 return new Credentials(
118 parsed['accessToken'],
119 parsed['refreshToken'],
120 tokenEndpoint,
121 scopes,
122 expiration);
123 }
124
125 /// Serializes a set of credentials to JSON. Nothing is guaranteed about the
126 /// output except that it's valid JSON and compatible with
127 /// [Credentials.toJson].
128 String toJson() => JSON.encode({
129 'accessToken': accessToken,
130 'refreshToken': refreshToken,
131 'tokenEndpoint': tokenEndpoint == null ? null : tokenEndpoint.toString(),
132 'scopes': scopes,
133 'expiration': expiration == null ? null : expiration.millisecondsSinceEpoch
134 });
135
136 /// Returns a new set of refreshed credentials. See [Client.identifier] and
137 /// [Client.secret] for explanations of those parameters.
138 ///
139 /// You may request different scopes than the default by passing in
140 /// [newScopes]. These must be a subset of [scopes].
141 ///
142 /// This will throw a [StateError] if these credentials can't be refreshed, an
143 /// [AuthorizationException] if refreshing the credentials fails, or a
144 /// [FormatError] if the authorization server returns invalid responses.
145 Future<Credentials> refresh(
146 String identifier,
147 String secret,
148 {List<String> newScopes,
149 http.Client httpClient}) {
150 var scopes = this.scopes;
151 if (newScopes != null) scopes = newScopes;
152 if (scopes == null) scopes = <String>[];
153 if (httpClient == null) httpClient = new http.Client();
154
155 var startTime = new DateTime.now();
156 return async.then((_) {
157 if (refreshToken == null) {
158 throw new StateError("Can't refresh credentials without a refresh "
159 "token.");
160 } else if (tokenEndpoint == null) {
161 throw new StateError("Can't refresh credentials without a token "
162 "endpoint.");
163 }
164
165 var fields = {
166 "grant_type": "refresh_token",
167 "refresh_token": refreshToken,
168 // TODO(nweiz): the spec recommends that HTTP basic auth be used in
169 // preference to form parameters, but Google doesn't support that.
170 // Should it be configurable?
171 "client_id": identifier,
172 "client_secret": secret
173 };
174 if (!scopes.isEmpty) fields["scope"] = scopes.join(' ');
175
176 return httpClient.post(tokenEndpoint, body: fields);
177 }).then((response) {
178 return handleAccessTokenResponse(
179 response, tokenEndpoint, startTime, scopes);
180 }).then((credentials) {
181 // The authorization server may issue a new refresh token. If it doesn't,
182 // we should re-use the one we already have.
183 if (credentials.refreshToken != null) return credentials;
184 return new Credentials(
185 credentials.accessToken,
186 this.refreshToken,
187 credentials.tokenEndpoint,
188 credentials.scopes,
189 credentials.expiration);
190 });
191 }
192 }
OLDNEW
« no previous file with comments | « pkg/oauth2/lib/src/client.dart ('k') | pkg/oauth2/lib/src/expiration_exception.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698