Skip to content

Commit bdd0b84

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 ea3b49c commit bdd0b84

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,36 @@ public void CreateScoped_Impersonated()
697697
Assert.Collection(impersonatedCredential.Scopes, scope => Assert.Equal("new_scope", scope));
698698
}
699699

700+
[Fact]
701+
public void CreateScoped_Impersonated_FromJson()
702+
{
703+
var scopes = new[] { "scope1", "scope2" };
704+
var parameters = CreateImpersonatedCredentialParameters(scopes);
705+
706+
var impersonatedCredential = CredentialFactory.FromJsonParameters<ImpersonatedCredential>(parameters);
707+
708+
// The scopes passed in through the credential json should be the scopes set on the impersonated credential
709+
Assert.Equal(scopes, impersonatedCredential.Scopes);
710+
}
711+
712+
[Fact]
713+
public void CreateScoped_Impersonated_FromJsonScopesOverwritten()
714+
{
715+
var jsonScopes = new[] { "scope1", "scope2" };
716+
var manuallySetScopes = new[] { "scope3" };
717+
var parameters = CreateImpersonatedCredentialParameters(jsonScopes);
718+
719+
var credentialFromJson = CredentialFactory.FromJsonParameters<ImpersonatedCredential>(parameters).ToGoogleCredential();
720+
var manuallyScopedCredential = credentialFromJson.CreateScoped(manuallySetScopes);
721+
var originalImpersonatedCredential = Assert.IsType<ImpersonatedCredential>(credentialFromJson.UnderlyingCredential);
722+
var newImpersonatedCredential = Assert.IsType<ImpersonatedCredential>(manuallyScopedCredential.UnderlyingCredential);
723+
724+
// If scopes are explicitly set in code, these should override the scopes passed through the credential json
725+
Assert.Equal(manuallySetScopes, newImpersonatedCredential.Scopes);
726+
// The original credential's scopes should remain unchanged
727+
Assert.Equal(jsonScopes, originalImpersonatedCredential.Scopes);
728+
}
729+
700730
[Fact]
701731
public void CreateWithQuotaProject_Impersonated()
702732
{
@@ -846,5 +876,23 @@ public Task RevokeTokenAsync(string userId, string token, CancellationToken task
846876

847877
public bool ShouldForceTokenRetrieval() => throw new NotImplementedException();
848878
}
879+
880+
/// <summary>
881+
/// Creates json parameters for an impersonated credential with the specified scopes.
882+
/// </summary>
883+
private static JsonCredentialParameters CreateImpersonatedCredentialParameters(string[] scopes) =>
884+
new JsonCredentialParameters
885+
{
886+
Type = JsonCredentialParameters.ImpersonatedServiceAccountCredentialType,
887+
ServiceAccountImpersonationUrl = "https://example.com",
888+
Scopes = scopes,
889+
SourceCredential = new JsonCredentialParameters
890+
{
891+
Type = JsonCredentialParameters.AuthorizedUserCredentialType,
892+
ClientId = "CLIENT_ID",
893+
ClientSecret = "CLIENT_SECRET",
894+
RefreshToken = "REFRESH_TOKEN"
895+
}
896+
};
849897
}
850898
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ private static ImpersonatedCredential CreateImpersonatedServiceAccountCredential
336336
{
337337
DelegateAccounts = parameters.Delegates?.Length > 0 ? parameters.Delegates.ToList() : null,
338338
QuotaProject = parameters.QuotaProject,
339+
Scopes = parameters.Scopes?.Length > 0 ? parameters.Scopes.ToList() : 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)