Add ImpersonatedAuthClient for service account impersonation
# Add ImpersonatedAuthClient for service account impersonation
## Description
### Problem
Service account impersonation allows one set of credentials to act as a different service account via the [IAM Credentials API](https://cloud.google.com/iam/docs/reference/credentials/rest). This is useful for:
- Temporary elevation of privileges
- Testing with different service accounts
- Cross-project operations
- Workload identity federation scenarios
Currently, `googleapis_auth` has no built-in support for service account impersonation.
### Proposed Solution
Add `ImpersonatedAuthClient` that wraps a source client and impersonates a target service account:
```dart
class ImpersonatedAuthClient implements AuthClient {
ImpersonatedAuthClient({
required AuthClient sourceClient,
required String targetPrincipal,
List<String> targetScopes = const [],
List<String> delegates = const [],
int lifetime = 3600,
String? endpoint,
});
/// Signs data as the target principal via IAM signBlob.
Future<SignBlobResponse> sign(String blobToSign);
/// Generates an access token for the target principal via IAM generateAccessToken.
Future<AccessToken> generateAccessToken();
// ... standard AuthClient methods ...
}
```
### Implementation Details
The implementation should:
1. Use the source client to authenticate IAM API requests
2. Call `projects/-/serviceAccounts/{targetPrincipal}:generateAccessToken` for tokens
3. Call `projects/-/serviceAccounts/{targetPrincipal}:signBlob` for signing
4. Support `delegates` for impersonation chains
5. Support custom endpoints for universe domain (#155)
6. Cache access tokens until expiry
### Use Case
This enables complex authentication scenarios:
```dart
// Impersonate a service account
final impersonatedClient = ImpersonatedAuthClient(
sourceClient: await clientViaApplicationDefaultCredentials(scopes: [...]),
targetPrincipal: 'target-sa@project.iam.gserviceaccount.com',
targetScopes: ['https://www.googleapis.com/auth/cloud-platform'],
);
// Use impersonated client for API calls
final response = await impersonatedClient.get(someUri);
// Sign data as the impersonated account
final signature = await impersonatedClient.sign('data to sign');
```
### Dependencies
- **Depends on #157** (IAM signBlob API): Reuses IAM signing implementation
- **Depends on #155** (universeDomain and projectId fields): To construct correct IAM endpoints
### Related Issues
- **Used by #159** (Smart Signing Extension): The smart signing extension should detect and handle `ImpersonatedAuthClient`
### References
- [IAM Credentials API generateAccessToken](https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/generateAccessToken)
- [IAM Credentials API signBlob](https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob)
- [Service Account Impersonation documentation](https://cloud.google.com/iam/docs/impersonating-service-accounts)
- Node.js equivalent: [Impersonated class](https://github.com/googleapis/google-cloud-node-core/blob/main/packages/google-auth-library-nodejs/src/auth/impersonated.ts) - see [sign() method](https://github.com/googleapis/google-cloud-node-core/blob/main/packages/google-auth-library-nodejs/src/auth/impersonated.ts#L161-L176) and [refreshToken()](https://github.com/googleapis/google-cloud-node-core/blob/main/packages/google-auth-library-nodejs/src/auth/impersonated.ts#L186-L217)
- Related to replacing `googleapis_auth_utils` functionality
0 条评论