diff --git a/java/google/registry/config/CredentialModule.java b/java/google/registry/config/CredentialModule.java
index 4061fd1b6..b6ba7fa52 100644
--- a/java/google/registry/config/CredentialModule.java
+++ b/java/google/registry/config/CredentialModule.java
@@ -79,6 +79,29 @@ public abstract class CredentialModule {
return credential;
}
+ /**
+ * Provides a {@link GoogleCredential} with delegated admin access for a G Suite domain.
+ *
+ *
The G Suite domain must grant delegated admin access to the registry service account with
+ * all scopes in {@code requiredScopes}, including ones not related to G Suite.
+ */
+ @DelegatedCredential
+ @Provides
+ @Singleton
+ public static GoogleCredential provideDelegatedCredential(
+ @Config("credentialOauthScopes") ImmutableList requiredScopes,
+ @JsonCredential GoogleCredential googleCredential,
+ @Config("gSuiteAdminAccountEmailAddress") String gSuiteAdminAccountEmailAddress) {
+ return new GoogleCredential.Builder()
+ .setTransport(Utils.getDefaultTransport())
+ .setJsonFactory(Utils.getDefaultJsonFactory())
+ .setServiceAccountId(googleCredential.getServiceAccountId())
+ .setServiceAccountPrivateKey(googleCredential.getServiceAccountPrivateKey())
+ .setServiceAccountScopes(requiredScopes)
+ .setServiceAccountUser(gSuiteAdminAccountEmailAddress)
+ .build();
+ }
+
/** Dagger qualifier for the Application Default Credential. */
@Qualifier
public @interface DefaultCredential {}
diff --git a/java/google/registry/config/files/default-config.yaml b/java/google/registry/config/files/default-config.yaml
index 3ba24741e..2ff11252b 100644
--- a/java/google/registry/config/files/default-config.yaml
+++ b/java/google/registry/config/files/default-config.yaml
@@ -185,10 +185,7 @@ credentialOAuth:
- https://www.googleapis.com/auth/drive
# View and manage groups on your domain in Directory API.
- https://www.googleapis.com/auth/admin.directory.group
- # Inherited from current code.
- # TODO(weiminyu): verify if the scope above is sufficient by itself.
- - https://www.googleapis.com/auth/admin.directory.group.member
- # View and manage the settings of a Google Apps Group.
+ # View and manage group settings in Group Settings API.
- https://www.googleapis.com/auth/apps.groups.settings
icannReporting:
diff --git a/java/google/registry/groups/DirectoryModule.java b/java/google/registry/groups/DirectoryModule.java
index 700efc48e..e5fe05f6c 100644
--- a/java/google/registry/groups/DirectoryModule.java
+++ b/java/google/registry/groups/DirectoryModule.java
@@ -16,12 +16,10 @@ package google.registry.groups;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.admin.directory.Directory;
-import com.google.api.services.admin.directory.DirectoryScopes;
-import com.google.common.collect.ImmutableSet;
import dagger.Module;
import dagger.Provides;
+import google.registry.config.CredentialModule.DelegatedCredential;
import google.registry.config.RegistryConfig.Config;
-import javax.inject.Named;
/** Dagger module for the Google {@link Directory} service. */
@Module
@@ -29,15 +27,8 @@ public final class DirectoryModule {
@Provides
static Directory provideDirectory(
- @Named("delegatedAdmin") GoogleCredential credential,
- @Config("projectId") String projectId) {
- return new Directory.Builder(
- credential.getTransport(),
- credential.getJsonFactory(),
- credential.createScoped(
- ImmutableSet.of(
- DirectoryScopes.ADMIN_DIRECTORY_GROUP_MEMBER,
- DirectoryScopes.ADMIN_DIRECTORY_GROUP)))
+ @DelegatedCredential GoogleCredential credential, @Config("projectId") String projectId) {
+ return new Directory.Builder(credential.getTransport(), credential.getJsonFactory(), credential)
.setApplicationName(projectId)
.build();
}
diff --git a/java/google/registry/groups/GroupssettingsModule.java b/java/google/registry/groups/GroupssettingsModule.java
index 7fe3ac481..23621e58c 100644
--- a/java/google/registry/groups/GroupssettingsModule.java
+++ b/java/google/registry/groups/GroupssettingsModule.java
@@ -16,12 +16,10 @@ package google.registry.groups;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.groupssettings.Groupssettings;
-import com.google.api.services.groupssettings.GroupssettingsScopes;
-import com.google.common.collect.ImmutableSet;
import dagger.Module;
import dagger.Provides;
+import google.registry.config.CredentialModule.DelegatedCredential;
import google.registry.config.RegistryConfig.Config;
-import javax.inject.Named;
/** Dagger module for the Google {@link Groupssettings} service. */
@Module
@@ -29,12 +27,9 @@ public final class GroupssettingsModule {
@Provides
static Groupssettings provideDirectory(
- @Named("delegatedAdmin") GoogleCredential credential,
- @Config("projectId") String projectId) {
+ @DelegatedCredential GoogleCredential credential, @Config("projectId") String projectId) {
return new Groupssettings.Builder(
- credential.getTransport(),
- credential.getJsonFactory(),
- credential.createScoped(ImmutableSet.of(GroupssettingsScopes.APPS_GROUPS_SETTINGS)))
+ credential.getTransport(), credential.getJsonFactory(), credential)
.setApplicationName(projectId)
.build();
}
diff --git a/java/google/registry/request/Modules.java b/java/google/registry/request/Modules.java
index a0fe007c9..5b9cdf0ff 100644
--- a/java/google/registry/request/Modules.java
+++ b/java/google/registry/request/Modules.java
@@ -31,17 +31,14 @@ import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
-import com.google.common.collect.ImmutableSet;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
-import google.registry.config.RegistryConfig.Config;
import google.registry.keyring.api.KeyModule.Key;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Set;
import java.util.function.Function;
-import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
@@ -206,35 +203,5 @@ public final class Modules {
final Provider googleCredentialProvider) {
return scopes -> googleCredentialProvider.get().createScoped(scopes);
}
-
- /**
- * Provides a GoogleCredential that will connect to GAE using delegated admin access. This is
- * needed for API calls requiring domain admin access to the relevant GAFYD using delegated
- * scopes, e.g. the Directory API and the Groupssettings API.
- *
- * Note that you must call {@link GoogleCredential#createScoped} on the credential provided
- * by this method first before using it, as this does not and cannot set the scopes, and a
- * credential without scopes doesn't actually provide access to do anything.
- */
- @Provides
- @Singleton
- @Named("delegatedAdmin")
- static GoogleCredential provideDelegatedAdminGoogleCredential(
- GoogleCredential googleCredential,
- HttpTransport httpTransport,
- @Config("gSuiteAdminAccountEmailAddress") String gSuiteAdminAccountEmailAddress) {
- return new GoogleCredential.Builder()
- .setTransport(httpTransport)
- .setJsonFactory(googleCredential.getJsonFactory())
- .setServiceAccountId(googleCredential.getServiceAccountId())
- .setServiceAccountPrivateKey(googleCredential.getServiceAccountPrivateKey())
- // Set the scopes to empty because the default value is null, which throws an NPE in the
- // GoogleCredential constructor. We don't yet know the actual scopes to use here, and it
- // is thus the responsibility of every user of a delegated admin credential to call
- // createScoped() on it first to get the version with the correct scopes set.
- .setServiceAccountScopes(ImmutableSet.of())
- .setServiceAccountUser(gSuiteAdminAccountEmailAddress)
- .build();
- }
}
}