3
3
// BSD-style license that can be found in the LICENSE file.
4
4
5
5
library oauth2;
6
+ import 'dart:core' ;
6
7
7
8
import 'dart:async' ;
9
+ import 'dart:convert' ;
8
10
9
11
import 'package:oauth2/oauth2.dart' ;
10
12
import 'package:path/path.dart' as path;
13
+ import 'package:http/http.dart' as http;
11
14
12
15
import 'http.dart' ;
13
16
import 'io.dart' ;
@@ -303,4 +306,143 @@ class SimpleOAuth2Console implements OAuth2Console {
303
306
Uri _authorizationEndpoint;
304
307
List <String > _request_visible_actions;
305
308
PubHttpClient _httpClient;
306
- }
309
+ }
310
+
311
+ /**
312
+ * A compute engine oauth2 console client.
313
+ */
314
+ class ComputeOAuth2Console implements OAuth2Console {
315
+ Uri _tokenEndpoint =
316
+ Uri .parse ('http://metadata/computeMetadata/v1beta1/instance/service-accounts/default/token' );
317
+ Uri get tokenEndpoint => _tokenEndpoint;
318
+
319
+ Credentials _credentials;
320
+
321
+ Credentials get credentials => _credentials;
322
+
323
+ void set credentials (value) {
324
+ _credentials = value;
325
+ }
326
+
327
+ String _identifier = "" ;
328
+
329
+ String _secret = "" ;
330
+
331
+ String _accessToken = "" ;
332
+
333
+ final int authorizationResponseServerPort = null ;
334
+
335
+ Client _simpleHttpClient;
336
+
337
+ final String projectId;
338
+ ComputeOAuth2Console (this .projectId);
339
+
340
+ Future withClient (Future fn (Client client)) {
341
+ log.fine ("withClient(Future ${fn }(Client client))" );
342
+ _simpleHttpClient = new ComputeEngineClient (projectId);
343
+ return fn (_simpleHttpClient);
344
+ }
345
+
346
+ void close () {
347
+ _simpleHttpClient.close ();
348
+ }
349
+
350
+ /*
351
+ * Methods and variables not supported by this client.
352
+ */
353
+
354
+ void clearCredentials () {
355
+ throw new UnsupportedError ("clearCredentials" );
356
+ }
357
+
358
+ void set authorizedRedirect (String _authorizedRedirect) {
359
+ throw new UnsupportedError ("authorizedRedirect" );
360
+ }
361
+
362
+ String get authorizedRedirect => null ;
363
+
364
+ String get credentialsFilePath => null ;
365
+
366
+ void set credentialsFilePath (String _credentialsFilePath) {
367
+ throw new UnsupportedError ("credentialsFilePath" );
368
+ }
369
+
370
+ Future <Client > _getClient () {
371
+ throw new UnsupportedError ("_getClient" );
372
+ }
373
+
374
+ Credentials _loadCredentials () {
375
+ throw new UnsupportedError ("_loadCredentials" );
376
+ }
377
+ void _saveCredentials (Credentials credentials) {
378
+ throw new UnsupportedError ("_saveCredentials" );
379
+ }
380
+ Future _authorize () {
381
+ throw new UnsupportedError ("_authorize" );
382
+ }
383
+
384
+ List _scopes;
385
+ Uri _authorizationEndpoint;
386
+ List <String > _request_visible_actions;
387
+ PubHttpClient _httpClient;
388
+ }
389
+
390
+ class ComputeEngineClient extends http.BaseClient implements Client {
391
+ final String identifier = "" ;
392
+ final String secret = "" ;
393
+ final String projectId;
394
+ Credentials get credentials => _credentials;
395
+ Credentials _credentials;
396
+ http.Client _httpClient;
397
+
398
+ Uri _tokenEndpoint =
399
+ Uri .parse ('http://metadata/computeMetadata/v1beta1/instance/service-accounts/default/token' );
400
+
401
+ ComputeEngineClient (this .projectId,
402
+ {http.Client httpClient})
403
+ : _httpClient = httpClient == null ? new http.Client () : httpClient;
404
+
405
+ Future <http.StreamedResponse > send (http.BaseRequest request) {
406
+ return async .then ((_) {
407
+ // TODO: check if credentials need to be refreshed.
408
+ return refreshCredentials ();
409
+ }).then ((_) {
410
+ request.headers['Authorization' ] = "OAuth ${credentials .accessToken }" ;
411
+ request.headers['x-goog-api-version' ] = "2" ;
412
+ request.headers['x-goog-project-id' ] = "${projectId }" ;
413
+ return _httpClient.send (request);
414
+ }).then ((response) {
415
+ return response;
416
+ });
417
+ }
418
+
419
+ Future <Client > refreshCredentials ([List <String > newScopes]) {
420
+ return async .then ((_) {
421
+ return _httpClient.get (_tokenEndpoint,
422
+ headers: {'X-Google-Metadata-Request' : 'True' });
423
+ }).then ((http.Response response) {
424
+ if (response.statusCode == 200 ) {
425
+ // Successful request
426
+ var tokenData = JSON .decode (response.body);
427
+ int expiresIn = tokenData["expires_in" ];
428
+ var expiresTime = new DateTime .now ();
429
+ expiresTime = expiresTime.add (new Duration (seconds: expiresIn));
430
+ _credentials = new Credentials (tokenData["access_token" ], null , null ,
431
+ null , expiresTime);
432
+ return this ;
433
+ } else {
434
+ // Unsuccessful request
435
+ throw new StateError ("status code = ${response .statusCode }" );
436
+ }
437
+ });
438
+ }
439
+
440
+ void close () {
441
+ if (_httpClient != null ) _httpClient.close ();
442
+ _httpClient = null ;
443
+ }
444
+ }
445
+
446
+ /// Returns a [Future] that asynchronously completes to `null` .
447
+ Future get async => new Future .delayed (const Duration (milliseconds: 0 ),
448
+ () => null );
0 commit comments