33// BSD-style license that can be found in the LICENSE file.
44
55library oauth2;
6+ import 'dart:core' ;
67
78import 'dart:async' ;
9+ import 'dart:convert' ;
810
911import 'package:oauth2/oauth2.dart' ;
1012import 'package:path/path.dart' as path;
13+ import 'package:http/http.dart' as http;
1114
1215import 'http.dart' ;
1316import 'io.dart' ;
@@ -303,4 +306,143 @@ class SimpleOAuth2Console implements OAuth2Console {
303306 Uri _authorizationEndpoint;
304307 List <String > _request_visible_actions;
305308 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