Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions googleapis_auth/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
## 2.1.0-wip
## 2.1.0

- `AuthClient`
- Added `serviceAccountCredentials` getter.
- Added `sign()` method via `AuthClientSigningExtension`.
- `AuthClientSigningExtension`: Added `sign()` which accepts an optional `serviceAccountCredentials` argument, and `getServiceAccountEmail()` which accepts an optional `email` argument.
- `ServiceAccountCredentials`
- Added parsing for `projectId` and `universeDomain` properties.
- Added `sign()` method for RSA-SHA256 signing.
- `IAMSigner`
- Now uses the unified metadata cache from `package:google_cloud`.
- Added `signBlob()` function for signing via IAM Credentials API.
- `MetadataServerAuthorizationFlow`
- Now uses `getMetadataValue` (caching) and `fetchMetadataValue`
(non-caching) from `package:google_cloud`.
Expand Down
19 changes: 13 additions & 6 deletions googleapis_auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ This package also provides convenience functionality for:
- obtaining authenticated HTTP clients
- automatically refreshing OAuth2 credentials

> [!WARNING]
> Do _**NOT**_ use this package (`package:googleapis_auth`) with a
> [Flutter](https://flutter.dev/) application.
>
Expand Down Expand Up @@ -47,11 +48,12 @@ After the Client ID has been created, you can obtain access credentials via
```dart
import 'package:googleapis_auth/auth_browser.dart';

// Initialize the browser oauth2 flow functionality then use it to obtain credentials.
// Initialize the browser oauth2 flow functionality then use it to obtain
// credentials.
Future<AccessCredentials> obtainCredentials() => requestAccessCredentials(
clientId: '....apps.googleusercontent.com',
scopes: ['scope1', 'scope2'],
);
clientId: '....apps.googleusercontent.com',
scopes: ['scope1', 'scope2'],
);
```

or obtain an authenticated HTTP client via
Expand Down Expand Up @@ -207,7 +209,7 @@ Here is an example of getting an HTTP client which uses an API key for making
HTTP requests.

```dart
import "package:googleapis_auth/auth_io.dart";
import 'package:googleapis_auth/auth_io.dart';

var client = clientViaApiKey('<api-key-from-devconsole>');
// [client] can now be used to make REST calls to Google APIs.
Expand Down Expand Up @@ -240,11 +242,16 @@ class MicrosoftAuthEndpoints extends AuthEndpoints {
This can then be used to obtain credentials:

```dart
final clientId = ClientId('my-client-id', 'my-client-secret');
final credentials = await obtainAccessCredentialsViaUserConsent(
clientId,
['scope1', 'scope2'],
client,
prompt,
(url) {
print('Please go to the following URL and grant access:');
print(' => $url');
print('');
},
authEndpoints: MicrosoftAuthEndpoints(),
);
```
Expand Down
16 changes: 15 additions & 1 deletion googleapis_auth/lib/googleapis_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
///
/// In most cases, you'll want to import either
/// [auth_io] or [auth_browser] depending on your platform.
///
/// {@canonicalFor access_credentials.AccessCredentials}
/// {@canonicalFor access_token.AccessToken}
/// {@canonicalFor auth_client.AuthClient}
Expand All @@ -19,10 +20,23 @@
/// {@canonicalFor client_id.ClientId}
/// {@canonicalFor exceptions.AccessDeniedException}
/// {@canonicalFor exceptions.ServerRequestFailedException}
/// {@canonicalFor exceptions.RefreshFailedException}
/// {@canonicalFor exceptions.UserConsentException}
/// {@canonicalFor response_type.ResponseType}
/// {@canonicalFor service_account_credentials.ServiceAccountCredentials}
///
/// {@template googleapis_auth_returned_auto_refresh_client}
/// Returns an [AutoRefreshingAuthClient] that will automatically refresh the
/// [AccessCredentials] before they expire.
/// {@endtemplate}
///
/// {@template googleapis_auth_user_consent_return}
/// Returns the [AccessCredentials] containing the access token.
/// {@endtemplate}
///
/// {@template googleapis_auth_client_for_creds}
/// The provided `client` will be used for making the HTTP requests needed to
/// create the returned [AccessCredentials].
/// {@endtemplate}
library;

export 'src/auth_client.dart';
Expand Down
7 changes: 0 additions & 7 deletions googleapis_auth/lib/src/auth_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ import '../auth_io.dart';
abstract class AuthClient implements Client {
/// The credentials currently used for making HTTP requests.
AccessCredentials get credentials;

/// The service account credentials used to create this client, if any.
///
/// Returns `null` if this client was not created via
/// [clientViaServiceAccount] or if the underlying credentials are not
/// service account credentials.
ServiceAccountCredentials? get serviceAccountCredentials;
}

/// A auto-refreshing, authenticated HTTP client.
Expand Down
45 changes: 21 additions & 24 deletions googleapis_auth/lib/src/auth_client_signing_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ library;

import 'dart:convert';

import 'package:google_cloud/general.dart';
import 'iam_signer.dart';
import 'impersonated_auth_client.dart';
import 'service_account_credentials.dart';
import 'utils.dart';

/// Extension providing smart signing capabilities for [AuthClient].
///
Expand Down Expand Up @@ -41,21 +41,17 @@ import 'utils.dart';
/// final signature = await client.sign(utf8.encode('data to sign'));
/// ```
extension AuthClientSigningExtension on AuthClient {
/// Returns the service account email associated with this client.
///
/// If the client was created with explicit [ServiceAccountCredentials],
/// returns the email from those credentials.
///
/// Otherwise, queries the GCE metadata server to retrieve the default
/// Queries the GCE metadata server to retrieve the default
/// service account email.
///
/// The result is cached for the lifetime of the Dart process by the
/// underlying [IAMSigner].
/// The result is cached for the lifetime of the Dart process.
///
/// If [refresh] is `true`, the cache is cleared and the value is re-computed.
Future<String> getServiceAccountEmail({bool refresh = false}) async =>
serviceAccountCredentials?.email ??
await IAMSigner(this).getServiceAccountEmail(refresh: refresh);
await serviceAccountEmailFromMetadataServer(
client: this,
refresh: refresh,
);

/// Signs some bytes using the credentials from this auth client.
///
Expand All @@ -67,7 +63,8 @@ extension AuthClientSigningExtension on AuthClient {
/// - Other auth clients: Uses IAM signBlob API with the default service
/// account.
///
/// [data] is the bytes to be signed.
/// [serviceAccountCredentials] can be provided to sign the data locally
/// using RSA-SHA256 if the credentials have a private key.
///
/// [endpoint] is an optional custom IAM Credentials API endpoint. This is
/// useful when working with different universe domains. If not provided,
Expand All @@ -83,28 +80,28 @@ extension AuthClientSigningExtension on AuthClient {
///
/// final client = await clientViaServiceAccount(credentials, scopes);
/// final data = utf8.encode('data to sign');
/// final signature = await client.sign(data);
/// final signature = await client.sign(
/// data,
/// serviceAccountCredentials: credentials,
/// );
/// print('Signature (base64): ${signature.signedBlob}');
/// ```
Future<String> sign(List<int> data, {String? endpoint}) async {
Future<String> sign(
List<int> data, {
ServiceAccountCredentials? serviceAccountCredentials,
String? endpoint,
}) async {
// Check if this is an impersonated client
if (this is ImpersonatedAuthClient) {
final impersonated = this as ImpersonatedAuthClient;
return (await impersonated.sign(data)).signedBlob;
}

// Check if we have service account credentials for local signing
final serviceAccountCreds = serviceAccountCredentials;

if (serviceAccountCreds != null) {
if (serviceAccountCredentials != null) {
// Use local signing with service account credentials
return base64Encode(serviceAccountCreds.sign(data));
return base64Encode(serviceAccountCredentials.sign(data));
}

// If we're NOT using local signing, use IAM API signing
final universeDomain =
serviceAccountCreds?.universeDomain ?? defaultUniverseDomain;
endpoint ??= 'https://iamcredentials.$universeDomain';
return (await IAMSigner(this, endpoint: endpoint).sign(data)).signedBlob;
return (await signBlob(this, data, endpoint: endpoint)).signedBlob;
}
}
6 changes: 0 additions & 6 deletions googleapis_auth/lib/src/auth_http_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ class AuthenticatedClient extends DelegatingClient implements AuthClient {
super.closeUnderlyingClient = false,
});

@override
ServiceAccountCredentials? get serviceAccountCredentials => null;

@override
Future<StreamedResponse> send(BaseRequest request) async {
// Make new request object and perform the authenticated request.
Expand Down Expand Up @@ -113,9 +110,6 @@ class AutoRefreshingClient extends AutoRefreshDelegatingClient {
);
}

@override
ServiceAccountCredentials? get serviceAccountCredentials => null;

@override
Future<StreamedResponse> send(BaseRequest request) async {
if (!credentials.accessToken.hasExpired) {
Expand Down
Loading
Loading