Skip to content

Commit 589197d

Browse files
feat: Support scopes from JSON for Impersonated Credentials
When using an impersonated service account, scopes specified in the JSON file were previously ignored. This change updates the `CredentialFactory` to read the `scopes` array from the impersonated credential configuration. Programmatically set scopes via `CreateScoped` will continue to take precedence over the scopes defined in the JSON file.
1 parent 476c673 commit 589197d

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

Src/Support/Google.Apis.Auth.Tests/OAuth2/GoogleCredentialTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ public class GoogleCredentialTests
4545
{
4646
private const string QuotaProjectHeaderKey = "x-goog-user-project";
4747
private const string FakeAuthUri = "https://www.googleapis.com/google.some_google_api";
48+
private const string FakeImpersonatedCredentialFileContents = @"{
49+
""service_account_impersonation_url"": ""https://example.com"",
50+
""type"": ""impersonated_service_account"",
51+
""scopes"": [""SCOPE""],
52+
""source_credentials"": {
53+
""client_id"": ""CLIENT_ID"",
54+
""client_secret"": ""CLIENT_SECRET"",
55+
""refresh_token"": ""REFRESH_TOKEN"",
56+
""type"": ""authorized_user""
57+
}}";
4858
private const string FakeUserCredentialFileContents = @"{
4959
""client_id"": ""CLIENT_ID"",
5060
""client_secret"": ""CLIENT_SECRET"",
@@ -697,6 +707,31 @@ public void CreateScoped_Impersonated()
697707
Assert.Collection(impersonatedCredential.Scopes, scope => Assert.Equal("new_scope", scope));
698708
}
699709

710+
[Fact]
711+
public void CreateScoped_Impersonated_FromJson()
712+
{
713+
var impersonatedCredential = CredentialFactory.FromJson<ImpersonatedCredential>(FakeImpersonatedCredentialFileContents);
714+
715+
// The scopes passed in through the credential json should be the scopes set on the impersonated credential
716+
Assert.Equal(["SCOPE"], impersonatedCredential.Scopes);
717+
}
718+
719+
[Fact]
720+
public void CreateScoped_Impersonated_FromJsonScopesOverwritten()
721+
{
722+
var manuallySetScopes = new[] { "manuallySetScope" };
723+
724+
var credentialFromJson = CredentialFactory.FromJson<ImpersonatedCredential>(FakeImpersonatedCredentialFileContents).ToGoogleCredential();
725+
var manuallyScopedCredential = credentialFromJson.CreateScoped(manuallySetScopes);
726+
var originalImpersonatedCredential = Assert.IsType<ImpersonatedCredential>(credentialFromJson.UnderlyingCredential);
727+
var newImpersonatedCredential = Assert.IsType<ImpersonatedCredential>(manuallyScopedCredential.UnderlyingCredential);
728+
729+
// If scopes are explicitly set in code, these should override the scopes passed through the credential json
730+
Assert.Equal(manuallySetScopes, newImpersonatedCredential.Scopes);
731+
// The original credential's scopes should remain unchanged
732+
Assert.Equal(["SCOPE"], originalImpersonatedCredential.Scopes);
733+
}
734+
700735
[Fact]
701736
public void CreateWithQuotaProject_Impersonated()
702737
{

Src/Support/Google.Apis.Auth/OAuth2/CredentialFactory.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,9 @@ private static ImpersonatedCredential CreateImpersonatedServiceAccountCredential
334334
var maybeTargetPrincipal = ImpersonatedCredential.ExtractTargetPrincipal(parameters.ServiceAccountImpersonationUrl);
335335
var initializer = new ImpersonatedCredential.Initializer(parameters.ServiceAccountImpersonationUrl, maybeTargetPrincipal)
336336
{
337-
DelegateAccounts = parameters.Delegates?.Length > 0 ? parameters.Delegates.ToList() : null,
337+
DelegateAccounts = parameters.Delegates?.Length > 0 ? parameters.Delegates : null,
338338
QuotaProject = parameters.QuotaProject,
339+
Scopes = parameters.Scopes?.Length > 0 ? parameters.Scopes : null,
339340
};
340341

341342
var impersonatedCredential = ImpersonatedCredential.Create(sourceCredential.ToGoogleCredential(), initializer);

Src/Support/Google.Apis.Auth/OAuth2/JsonCredentialParameters.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ public class JsonCredentialParameters
152152
[JsonProperty("delegates")]
153153
public string[] Delegates { get; set; }
154154

155+
/// <summary>
156+
/// Scopes associated with the impersonated credential.
157+
/// </summary>
158+
[JsonProperty("scopes")]
159+
public string[] Scopes { get; set; }
160+
155161
/// <summary>
156162
/// The source credential associated to the impersonated credential.
157163
/// </summary>

0 commit comments

Comments
 (0)