Add smart signing extension method to AuthClient
# Add smart signing extension method to AuthClient
## Description
### Problem
Once Issues #154-158 are implemented, `googleapis_auth` will have all the primitives needed for signing (local signing, IAM signing, impersonation, credential association, universe domain). However, users would need to manually write logic to choose between these signing methods based on the authentication scenario.
This creates a poor developer experience compared to other Google auth libraries (e.g., Node.js `google-auth-library`) which provide a single `sign()` method that automatically chooses the right signing strategy.
### Proposed Solution
Add a `sign()` extension method on `AuthClient` that intelligently chooses the signing method:
```dart
extension AuthClientSigningExtension on AuthClient {
/// Signs data using the appropriate method based on the auth client type.
///
/// Signing behavior:
/// - [ImpersonatedAuthClient]: Uses IAM signBlob with target principal
/// - Auth clients with service account credentials: Signs locally with RSA-SHA256
/// - Other auth clients (ADC on GCE/Cloud Run): Uses IAM signBlob with default service account
///
/// [data] is the bytes to be signed.
/// [endpoint] is an optional custom IAM Credentials API endpoint for universe domain support.
///
/// Returns the signature as a list of bytes.
Future<List<int>> sign(List<int> data, {String? endpoint}) async {
// 1. Check if impersonated client
if (this is ImpersonatedAuthClient) {
final impersonated = this as ImpersonatedAuthClient;
return impersonated.sign(data);
}
// 2. Check for local signing capability (requires #154)
final serviceAccountCreds = // ... get credentials via #154
if (serviceAccountCreds != null) {
// Use local signing (#156)
return serviceAccountCreds.sign(data);
}
// 3. Fall back to IAM signing (#157)
// Determine endpoint from universe domain (#155)
final universeDomain = // ... from credentials or default
endpoint ??= 'https://iamcredentials.$universeDomain';
final signer = IAMSigner(
this,
serviceAccountEmail: await _getServiceAccountEmail(),
endpoint: endpoint,
);
return signer.sign(data);
}
}
```
### Use Case
Provides a seamless signing API that works across all authentication scenarios:
```dart
// Works with service account key file
final creds = ServiceAccountCredentials.fromJson(json);
final client = await clientViaServiceAccount(creds, scopes);
final signature = await client.sign(dataToSign);
// Works with ADC on GCE/Cloud Run
final client = await clientViaApplicationDefaultCredentials(scopes: scopes);
final signature = await client.sign(dataToSign);
// Works with impersonated credentials
final impersonatedClient = ImpersonatedAuthClient(
sourceClient: sourceClient,
targetPrincipal: 'target@project.iam.gserviceaccount.com',
);
final signature = await impersonatedClient.sign(dataToSign);
```
Users don't need to know or care about the authentication method - signing "just works".
### Dependencies
This issue **depends on all previous issues**:
- **#156** (Public Signing API): For local signing with service account credentials
- **#157** (IAM signBlob API): For remote signing via IAM API
- **#158** (ImpersonatedAuthClient): For impersonated signing
- **#155** (universeDomain and projectId fields): For correct IAM endpoint construction
- **#154** (Credential-Client Association): To determine which signing method to use
### Implementation Order
This should be implemented **last**, after all dependencies are complete.
### References
- Node.js equivalent: [GoogleAuth.sign() method](https://github.com/googleapis/google-cloud-node-core/blob/main/packages/google-auth-library-nodejs/src/auth/googleauth.ts#L1272-L1310) - intelligently chooses between local signing (JWT), IAM signBlob, or impersonated signing
- Related to replacing `googleapis_auth_utils` functionality
- This is the final piece that makes `googleapis_auth_utils` obsolete
0 条评论