diff --git a/Src/Support/Google.Apis.Auth.Tests/OAuth2/GoogleCredentialTests.cs b/Src/Support/Google.Apis.Auth.Tests/OAuth2/GoogleCredentialTests.cs index e692b45dd42..849190456e8 100644 --- a/Src/Support/Google.Apis.Auth.Tests/OAuth2/GoogleCredentialTests.cs +++ b/Src/Support/Google.Apis.Auth.Tests/OAuth2/GoogleCredentialTests.cs @@ -272,6 +272,16 @@ public void FromStream_UserCredential() Assert.Equal("CLIENT_SECRET", flow.ClientSecrets.ClientSecret); Assert.Equal("PROJECT_ID", flow.ProjectId); Assert.Equal("QUOTA_PROJECT", userCred.QuotaProject); + Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, (userCred as IGoogleCredential).GetUniverseDomain()); + } + + [Fact] + public void CreateWithUniverseDomain_UserCredential_Fails() + { + var stream = new MemoryStream(Encoding.UTF8.GetBytes(FakeUserCredentialFileContents)); + var credential = GoogleCredential.FromStream(stream); + + Assert.Throws(() => credential.CreateWithUniverseDomain("fake.universe.domain.com")); } [Fact] @@ -284,6 +294,24 @@ public void FromStream_ServiceAccountCredential() var serviceCred = (ServiceAccountCredential)credential.UnderlyingCredential; Assert.Equal("CLIENT_EMAIL", serviceCred.Id); Assert.Equal("PROJECT_ID", serviceCred.ProjectId); + Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain()); + } + + [Fact] + public void CreateWithUniverseDomain_ServiceAccountCredential() + { + var universeDomain = "fake.universe.domain.com"; + var stream = new MemoryStream(Encoding.UTF8.GetBytes(FakeServiceAccountCredentialFileContents)); + var credential = GoogleCredential.FromServiceAccountCredential( + ServiceAccountCredential.FromServiceAccountData(stream).WithUseJwtAccessWithScopes(true)); + + var newCredential = credential.CreateWithUniverseDomain(universeDomain); + + Assert.NotSame(credential, newCredential); + Assert.IsType(newCredential.UnderlyingCredential); + + Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain()); + Assert.Equal(universeDomain, newCredential.GetUniverseDomain()); } [Fact] diff --git a/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs index 1f2fec3d87d..4595391c954 100644 --- a/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs +++ b/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs @@ -267,6 +267,37 @@ public static GoogleCredential FromComputeCredential(ComputeCredential computeCr /// public ICredential UnderlyingCredential => credential; + /// + /// Returns the universe domain this credential belongs to. + /// + /// + /// For most credential types, this operation is synchronous and will always + /// return a completed task. + /// For , the universe domain is obtained from the + /// metadata server, which requires an HTTP call. This value is obtained only once, + /// the first time it is requested for any instance of . + /// After that, this method will always return a completed task. + /// The task's result will never be null. + /// + public Task GetUniverseDomainAsync(CancellationToken cancellationToken) => + credential.GetUniverseDomainAsync(cancellationToken); + + /// + /// Returns the universe domain this credential belongs to. + /// + /// + /// Because is truly async only once, at most, in the lifetime + /// of an application, this method exists for convenience. + /// It can always be safely used for all credential types except for . + /// For , the universe domain is obtained from the + /// metadata server, which requires an HTTP call. This value is obtained only once, + /// the first time it is requested for any instance of . + /// That first time, this method may block while waiting for the HTTP call to complete. + /// After that, this method will always be safe to use. + /// Will never return null. + /// + public string GetUniverseDomain() => credential.GetUniverseDomain(); + /// /// If this library supports setting explicit scopes on this credential, /// this method will creates a copy of the credential with the specified scopes. @@ -332,6 +363,16 @@ GoogleAuthConsts.EnvironmentQuotaProject is string environmentQuotaProject public virtual GoogleCredential CreateWithHttpClientFactory(IHttpClientFactory factory) => new GoogleCredential(credential.WithHttpClientFactory(factory)); + /// + /// If the credential supports custom universe domains this method will create a copy of the + /// credential with the specified universe domain set. + /// Otherwise, it throws . + /// + /// The universe domain to use for the credential. + /// May be null, in which case the default universe domain will be used. + public GoogleCredential CreateWithUniverseDomain(string universeDomain) => + new GoogleCredential(credential.WithUniverseDomain(universeDomain)); + void IConfigurableHttpClientInitializer.Initialize(ConfigurableHttpClient httpClient) { credential.Initialize(httpClient);