applicationDefaultCredentialsAuthenticator function
Create an HttpBasedAuthenticator using Application Default Credentials.
Looks for credentials in the following order of preference:
- A JSON file whose path is specified by
GOOGLE_APPLICATION_CREDENTIALS
, this file typically contains exported service account keys. - A JSON file created by
gcloud auth application-default login
in a well-known location (%APPDATA%/gcloud/application_default_credentials.json
on Windows and$HOME/.config/gcloud/application_default_credentials.json
on Linux/Mac). - On Google Compute Engine and App Engine Flex we fetch credentials from GCE metadata service.
Implementation
Future<HttpBasedAuthenticator> applicationDefaultCredentialsAuthenticator(
List<String> scopes,
) async {
File? credFile;
String? fileSource;
// If env var specifies a file to load credentials from we'll do that.
final credsEnv = Platform.environment['GOOGLE_APPLICATION_CREDENTIALS'];
if (credsEnv != null && credsEnv.isNotEmpty) {
// If env var is specified and not empty, we always try to load, even if
// the file doesn't exist.
credFile = File(credsEnv);
fileSource = 'GOOGLE_APPLICATION_CREDENTIALS';
}
// Attempt to use file created by `gcloud auth application-default login`
File gcloudAdcFile;
if (Platform.isWindows) {
gcloudAdcFile = File.fromUri(Uri.directory(Platform.environment['APPDATA']!)
.resolve('gcloud/application_default_credentials.json'));
} else {
gcloudAdcFile = File.fromUri(Uri.directory(Platform.environment['HOME']!)
.resolve('.config/gcloud/application_default_credentials.json'));
}
// Only try to load from gcloudAdcFile if it exists.
if (credFile == null && await gcloudAdcFile.exists()) {
credFile = gcloudAdcFile;
fileSource = '`gcloud auth application-default login`';
}
// Attempt to load form credFile, if detected
if (credFile != null) {
Object? credentials;
try {
credentials = json.decode(await credFile.readAsString());
} on IOException {
throw Exception(
'Failed to read credentials file from $fileSource',
);
} on FormatException {
throw Exception(
'Failed to parse JSON from credentials file from $fileSource',
);
}
if (credentials is Map && credentials['type'] == 'authorized_user') {
final clientId = auth.ClientId(
credentials['client_id'],
credentials['client_secret'],
);
final client = http.Client();
try {
final accessCreds = await auth.refreshCredentials(
clientId,
auth.AccessCredentials(
// Hack: Create empty credentials that have expired.
auth.AccessToken('Bearer', '', DateTime(0).toUtc()),
credentials['refresh_token'],
scopes,
),
client,
);
return _CredentialsRefreshingAuthenticator(
clientId,
accessCreds,
credentials['quota_project_id'],
);
} finally {
client.close();
}
}
return ServiceAccountAuthenticator(json.encode(credentials), scopes);
}
return ComputeEngineAuthenticator();
}