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

Side by Side Diff: utils/pub/oauth2.dart

Issue 11348268: Don't require users to copy-paste authorization codes when authorizing pub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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 | « no previous file | utils/pub/utils.dart » ('j') | utils/pub/utils.dart » ('J')
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 oauth2; 5 library oauth2;
6 6
7 import 'dart:io'; 7 import 'dart:io';
8 import 'dart:uri'; 8 import 'dart:uri';
9 9
10 // TODO(nweiz): Make this a "package:" URL, or something nicer than this. 10 // TODO(nweiz): Make this a "package:" URL, or something nicer than this.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 completer.completeException(e, stackTrace); 71 completer.completeException(e, stackTrace);
72 } 72 }
73 }); 73 });
74 return completer.future; 74 return completer.future;
75 }); 75 });
76 } 76 }
77 77
78 /// Gets a new OAuth2 client. If saved credentials are available, those are 78 /// Gets a new OAuth2 client. If saved credentials are available, those are
79 /// used; otherwise, the user is prompted to authorize the pub client. 79 /// used; otherwise, the user is prompted to authorize the pub client.
80 Future<Client> _getClient(SystemCache cache) { 80 Future<Client> _getClient(SystemCache cache) {
81 var httpClient = new CurlClient();
82
83 return _loadCredentials(cache).chain((credentials) { 81 return _loadCredentials(cache).chain((credentials) {
84 if (credentials != null) { 82 if (credentials == null) return _authorize();
85 return new Future.immediate(new Client( 83 return new Future.immediate(new Client(
Bob Nystrom 2012/11/28 19:35:41 Can't wait until Future unifies chain/transform...
nweiz 2012/11/28 19:42:14 Indeed.
86 _identifier, _secret, credentials, httpClient: httpClient)); 84 _identifier, _secret, credentials, httpClient: new CurlClient()));
87 }
88
89 // Allow the tests to inject their own token endpoint URL.
90 var tokenEndpoint = Platform.environment['_PUB_TEST_TOKEN_ENDPOINT'];
91 if (tokenEndpoint != null) {
92 tokenEndpoint = new Uri.fromString(tokenEndpoint);
93 } else {
94 tokenEndpoint = _tokenEndpoint;
95 }
96
97 var grant = new AuthorizationCodeGrant(
98 _identifier,
99 _secret,
100 _authorizationEndpoint,
101 tokenEndpoint,
102 httpClient: httpClient);
103
104 // TODO(nweiz): spin up a server on localhost and redirect the user there so
105 // they don't have to copy/paste the authorization code. See issue 6951.
106 var authUrl = grant.getAuthorizationUrl(
107 new Uri.fromString('urn:ietf:wg:oauth:2.0:oob'), scopes: _scopes);
108
109 stdout.writeString(
110 'Pub needs your authorization to upload packages on your behalf.\n'
111 'Go to $authUrl\n'
112 'Then click "Allow access" and paste the code below:\n'
113 '> ');
114 return readLine().chain(grant.handleAuthorizationCode);
115 }).chain((client) { 85 }).chain((client) {
116 return _saveCredentials(cache, client.credentials).transform((_) => client); 86 return _saveCredentials(cache, client.credentials).transform((_) => client);
117 }); 87 });
118 } 88 }
119 89
120 /// Loads the user's OAuth2 credentials from the in-memory cache or the 90 /// Loads the user's OAuth2 credentials from the in-memory cache or the
121 /// filesystem if possible. If the credentials can't be loaded for any reason, 91 /// filesystem if possible. If the credentials can't be loaded for any reason,
122 /// the returned [Future] will complete to null. 92 /// the returned [Future] will complete to null.
123 Future<Credentials> _loadCredentials(SystemCache cache) { 93 Future<Credentials> _loadCredentials(SystemCache cache) {
124 if (_credentials != null) return new Future.immediate(_credentials); 94 if (_credentials != null) return new Future.immediate(_credentials);
(...skipping 23 matching lines...) Expand all
148 Future _saveCredentials(SystemCache cache, Credentials credentials) { 118 Future _saveCredentials(SystemCache cache, Credentials credentials) {
149 _credentials = credentials; 119 _credentials = credentials;
150 var credentialsFile = _credentialsFile(cache); 120 var credentialsFile = _credentialsFile(cache);
151 return ensureDir(dirname(credentialsFile)).chain((_) => 121 return ensureDir(dirname(credentialsFile)).chain((_) =>
152 writeTextFile(credentialsFile, credentials.toJson())); 122 writeTextFile(credentialsFile, credentials.toJson()));
153 } 123 }
154 124
155 /// The path to the file in which the user's OAuth2 credentials are stored. 125 /// The path to the file in which the user's OAuth2 credentials are stored.
156 String _credentialsFile(SystemCache cache) => 126 String _credentialsFile(SystemCache cache) =>
157 join(cache.rootDir, 'credentials.json'); 127 join(cache.rootDir, 'credentials.json');
128
129 /// Gets the user to authorize pub as a client of pub.dartlang.org via oauth2.
130 /// Returns a Future that will complete to a fully-authorized [Client].
131 Future<Client> _authorize() {
132 // Allow the tests to inject their own token endpoint URL.
133 var tokenEndpoint = Platform.environment['_PUB_TEST_TOKEN_ENDPOINT'];
134 if (tokenEndpoint != null) {
135 tokenEndpoint = new Uri.fromString(tokenEndpoint);
136 } else {
137 tokenEndpoint = _tokenEndpoint;
138 }
139
140 var grant = new AuthorizationCodeGrant(
141 _identifier,
142 _secret,
143 _authorizationEndpoint,
144 tokenEndpoint,
145 httpClient: new CurlClient());
146
147 // Spin up a one-shot HTTP server to receive the authorization code from the
148 // Google OAuth2 server via redirect. This server will close itself as soon as
149 // the code is received.
150 var completer = new Completer();
151 var server = new HttpServer();
152 server.addRequestHandler((request) => request.path == "/", (request, response) {
Bob Nystrom 2012/11/28 19:35:41 Long line.
nweiz 2012/11/28 19:42:14 Done.
153 chainToCompleter(new Future.immediate(null).chain((_) {
154 print('Authorization received, processing...');
155 var queryString = request.queryString;
156 if (queryString == null) queryString = '';
157 response.statusCode = 302;
158 response.headers.set('location', 'http://pub.dartlang.org/authorized');
159 response.outputStream.close();
160 server.close();
161 return grant.handleAuthorizationResponse(queryToMap(queryString));
162 }), completer);
163 });
164 server.listen('127.0.0.1', 0);
165
166 var authUrl = grant.getAuthorizationUrl(
167 new Uri.fromString('http://localhost:${server.port}'), scopes: _scopes);
168
169 print('Pub needs your authorization to upload packages on your behalf.\n'
170 'Go to $authUrl\n'
Bob Nystrom 2012/11/28 19:35:41 "In a web browser, go to"?
nweiz 2012/11/28 19:42:14 Done.
171 'Then click "Allow access".\n\n'
172 'Waiting for your authorization...');
173
174 return completer.future.transform((client) {
175 print('Successfully authorized.\n');
176 return client;
177 });
178 }
OLDNEW
« no previous file with comments | « no previous file | utils/pub/utils.dart » ('j') | utils/pub/utils.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698