diff --git a/core/src/main/java/google/registry/config/RegistryConfig.java b/core/src/main/java/google/registry/config/RegistryConfig.java
index 355d9373e..c1566592b 100644
--- a/core/src/main/java/google/registry/config/RegistryConfig.java
+++ b/core/src/main/java/google/registry/config/RegistryConfig.java
@@ -1174,44 +1174,6 @@ public final class RegistryConfig {
return CONFIG_SETTINGS.get();
}
- /**
- * Provides the OAuth scopes that authentication logic should detect on access tokens.
- *
- *
This list should be a superset of the required OAuth scope set provided below. Note that
- * ideally, this setting would not be required and all scopes on an access token would be
- * detected automatically, but that is not the case due to the way {@code OAuthService} works.
- *
- *
This is an independent setting from the required OAuth scopes (below) to support use cases
- * where certain actions require some additional scope (e.g. access to a user's Google Drive)
- * but that scope shouldn't be required for authentication alone; in that case the Drive scope
- * would be specified only for this setting, allowing that action to check for its presence.
- */
- @Provides
- @Config("availableOauthScopes")
- public static ImmutableSet provideAvailableOauthScopes(RegistryConfigSettings config) {
- return ImmutableSet.copyOf(config.auth.availableOauthScopes);
- }
-
- /**
- * Provides the OAuth scopes that are required for authenticating successfully.
- *
- * This set contains the scopes which must be present to authenticate a user. It should be a
- * subset of the scopes we request from the OAuth interface, provided above.
- *
- *
If we feel the need, we could define additional fixed scopes, similar to the Java remote
- * API, which requires at least one of:
- *
- *
- * - {@code https://www.googleapis.com/auth/appengine.apis}
- *
- {@code https://www.googleapis.com/auth/cloud-platform}
- *
- */
- @Provides
- @Config("requiredOauthScopes")
- public static ImmutableSet provideRequiredOauthScopes(RegistryConfigSettings config) {
- return ImmutableSet.copyOf(config.auth.requiredOauthScopes);
- }
-
/**
* Provides service account email addresses allowed to authenticate with the app at {@link
* google.registry.request.auth.AuthSettings.AuthLevel#APP} level.
@@ -1223,13 +1185,6 @@ public final class RegistryConfig {
return ImmutableSet.copyOf(config.auth.allowedServiceAccountEmails);
}
- /** Provides the allowed OAuth client IDs (could be multibinding). */
- @Provides
- @Config("allowedOauthClientIds")
- public static ImmutableSet provideAllowedOauthClientIds(RegistryConfigSettings config) {
- return ImmutableSet.copyOf(config.auth.allowedOauthClientIds);
- }
-
@Provides
@Config("oauthClientId")
public static String provideOauthClientId(RegistryConfigSettings config) {
diff --git a/core/src/main/java/google/registry/config/RegistryConfigSettings.java b/core/src/main/java/google/registry/config/RegistryConfigSettings.java
index b9b424c6c..8d62a0a53 100644
--- a/core/src/main/java/google/registry/config/RegistryConfigSettings.java
+++ b/core/src/main/java/google/registry/config/RegistryConfigSettings.java
@@ -58,9 +58,6 @@ public class RegistryConfigSettings {
/** Configuration options for authenticating users. */
public static class Auth {
- public List availableOauthScopes;
- public List requiredOauthScopes;
- public List allowedOauthClientIds;
public List allowedServiceAccountEmails;
public String oauthClientId;
}
diff --git a/core/src/main/java/google/registry/config/files/default-config.yaml b/core/src/main/java/google/registry/config/files/default-config.yaml
index 1d772f5de..97c403008 100644
--- a/core/src/main/java/google/registry/config/files/default-config.yaml
+++ b/core/src/main/java/google/registry/config/files/default-config.yaml
@@ -304,24 +304,6 @@ caching:
# Note: Only allowedServiceAccountEmails and oauthClientId should be configured.
# Other fields are related to OAuth-based authentication and will be removed.
auth:
- # Deprecated: Use OIDC-based auth instead. This field is for OAuth-based auth.
- # OAuth scopes to detect on access tokens. Superset of requiredOauthScopes.
- availableOauthScopes:
- - https://www.googleapis.com/auth/userinfo.email
-
- # Deprecated: Use OIDC-based auth instead. This field is for OAuth-based auth.
- # OAuth scopes required for authenticating. Subset of availableOauthScopes.
- requiredOauthScopes:
- - https://www.googleapis.com/auth/userinfo.email
-
- # Deprecated: Use OIDC-based auth instead. This field is for OAuth-based auth.
- # OAuth client IDs that are allowed to authenticate and communicate with
- # backend services, e.g. nomulus tool, EPP proxy, etc. The value in
- # registryTool.clientId field should be included in this list. Client IDs are
- # typically of the format
- # numbers-alphanumerics.apps.googleusercontent.com
- allowedOauthClientIds: []
-
# Service accounts (e.g. default service account, account used by Cloud
# Scheduler) allowed to send authenticated requests.
allowedServiceAccountEmails:
diff --git a/core/src/main/java/google/registry/config/files/nomulus-config-production-sample.yaml b/core/src/main/java/google/registry/config/files/nomulus-config-production-sample.yaml
deleted file mode 100644
index 73ca90a1e..000000000
--- a/core/src/main/java/google/registry/config/files/nomulus-config-production-sample.yaml
+++ /dev/null
@@ -1,76 +0,0 @@
-# This is a sample production config (to be deployed in the WEB-INF directory).
-# This is the same as what Google Registry runs in production, except with
-# placeholders for Google-specific settings.
-
-gcpProject:
- projectId: placeholder
- # Set to true if running against local servers (localhost)
- isLocal: false
- # The "-dot-" prefix is used on the project ID in this URL in order
- # to get around an issue with double-wildcard SSL certs.
- defaultServiceUrl: https://domain-registry-placeholder.appspot.com
- backendServiceUrl: https://backend-dot-domain-registry-placeholder.appspot.com
- toolsServiceUrl: https://tools-dot-domain-registry-placeholder.appspot.com
- pubapiServiceUrl: https://pubapi-dot-domain-registry-placeholder.appspot.com
-
-gSuite:
- domainName: placeholder
- outgoingEmailDisplayName: placeholder
- outgoingEmailAddress: placeholder
- adminAccountEmailAddress: placeholder
- supportGroupEmailAddress: placeholder
-
-registryPolicy:
- contactAndHostRoidSuffix: placeholder
- productName: placeholder
- greetingServerId: placeholder
- registrarChangesNotificationEmailAddresses:
- - placeholder
- - placeholder
- defaultRegistrarWhoisServer: placeholder
- tmchCaMode: PRODUCTION
- tmchCrlUrl: http://crl.icann.org/tmch.crl
- tmchMarksDbUrl: https://ry.marksdb.org
- checkApiServletClientId: placeholder
- registryAdminClientId: placeholder
- whoisDisclaimer: |
- multi-line
- placeholder
-
-icannReporting:
- icannTransactionsReportingUploadUrl: https://ry-api.icann.org/report/registrar-transactions
- icannActivityReportingUploadUrl: https://ry-api.icann.org/report/registry-functions-activity
-
-oAuth:
- allowedOauthClientIds:
- - placeholder.apps.googleusercontent.com
- - placeholder-for-proxy
-
-rde:
- reportUrlPrefix: https://ry-api.icann.org/report/registry-escrow-report
- uploadUrl: sftp://placeholder@sftpipm2.ironmountain.com/Outbox
- sshIdentityEmailAddress: placeholder
-
-registrarConsole:
- logoFilename: placeholder
- supportPhoneNumber: placeholder
- supportEmailAddress: placeholder
- announcementsEmailAddress: placeholder
- integrationEmailAddress: placeholder
- technicalDocsUrl: https://drive.google.com/drive/folders/placeholder
-
-misc:
- sheetExportId: placeholder
-
-cloudDns:
- rootUrl: null
- servicePath: null
-
-keyring:
- activeKeyring: KMS
- kms:
- projectId: placeholder
-
-registryTool:
- clientId: placeholder.apps.googleusercontent.com
- clientSecret: placeholder
diff --git a/core/src/main/java/google/registry/flows/EppTlsAction.java b/core/src/main/java/google/registry/flows/EppTlsAction.java
index a1f63cae6..6b34988fa 100644
--- a/core/src/main/java/google/registry/flows/EppTlsAction.java
+++ b/core/src/main/java/google/registry/flows/EppTlsAction.java
@@ -29,7 +29,7 @@ import javax.servlet.http.HttpSession;
service = Action.Service.DEFAULT,
path = "/_dr/epp",
method = Method.POST,
- auth = Auth.AUTH_API_PUBLIC)
+ auth = Auth.AUTH_API_ADMIN)
public class EppTlsAction implements Runnable {
@Inject @Payload byte[] inputXmlBytes;
diff --git a/core/src/main/java/google/registry/request/auth/Auth.java b/core/src/main/java/google/registry/request/auth/Auth.java
index 3acc4d32c..5bd7f25b9 100644
--- a/core/src/main/java/google/registry/request/auth/Auth.java
+++ b/core/src/main/java/google/registry/request/auth/Auth.java
@@ -15,8 +15,6 @@
package google.registry.request.auth;
import com.google.common.collect.ImmutableList;
-import google.registry.flows.EppTlsAction;
-import google.registry.flows.TlsCredentials;
import google.registry.request.auth.AuthSettings.AuthLevel;
import google.registry.request.auth.AuthSettings.AuthMethod;
import google.registry.request.auth.AuthSettings.UserPolicy;
@@ -48,30 +46,18 @@ public enum Auth {
* Allows anyone to access, as long as they are logged in.
*
* This is used by legacy registrar console programmatic endpoints (those that extend {@link
- * JsonGetAction}, which are accessed via XHR requests sent from a logged-in user when performing
+ * JsonGetAction}), which are accessed via XHR requests sent from a logged-in user when performing
* actions on the console.
*/
AUTH_PUBLIC_LOGGED_IN(
ImmutableList.of(AuthMethod.API, AuthMethod.LEGACY), AuthLevel.USER, UserPolicy.PUBLIC),
/**
- * Allows any client to access, as long as they are logged in via API-based authentication
- * mechanisms.
+ * Allows only the app itself (via service accounts) or admins to access.
*
- *
This is used by the proxy to access Nomulus endpoints. The proxy service account does NOT
- * have admin privileges. For EPP, we handle client authentication within {@link EppTlsAction},
- * using {@link TlsCredentials}. For WHOIS, anyone connecting to the proxy can access.
- *
- *
Note that the proxy service account DOES need to be allow-listed in the {@code
- * auth.allowedServiceAccountEmails} field in the config YAML file in order for OIDC-based
- * authentication to pass.
- */
- AUTH_API_PUBLIC(ImmutableList.of(AuthMethod.API), AuthLevel.APP, UserPolicy.PUBLIC),
-
- /**
- * Allows only admins to access.
- *
- *
This applies to the majority of the endpoints.
+ *
This applies to the majority of the endpoints. For APP level authentication to work, the
+ * associated service account needs to be allowlisted in the {@code
+ * auth.allowedServiceAccountEmails} field in the config YAML file.
*/
AUTH_API_ADMIN(ImmutableList.of(AuthMethod.API), AuthLevel.APP, UserPolicy.ADMIN);
diff --git a/core/src/main/java/google/registry/request/auth/AuthModule.java b/core/src/main/java/google/registry/request/auth/AuthModule.java
index b416e5b00..1ac8d8cb7 100644
--- a/core/src/main/java/google/registry/request/auth/AuthModule.java
+++ b/core/src/main/java/google/registry/request/auth/AuthModule.java
@@ -16,8 +16,6 @@ package google.registry.request.auth;
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
-import com.google.appengine.api.oauth.OAuthService;
-import com.google.appengine.api.oauth.OAuthServiceFactory;
import com.google.auth.oauth2.TokenVerifier;
import com.google.common.collect.ImmutableList;
import dagger.Module;
@@ -36,9 +34,6 @@ public class AuthModule {
// IAP-signed JWT will be in this header.
// See https://cloud.google.com/iap/docs/signed-headers-howto#securing_iap_headers.
public static final String IAP_HEADER_NAME = "X-Goog-IAP-JWT-Assertion";
- // GAE will put the content in header "proxy-authorization" in this header when it routes the
- // request to the app.
- public static final String PROXY_HEADER_NAME = "X-Google-Proxy-Authorization";
public static final String BEARER_PREFIX = "Bearer ";
// TODO: Change the IAP audience format once we are on GKE.
// See: https://cloud.google.com/iap/docs/signed-headers-howto#verifying_the_jwt_payload
@@ -46,16 +41,12 @@ public class AuthModule {
private static final String IAP_ISSUER_URL = "https://cloud.google.com/iap";
private static final String REGULAR_ISSUER_URL = "https://accounts.google.com";
- /** Provides the custom authentication mechanisms (including OAuth and OIDC). */
+ /** Provides the custom authentication mechanisms. */
@Provides
ImmutableList provideApiAuthenticationMechanisms(
- OAuthAuthenticationMechanism oauthAuthenticationMechanism,
IapOidcAuthenticationMechanism iapOidcAuthenticationMechanism,
RegularOidcAuthenticationMechanism regularOidcAuthenticationMechanism) {
- return ImmutableList.of(
- oauthAuthenticationMechanism,
- iapOidcAuthenticationMechanism,
- regularOidcAuthenticationMechanism);
+ return ImmutableList.of(iapOidcAuthenticationMechanism, regularOidcAuthenticationMechanism);
}
@Qualifier
@@ -64,12 +55,6 @@ public class AuthModule {
@Qualifier
@interface RegularOidc {}
- /** Provides the OAuthService instance. */
- @Provides
- OAuthService provideOauthService() {
- return OAuthServiceFactory.getOAuthService();
- }
-
@Provides
@IapOidc
@Singleton
@@ -98,11 +83,7 @@ public class AuthModule {
@Singleton
TokenExtractor provideRegularTokenExtractor() {
return request -> {
- // TODO: only check the Authorizaiton header after the migration to OIDC is complete.
- String rawToken = request.getHeader(PROXY_HEADER_NAME);
- if (rawToken == null) {
- rawToken = request.getHeader(AUTHORIZATION);
- }
+ String rawToken = request.getHeader(AUTHORIZATION);
if (rawToken != null && rawToken.startsWith(BEARER_PREFIX)) {
return rawToken.substring(BEARER_PREFIX.length());
}
diff --git a/core/src/main/java/google/registry/request/auth/AuthResult.java b/core/src/main/java/google/registry/request/auth/AuthResult.java
index 1e4432a63..82e64b007 100644
--- a/core/src/main/java/google/registry/request/auth/AuthResult.java
+++ b/core/src/main/java/google/registry/request/auth/AuthResult.java
@@ -14,7 +14,9 @@
package google.registry.request.auth;
-import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkArgument;
+import static google.registry.request.auth.AuthSettings.AuthLevel.APP;
+import static google.registry.request.auth.AuthSettings.AuthLevel.USER;
import com.google.auto.value.AutoValue;
import google.registry.request.auth.AuthSettings.AuthLevel;
@@ -22,8 +24,8 @@ import java.util.Optional;
import javax.annotation.Nullable;
/**
- * Results of authentication for a given HTTP request, as emitted by an
- * {@link AuthenticationMechanism}.
+ * Results of authentication for a given HTTP request, as emitted by an {@link
+ * AuthenticationMechanism}.
*/
@AutoValue
public abstract class AuthResult {
@@ -33,6 +35,10 @@ public abstract class AuthResult {
/** Information about the authenticated user, if there is one. */
public abstract Optional userAuthInfo();
+ /** Service account email of the authenticated app, if there is one. */
+ @SuppressWarnings("unused") // The service account will be logged upon successful login.
+ public abstract Optional appServiceAccount();
+
public boolean isAuthenticated() {
return authLevel() != AuthLevel.NONE;
}
@@ -47,15 +53,27 @@ public abstract class AuthResult {
.orElse("");
}
- public static AuthResult create(AuthLevel authLevel) {
- return new AutoValue_AuthResult(authLevel, Optional.empty());
+ public static AuthResult createApp(String email) {
+ return create(APP, null, email);
}
- public static AuthResult create(AuthLevel authLevel, @Nullable UserAuthInfo userAuthInfo) {
- if (authLevel == AuthLevel.USER) {
- checkNotNull(userAuthInfo);
- }
- return new AutoValue_AuthResult(authLevel, Optional.ofNullable(userAuthInfo));
+ public static AuthResult createUser(UserAuthInfo userAuthInfo) {
+ return create(USER, userAuthInfo, null);
+ }
+
+ private static AuthResult create(
+ AuthLevel authLevel, @Nullable UserAuthInfo userAuthInfo, @Nullable String email) {
+ checkArgument(
+ userAuthInfo == null || email == null,
+ "User auth info and service account email cannot be specificed at the same time");
+ checkArgument(
+ authLevel != USER || userAuthInfo != null,
+ "User auth info must be specified for auth level USER");
+ checkArgument(
+ authLevel != APP || email != null,
+ "Service account email must be specified for auth level APP");
+ return new AutoValue_AuthResult(
+ authLevel, Optional.ofNullable(userAuthInfo), Optional.ofNullable(email));
}
/**
@@ -67,5 +85,5 @@ public abstract class AuthResult {
* returns NOT_AUTHENTICATED in this case, as opposed to absent() if authentication failed and was
* required. So as a return from an authorization check, this can be treated as a success.
*/
- public static final AuthResult NOT_AUTHENTICATED = create(AuthLevel.NONE);
+ public static final AuthResult NOT_AUTHENTICATED = create(AuthLevel.NONE, null, null);
}
diff --git a/core/src/main/java/google/registry/request/auth/AuthSettings.java b/core/src/main/java/google/registry/request/auth/AuthSettings.java
index 5448ae8c0..b685f818b 100644
--- a/core/src/main/java/google/registry/request/auth/AuthSettings.java
+++ b/core/src/main/java/google/registry/request/auth/AuthSettings.java
@@ -17,6 +17,7 @@ package google.registry.request.auth;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;
+import google.registry.model.console.UserRoles;
/**
* Parameters used to configure the authenticator.
@@ -42,7 +43,10 @@ public abstract class AuthSettings {
/** Available methods for authentication. */
public enum AuthMethod {
- /** Authentication methods suitable for API-style access, such as OAuth 2. */
+ /**
+ * Authentication methods suitable for API-style access, such as {@link
+ * OidcTokenAuthenticationMechanism}.
+ */
API,
/** Legacy authentication using cookie-based App Engine Users API. Must come last if present. */
@@ -68,10 +72,11 @@ public abstract class AuthSettings {
/**
* Authentication required, but user not required.
*
- * In Auth: Authentication is required, but app-internal authentication (which isn't
- * associated with a specific user) is permitted.
+ *
In Auth: authentication is required, but App-internal authentication (which isn't
+ * associated with a specific user, but a service account) is permitted. Examples include
+ * requests from Cloud Tasks, Cloud Scheduler, and the proxy.
*
- *
In AuthResult: App-internal authentication was successful.
+ *
In AuthResult: App-internal authentication (via service accounts) was successful.
*/
APP,
@@ -93,10 +98,14 @@ public abstract class AuthSettings {
PUBLIC,
/**
- * If there is a user, it must be an admin, as determined by isUserAdmin().
+ * If there is a user, it must be an admin, as determined by {@link UserAuthInfo#isUserAdmin()}.
*
- *
Note that, according to App Engine, anybody with access to the app in the GCP Console,
+ *
Note that, if the user returned is an App Engine {@link
+ * com.google.appengine.api.users.User} , anybody with access to the app in the GCP Console,
* including editors and viewers, is an admin.
+ *
+ *
On the other hand, if the user is a {@link google.registry.model.console.User}, the admin
+ * role is explicitly defined in that object via the {@link UserRoles#isAdmin()} method.
*/
ADMIN
}
diff --git a/core/src/main/java/google/registry/request/auth/AuthenticationMechanism.java b/core/src/main/java/google/registry/request/auth/AuthenticationMechanism.java
index 8427c102e..db30f77b0 100644
--- a/core/src/main/java/google/registry/request/auth/AuthenticationMechanism.java
+++ b/core/src/main/java/google/registry/request/auth/AuthenticationMechanism.java
@@ -19,7 +19,7 @@ import javax.servlet.http.HttpServletRequest;
/**
* A particular way to authenticate an HTTP request, returning an {@link AuthResult}.
*
- *
For instance, a request could be authenticated using OAuth, via special request headers, etc.
+ *
For instance, a request could be authenticated using OIDC, via special request headers, etc.
*/
public interface AuthenticationMechanism {
diff --git a/core/src/main/java/google/registry/request/auth/LegacyAuthenticationMechanism.java b/core/src/main/java/google/registry/request/auth/LegacyAuthenticationMechanism.java
index b7fc660b7..3e2e9ee32 100644
--- a/core/src/main/java/google/registry/request/auth/LegacyAuthenticationMechanism.java
+++ b/core/src/main/java/google/registry/request/auth/LegacyAuthenticationMechanism.java
@@ -16,8 +16,7 @@ package google.registry.request.auth;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.nullToEmpty;
-import static google.registry.request.auth.AuthSettings.AuthLevel.NONE;
-import static google.registry.request.auth.AuthSettings.AuthLevel.USER;
+import static google.registry.request.auth.AuthResult.NOT_AUTHENTICATED;
import static google.registry.security.XsrfTokenManager.P_CSRF_TOKEN;
import static google.registry.security.XsrfTokenManager.X_CSRF_TOKEN;
@@ -49,15 +48,14 @@ public class LegacyAuthenticationMechanism implements AuthenticationMechanism {
@Override
public AuthResult authenticate(HttpServletRequest request) {
if (!userService.isUserLoggedIn()) {
- return AuthResult.create(NONE);
+ return NOT_AUTHENTICATED;
}
if (!SAFE_METHODS.contains(request.getMethod()) && !validateXsrf(request)) {
- return AuthResult.create(NONE);
+ return NOT_AUTHENTICATED;
}
- return AuthResult.create(
- USER,
+ return AuthResult.createUser(
UserAuthInfo.create(userService.getCurrentUser(), userService.isUserAdmin()));
}
diff --git a/core/src/main/java/google/registry/request/auth/OAuthAuthenticationMechanism.java b/core/src/main/java/google/registry/request/auth/OAuthAuthenticationMechanism.java
deleted file mode 100644
index 085466f16..000000000
--- a/core/src/main/java/google/registry/request/auth/OAuthAuthenticationMechanism.java
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2017 The Nomulus Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package google.registry.request.auth;
-
-import static com.google.common.net.HttpHeaders.AUTHORIZATION;
-import static google.registry.request.auth.AuthModule.BEARER_PREFIX;
-import static google.registry.request.auth.AuthSettings.AuthLevel.NONE;
-import static google.registry.request.auth.AuthSettings.AuthLevel.USER;
-
-import com.google.appengine.api.oauth.OAuthRequestException;
-import com.google.appengine.api.oauth.OAuthService;
-import com.google.appengine.api.oauth.OAuthServiceFailureException;
-import com.google.appengine.api.users.User;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.flogger.FluentLogger;
-import google.registry.config.RegistryConfig.Config;
-import google.registry.config.RegistryEnvironment;
-import javax.inject.Inject;
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * OAuth authentication mechanism, using the OAuthService interface.
- *
- *
Only OAuth version 2 is supported.
- */
-public class OAuthAuthenticationMechanism implements AuthenticationMechanism {
-
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final OAuthService oauthService;
-
- /** The available OAuth scopes for which {@link OAuthService} should check. */
- private final ImmutableSet availableOauthScopes;
-
- /** The OAuth scopes which must all be present for authentication to succeed. */
- private final ImmutableSet requiredOauthScopes;
-
- private final ImmutableSet allowedOauthClientIds;
-
- @Inject
- public OAuthAuthenticationMechanism(
- OAuthService oauthService,
- @Config("availableOauthScopes") ImmutableSet availableOauthScopes,
- @Config("requiredOauthScopes") ImmutableSet requiredOauthScopes,
- @Config("allowedOauthClientIds") ImmutableSet allowedOauthClientIds) {
- this.oauthService = oauthService;
- this.availableOauthScopes = availableOauthScopes;
- this.requiredOauthScopes = requiredOauthScopes;
- this.allowedOauthClientIds = allowedOauthClientIds;
- }
-
- @Override
- public AuthResult authenticate(HttpServletRequest request) {
-
- // Make sure that there is an Authorization header in Bearer form. OAuthService also accepts
- // tokens in the request body and URL string, but we should not use those, since they are more
- // likely to be logged than the Authorization header. Checking to make sure there's a token also
- // avoids unnecessary RPCs, since OAuthService itself does not check whether the header is
- // present. In theory, there could be more than one Authorization header, but we only check the
- // first one, because there's not a legitimate use case for having more than one, and
- // OAuthService itself only looks at the first one anyway.
- String header = request.getHeader(AUTHORIZATION);
- if ((header == null) || !header.startsWith(BEARER_PREFIX)) {
- if (header != null) {
- logger.atInfo().log("Invalid authorization header.");
- }
- return AuthResult.create(NONE);
- }
- // Assume that, if a bearer token is found, it's what OAuthService will use to attempt
- // authentication. This is not technically guaranteed by the contract of OAuthService; see
- // OAuthTokenInfo for more information.
- String rawAccessToken =
- RegistryEnvironment.get() == RegistryEnvironment.PRODUCTION
- ? "Raw token redacted in prod"
- : header.substring(BEARER_PREFIX.length());
-
- // Get the OAuth information. The various oauthService method calls use a single cached
- // authentication result, so we can call them one by one.
- User currentUser;
- boolean isUserAdmin;
- String oauthClientId;
- ImmutableSet authorizedScopes;
- try {
- String[] availableOauthScopeArray = availableOauthScopes.toArray(new String[0]);
- currentUser = oauthService.getCurrentUser(availableOauthScopeArray);
- isUserAdmin = oauthService.isUserAdmin(availableOauthScopeArray);
- logger.atInfo().log(
- "Current user: %s (%s).", currentUser, isUserAdmin ? "admin" : "not admin");
- oauthClientId = oauthService.getClientId(availableOauthScopeArray);
- logger.atInfo().log("OAuth client ID: %s", oauthClientId);
- authorizedScopes =
- ImmutableSet.copyOf(oauthService.getAuthorizedScopes(availableOauthScopeArray));
- logger.atInfo().log("Authorized scope(s): %s", authorizedScopes);
- } catch (OAuthRequestException | OAuthServiceFailureException e) {
- logger.atInfo().withCause(e).log("Unable to get OAuth information.");
- return AuthResult.create(NONE);
- }
- if ((currentUser == null) || (oauthClientId == null) || (authorizedScopes == null)) {
- return AuthResult.create(NONE);
- }
-
- // Make sure that the client ID matches, to avoid a confused deputy attack; see:
- // http://stackoverflow.com/a/17439317/1179226
- if (!allowedOauthClientIds.contains(oauthClientId)) {
- logger.atInfo().log("OAuth client ID is not allowed.");
- return AuthResult.create(NONE);
- }
-
- // Make sure that all required scopes are present.
- if (!authorizedScopes.containsAll(requiredOauthScopes)) {
- logger.atInfo().log("Missing required scope(s).");
- return AuthResult.create(NONE);
- }
-
- // Create the {@link AuthResult}, including the OAuth token info.
- return AuthResult.create(
- USER,
- UserAuthInfo.create(
- currentUser,
- isUserAdmin,
- OAuthTokenInfo.create(
- ImmutableSet.copyOf(authorizedScopes), oauthClientId, rawAccessToken)));
- }
-}
diff --git a/core/src/main/java/google/registry/request/auth/OAuthTokenInfo.java b/core/src/main/java/google/registry/request/auth/OAuthTokenInfo.java
deleted file mode 100644
index 6cb3d3950..000000000
--- a/core/src/main/java/google/registry/request/auth/OAuthTokenInfo.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2017 The Nomulus Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package google.registry.request.auth;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableSet;
-
-/** Information provided by the OAuth authentication mechanism (only) about the session. */
-@AutoValue
-public abstract class OAuthTokenInfo {
-
- /** Authorized OAuth scopes granted by the access token provided with the request. */
- abstract ImmutableSet authorizedScopes();
-
- /** OAuth client ID from the access token provided with the request. */
- abstract String oauthClientId();
-
- /**
- * Raw OAuth access token value provided with the request, for passing along to downstream APIs as
- * appropriate.
- *
- * Note that the request parsing code makes certain assumptions about whether the Authorization
- * header was used as the source of the token. Because OAuthService could theoretically fall back
- * to some other source of authentication, it might be possible for rawAccessToken not to have
- * been the source of OAuth authentication. Looking at the code of OAuthService, that could not
- * currently happen, but if OAuthService were modified in the future so that it tried the bearer
- * token, and then when that failed, fell back to another, successful authentication path, then
- * rawAccessToken might not be valid.
- */
- abstract String rawAccessToken();
-
- static OAuthTokenInfo create(
- ImmutableSet authorizedScopes, String oauthClientId, String rawAccessToken) {
- return new AutoValue_OAuthTokenInfo(authorizedScopes, oauthClientId, rawAccessToken);
- }
-}
diff --git a/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java b/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java
index 9efaa96cc..7a5f31f9b 100644
--- a/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java
+++ b/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java
@@ -14,8 +14,6 @@
package google.registry.request.auth;
-import static google.registry.request.auth.AuthSettings.AuthLevel.APP;
-
import com.google.api.client.json.webtoken.JsonWebSignature;
import com.google.auth.oauth2.TokenVerifier;
import com.google.common.annotations.VisibleForTesting;
@@ -97,12 +95,11 @@ public abstract class OidcTokenAuthenticationMechanism implements Authentication
}
Optional maybeUser = UserDao.loadUser(email);
if (maybeUser.isPresent()) {
- return AuthResult.create(AuthLevel.USER, UserAuthInfo.create(maybeUser.get()));
+ return AuthResult.createUser(UserAuthInfo.create(maybeUser.get()));
}
- // TODO: implement caching so we don't have to look up the database for every request.
logger.atInfo().log("No end user found for email address %s", email);
if (serviceAccountEmails.stream().anyMatch(e -> e.equals(email))) {
- return AuthResult.create(APP);
+ return AuthResult.createApp(email);
}
logger.atInfo().log("No service account found for email address %s", email);
logger.atWarning().log(
@@ -153,15 +150,8 @@ public abstract class OidcTokenAuthenticationMechanism implements Authentication
*
* If the endpoint is not behind IAP, we can try to authenticate the OIDC token supplied in the
* request header directly. Ideally we would like all endpoints to be behind IAP, but being able
- * to authenticate the token directly provides us with the flexibility to do away with OAuth-based
- * {@link OAuthAuthenticationMechanism} that is tied to App Engine runtime without having to turn
- * on IAP, which is an all-or-nothing switch for each GAE service (i.e. no way to turn it on only
- * for certain GAE endpoints).
- *
- *
Note that this mechanism will try to first extract the token under the "proxy-authorization"
- * header, before trying "authorization". This is because currently the GAE OAuth service always
- * uses "authorization", and we would like to provide a way for both auth mechanisms to be working
- * at the same time for the same request.
+ * to authenticate the token directly provides us with some extra flexibility that comes in handy,
+ * at least during the migration to GKE.
*
* @see Bearer Token Usage
*/
diff --git a/core/src/main/java/google/registry/request/auth/RequestAuthenticator.java b/core/src/main/java/google/registry/request/auth/RequestAuthenticator.java
index 10747dd6f..bec01c865 100644
--- a/core/src/main/java/google/registry/request/auth/RequestAuthenticator.java
+++ b/core/src/main/java/google/registry/request/auth/RequestAuthenticator.java
@@ -60,7 +60,8 @@ public class RequestAuthenticator {
if (auth.minimumLevel() == APP && !authResult.isAuthenticated()) {
logger.atWarning().log("Not authorized; no authentication found.");
return Optional.empty();
- } else if (auth.minimumLevel() == USER && authResult.authLevel() != USER) {
+ }
+ if (auth.minimumLevel() == USER && authResult.authLevel() != USER) {
logger.atWarning().log("Not authorized; no authenticated user.");
return Optional.empty();
}
@@ -81,12 +82,12 @@ public class RequestAuthenticator {
* @param req the {@link HttpServletRequest}; some authentication mechanisms use HTTP headers
* @return an authentication result; if no authentication was made, returns NOT_AUTHENTICATED
*/
- private AuthResult authenticate(AuthSettings auth, HttpServletRequest req) {
+ AuthResult authenticate(AuthSettings auth, HttpServletRequest req) {
checkAuthConfig(auth);
for (AuthMethod authMethod : auth.methods()) {
AuthResult authResult;
switch (authMethod) {
- // API-based user authentication mechanisms, such as OAuth and OIDC.
+ // API-based user authentication mechanisms, such as OIDC.
case API:
for (AuthenticationMechanism authMechanism : apiAuthenticationMechanisms) {
authResult = authMechanism.authenticate(req);
@@ -113,10 +114,9 @@ public class RequestAuthenticator {
/** Validates an AuthSettings object, checking for invalid setting combinations. */
static void checkAuthConfig(AuthSettings auth) {
- ImmutableList authMethods = ImmutableList.copyOf(auth.methods());
- checkArgument(!authMethods.isEmpty(), "Must specify at least one auth method");
+ checkArgument(!auth.methods().isEmpty(), "Must specify at least one auth method");
checkArgument(
- Ordering.explicit(AuthMethod.API, AuthMethod.LEGACY).isStrictlyOrdered(authMethods),
+ Ordering.explicit(AuthMethod.API, AuthMethod.LEGACY).isStrictlyOrdered(auth.methods()),
"Auth methods must be unique and strictly in order - API, LEGACY");
checkArgument(
(auth.minimumLevel() != NONE) || (auth.userPolicy() != ADMIN),
diff --git a/core/src/main/java/google/registry/request/auth/UserAuthInfo.java b/core/src/main/java/google/registry/request/auth/UserAuthInfo.java
index 54d1fb98c..d92430dde 100644
--- a/core/src/main/java/google/registry/request/auth/UserAuthInfo.java
+++ b/core/src/main/java/google/registry/request/auth/UserAuthInfo.java
@@ -22,6 +22,8 @@ import java.util.Optional;
@AutoValue
public abstract class UserAuthInfo {
+ public abstract Optional consoleUser();
+
/** User object from the AppEngine Users API. */
public abstract Optional appEngineUser();
@@ -34,11 +36,6 @@ public abstract class UserAuthInfo {
*/
public abstract boolean isUserAdmin();
- public abstract Optional consoleUser();
-
- /** Used by the OAuth authentication mechanism (only) to return information about the session. */
- public abstract Optional oauthTokenInfo();
-
public String getEmailAddress() {
return appEngineUser()
.map(User::getEmail)
@@ -51,20 +48,12 @@ public abstract class UserAuthInfo {
.orElseGet(() -> consoleUser().get().getEmailAddress());
}
- public static UserAuthInfo create(
- User user, boolean isUserAdmin) {
- return new AutoValue_UserAuthInfo(
- Optional.of(user), isUserAdmin, Optional.empty(), Optional.empty());
- }
-
- public static UserAuthInfo create(
- User user, boolean isUserAdmin, OAuthTokenInfo oauthTokenInfo) {
- return new AutoValue_UserAuthInfo(
- Optional.of(user), isUserAdmin, Optional.empty(), Optional.of(oauthTokenInfo));
+ public static UserAuthInfo create(User user, boolean isUserAdmin) {
+ return new AutoValue_UserAuthInfo(Optional.empty(), Optional.of(user), isUserAdmin);
}
public static UserAuthInfo create(google.registry.model.console.User user) {
return new AutoValue_UserAuthInfo(
- Optional.empty(), user.getUserRoles().isAdmin(), Optional.of(user), Optional.empty());
+ Optional.of(user), Optional.empty(), user.getUserRoles().isAdmin());
}
}
diff --git a/core/src/main/java/google/registry/tools/RegistryCli.java b/core/src/main/java/google/registry/tools/RegistryCli.java
index 72a2b3819..a5f06d41b 100644
--- a/core/src/main/java/google/registry/tools/RegistryCli.java
+++ b/core/src/main/java/google/registry/tools/RegistryCli.java
@@ -50,13 +50,6 @@ final class RegistryCli implements CommandRunner {
description = "Sets the default environment to run the command.")
private RegistryToolEnvironment environment = RegistryToolEnvironment.PRODUCTION;
- @Parameter(
- names = "--oauth",
- description =
- "Turn on OAuth-based authentication, the usage of which is to be deprecated. Use"
- + " `create_user` to create an Admin user that allows for OIDC-based authentication.")
- private boolean oAuth = false;
-
@Parameter(
names = {"-c", "--commands"},
description = "Returns all command names.")
@@ -168,7 +161,6 @@ final class RegistryCli implements CommandRunner {
DaggerRegistryToolComponent.builder()
.credentialFilePath(credentialJson)
.sqlAccessInfoFile(sqlAccessInfoFile)
- .addOAuthHeader(oAuth)
.build();
// JCommander stores sub-commands as nested JCommander objects containing a list of user objects
diff --git a/core/src/main/java/google/registry/tools/RegistryToolComponent.java b/core/src/main/java/google/registry/tools/RegistryToolComponent.java
index 099c94377..783899b32 100644
--- a/core/src/main/java/google/registry/tools/RegistryToolComponent.java
+++ b/core/src/main/java/google/registry/tools/RegistryToolComponent.java
@@ -191,9 +191,6 @@ interface RegistryToolComponent {
@BindsInstance
Builder sqlAccessInfoFile(@Nullable @Config("sqlAccessInfoFile") String sqlAccessInfoFile);
- @BindsInstance
- Builder addOAuthHeader(@Config("addOauthHeader") boolean addOauthHeader);
-
RegistryToolComponent build();
}
}
diff --git a/core/src/main/java/google/registry/tools/RequestFactoryModule.java b/core/src/main/java/google/registry/tools/RequestFactoryModule.java
index 5f7118553..8b8a69883 100644
--- a/core/src/main/java/google/registry/tools/RequestFactoryModule.java
+++ b/core/src/main/java/google/registry/tools/RequestFactoryModule.java
@@ -14,7 +14,7 @@
package google.registry.tools;
-import static com.google.common.net.HttpHeaders.PROXY_AUTHORIZATION;
+import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.javanet.NetHttpTransport;
@@ -42,8 +42,7 @@ final class RequestFactoryModule {
@Provides
static HttpRequestFactory provideHttpRequestFactory(
@ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
- @Config("oauthClientId") String oauthClientId,
- @Config("addOauthHeader") boolean addOauthHeader) {
+ @Config("oauthClientId") String oauthClientId) {
if (RegistryConfig.areServersLocal()) {
return new NetHttpTransport()
.createRequestFactory(
@@ -55,15 +54,11 @@ final class RequestFactoryModule {
return new NetHttpTransport()
.createRequestFactory(
request -> {
- if (addOauthHeader) {
- // Use the standard credential initializer to set the Authorization header
- credentialsBundle.getHttpRequestInitializer().initialize(request);
- }
- // Set OIDC token as the alternative bearer token.
+ // Set OIDC token as the bearer token.
request
.getHeaders()
.set(
- PROXY_AUTHORIZATION,
+ AUTHORIZATION,
"Bearer "
+ OidcTokenUtils.createOidcToken(credentialsBundle, oauthClientId));
// GAE request times out after 10 min, so here we set the timeout to 10 min. This is
diff --git a/core/src/main/java/google/registry/whois/WhoisAction.java b/core/src/main/java/google/registry/whois/WhoisAction.java
index 81f6d28df..c07421b53 100644
--- a/core/src/main/java/google/registry/whois/WhoisAction.java
+++ b/core/src/main/java/google/registry/whois/WhoisAction.java
@@ -51,7 +51,7 @@ import org.joda.time.DateTime;
service = Action.Service.PUBAPI,
path = "/_dr/whois",
method = POST,
- auth = Auth.AUTH_API_PUBLIC)
+ auth = Auth.AUTH_API_ADMIN)
public class WhoisAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
diff --git a/core/src/test/java/google/registry/rdap/RdapActionBaseTestCase.java b/core/src/test/java/google/registry/rdap/RdapActionBaseTestCase.java
index f8fb34037..e78ae58f7 100644
--- a/core/src/test/java/google/registry/rdap/RdapActionBaseTestCase.java
+++ b/core/src/test/java/google/registry/rdap/RdapActionBaseTestCase.java
@@ -28,7 +28,6 @@ import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.request.Actions;
import google.registry.request.auth.AuthResult;
-import google.registry.request.auth.AuthSettings.AuthLevel;
import google.registry.request.auth.UserAuthInfo;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
@@ -48,13 +47,11 @@ abstract class RdapActionBaseTestCase {
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
protected static final AuthResult AUTH_RESULT =
- AuthResult.create(
- AuthLevel.USER,
+ AuthResult.createUser(
UserAuthInfo.create(new User("rdap.user@user.com", "gmail.com", "12345"), false));
protected static final AuthResult AUTH_RESULT_ADMIN =
- AuthResult.create(
- AuthLevel.USER,
+ AuthResult.createUser(
UserAuthInfo.create(new User("rdap.admin@google.com", "gmail.com", "12345"), true));
protected FakeResponse response = new FakeResponse();
diff --git a/core/src/test/java/google/registry/request/RequestHandlerTest.java b/core/src/test/java/google/registry/request/RequestHandlerTest.java
index 8551e7986..e04ea9e74 100644
--- a/core/src/test/java/google/registry/request/RequestHandlerTest.java
+++ b/core/src/test/java/google/registry/request/RequestHandlerTest.java
@@ -20,6 +20,7 @@ import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.auth.Auth.AUTH_API_ADMIN;
import static google.registry.request.auth.Auth.AUTH_PUBLIC;
+import static google.registry.request.auth.AuthResult.NOT_AUTHENTICATED;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -228,7 +229,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("GET");
when(req.getRequestURI()).thenReturn("/bumblebee");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -242,7 +243,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("POST");
when(req.getRequestURI()).thenReturn("/bumblebee");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -255,7 +256,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("GET");
when(req.getRequestURI()).thenReturn("/bumblebee/hive");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -268,7 +269,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("POST");
when(req.getRequestURI()).thenReturn("/sloth");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -284,7 +285,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("POST");
when(req.getRequestURI()).thenReturn("/sloth/nest");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -296,7 +297,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("GET");
when(req.getRequestURI()).thenReturn("/fail");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -311,7 +312,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("GET");
when(req.getRequestURI()).thenReturn("/failAtConstruction");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -324,7 +325,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("GET");
when(req.getRequestURI()).thenReturn("/bogus");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -336,7 +337,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("POST");
when(req.getRequestURI()).thenReturn("/fail");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -348,7 +349,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("FIREAWAY");
when(req.getRequestURI()).thenReturn("/fail");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -364,7 +365,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("get");
when(req.getRequestURI()).thenReturn("/bumblebee");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -386,7 +387,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("POST");
when(req.getRequestURI()).thenReturn("/safe-sloth");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -399,7 +400,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("GET");
when(req.getRequestURI()).thenReturn("/safe-sloth");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -412,7 +413,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("GET");
when(req.getRequestURI()).thenReturn("/auth/none");
when(requestAuthenticator.authorize(AUTH_PUBLIC.authSettings(), req))
- .thenReturn(Optional.of(AuthResult.create(AuthLevel.NONE)));
+ .thenReturn(Optional.of(NOT_AUTHENTICATED));
handler.handleRequest(req, rsp);
@@ -440,8 +441,7 @@ public final class RequestHandlerTest {
when(req.getMethod()).thenReturn("GET");
when(req.getRequestURI()).thenReturn("/auth/adminUser");
when(requestAuthenticator.authorize(AUTH_API_ADMIN.authSettings(), req))
- .thenReturn(
- Optional.of(AuthResult.create(AuthLevel.USER, UserAuthInfo.create(testUser, true))));
+ .thenReturn(Optional.of(AuthResult.createUser(UserAuthInfo.create(testUser, true))));
handler.handleRequest(req, rsp);
@@ -449,7 +449,6 @@ public final class RequestHandlerTest {
assertThat(providedAuthResult.authLevel()).isEqualTo(AuthLevel.USER);
assertThat(providedAuthResult.userAuthInfo()).isPresent();
assertThat(providedAuthResult.userAuthInfo().get().appEngineUser()).hasValue(testUser);
- assertThat(providedAuthResult.userAuthInfo().get().oauthTokenInfo()).isEmpty();
assertMetric("/auth/adminUser", GET, AuthLevel.USER, true);
}
}
diff --git a/core/src/test/java/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java b/core/src/test/java/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java
index bbb0af9dc..552fc95df 100644
--- a/core/src/test/java/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java
+++ b/core/src/test/java/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java
@@ -15,6 +15,7 @@
package google.registry.request.auth;
import static com.google.common.truth.Truth.assertThat;
+import static google.registry.request.auth.AuthResult.NOT_AUTHENTICATED;
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.ADMIN;
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.OWNER;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
@@ -40,7 +41,6 @@ import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.Registrar.State;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
-import google.registry.request.auth.AuthSettings.AuthLevel;
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
import google.registry.util.JdkLoggerConfig;
import java.util.Optional;
@@ -75,7 +75,7 @@ class AuthenticatedRegistrarAccessorTest {
private static final AuthResult USER = createAuthResult(false);
private static final AuthResult GAE_ADMIN = createAuthResult(true);
- private static final AuthResult NO_USER = AuthResult.create(AuthLevel.NONE);
+ private static final AuthResult NO_USER = NOT_AUTHENTICATED;
private static final Optional SUPPORT_GROUP = Optional.of("support@registry.example");
/** Registrar ID of a REAL registrar with a RegistrarContact for USER and GAE_ADMIN. */
private static final String REGISTRAR_ID_WITH_CONTACT = "TheRegistrar";
@@ -94,8 +94,7 @@ class AuthenticatedRegistrarAccessorTest {
* @param isAdmin if true, the user is an administrator for the app-engine project.
*/
private static AuthResult createAuthResult(boolean isAdmin) {
- return AuthResult.create(
- AuthLevel.USER,
+ return AuthResult.createUser(
UserAuthInfo.create(new User("johndoe@theregistrar.com", "theregistrar.com"), isAdmin));
}
@@ -295,8 +294,7 @@ class AuthenticatedRegistrarAccessorTest {
void testGetRegistrarForUser_inContacts_isNotAdmin_caseInsensitive() throws Exception {
expectGetRegistrarSuccess(
REGISTRAR_ID_WITH_CONTACT,
- AuthResult.create(
- AuthLevel.USER,
+ AuthResult.createUser(
UserAuthInfo.create(new User("JohnDoe@theregistrar.com", "theregistrar.com"), false)),
"user JohnDoe@theregistrar.com has [OWNER] access to registrar TheRegistrar");
verify(lazyGroupsConnection).get();
@@ -421,7 +419,7 @@ class AuthenticatedRegistrarAccessorTest {
.setUserRoles(
new UserRoles.Builder().setIsAdmin(true).setGlobalRole(GlobalRole.FTE).build())
.build();
- AuthResult authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser));
+ AuthResult authResult = AuthResult.createUser(UserAuthInfo.create(consoleUser));
AuthenticatedRegistrarAccessor registrarAccessor =
new AuthenticatedRegistrarAccessor(
authResult, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection);
@@ -446,7 +444,7 @@ class AuthenticatedRegistrarAccessorTest {
.setEmailAddress("email@email.com")
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
.build();
- AuthResult authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser));
+ AuthResult authResult = AuthResult.createUser(UserAuthInfo.create(consoleUser));
AuthenticatedRegistrarAccessor registrarAccessor =
new AuthenticatedRegistrarAccessor(
authResult, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection);
@@ -471,7 +469,7 @@ class AuthenticatedRegistrarAccessorTest {
RegistrarRole.ACCOUNT_MANAGER))
.build())
.build();
- AuthResult authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser));
+ AuthResult authResult = AuthResult.createUser(UserAuthInfo.create(consoleUser));
AuthenticatedRegistrarAccessor registrarAccessor =
new AuthenticatedRegistrarAccessor(
authResult, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection);
diff --git a/core/src/test/java/google/registry/request/auth/OidcTokenAuthenticationMechanismTest.java b/core/src/test/java/google/registry/request/auth/OidcTokenAuthenticationMechanismTest.java
index 2f57a9723..3a53cf595 100644
--- a/core/src/test/java/google/registry/request/auth/OidcTokenAuthenticationMechanismTest.java
+++ b/core/src/test/java/google/registry/request/auth/OidcTokenAuthenticationMechanismTest.java
@@ -18,7 +18,6 @@ import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.request.auth.AuthModule.BEARER_PREFIX;
import static google.registry.request.auth.AuthModule.IAP_HEADER_NAME;
-import static google.registry.request.auth.AuthModule.PROXY_HEADER_NAME;
import static google.registry.testing.DatabaseHelper.insertInDb;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -92,9 +91,8 @@ public class OidcTokenAuthenticationMechanismTest {
@Test
void testAuthResultBypass() {
- OidcTokenAuthenticationMechanism.setAuthResultForTesting(AuthResult.create(AuthLevel.APP));
- assertThat(authenticationMechanism.authenticate(null))
- .isEqualTo(AuthResult.create(AuthLevel.APP));
+ OidcTokenAuthenticationMechanism.setAuthResultForTesting(AuthResult.NOT_AUTHENTICATED);
+ assertThat(authenticationMechanism.authenticate(null)).isEqualTo(AuthResult.NOT_AUTHENTICATED);
}
@Test
@@ -169,16 +167,10 @@ public class OidcTokenAuthenticationMechanismTest {
void testRegular_tokenExtractor() throws Exception {
useRegularOidcMechanism();
// The token does not have the "Bearer " prefix.
- when(request.getHeader(PROXY_HEADER_NAME)).thenReturn(rawToken);
+ when(request.getHeader(AUTHORIZATION)).thenReturn(rawToken);
assertThat(authenticationMechanism.tokenExtractor.extract(request)).isNull();
// The token is in the correct format.
- when(request.getHeader(PROXY_HEADER_NAME))
- .thenReturn(String.format("%s%s", BEARER_PREFIX, rawToken));
- assertThat(authenticationMechanism.tokenExtractor.extract(request)).isEqualTo(rawToken);
-
- // The token is in the correct format, and under the alternative header.
- when(request.getHeader(PROXY_HEADER_NAME)).thenReturn(null);
when(request.getHeader(AUTHORIZATION))
.thenReturn(String.format("%s%s", BEARER_PREFIX, rawToken));
assertThat(authenticationMechanism.tokenExtractor.extract(request)).isEqualTo(rawToken);
diff --git a/core/src/test/java/google/registry/request/auth/RequestAuthenticatorTest.java b/core/src/test/java/google/registry/request/auth/RequestAuthenticatorTest.java
index 19b3cbe6e..1351261d2 100644
--- a/core/src/test/java/google/registry/request/auth/RequestAuthenticatorTest.java
+++ b/core/src/test/java/google/registry/request/auth/RequestAuthenticatorTest.java
@@ -14,361 +14,276 @@
package google.registry.request.auth;
-import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
+import static google.registry.request.auth.AuthResult.NOT_AUTHENTICATED;
+import static google.registry.request.auth.AuthSettings.AuthLevel.APP;
+import static google.registry.request.auth.AuthSettings.AuthLevel.NONE;
+import static google.registry.request.auth.AuthSettings.AuthLevel.USER;
+import static google.registry.request.auth.AuthSettings.AuthMethod.API;
+import static google.registry.request.auth.AuthSettings.AuthMethod.LEGACY;
+import static google.registry.request.auth.AuthSettings.UserPolicy.ADMIN;
+import static google.registry.request.auth.AuthSettings.UserPolicy.PUBLIC;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
-import com.google.appengine.api.users.User;
-import com.google.appengine.api.users.UserService;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import google.registry.persistence.transaction.JpaTestExtensions;
-import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
+import google.registry.model.console.GlobalRole;
+import google.registry.model.console.User;
+import google.registry.model.console.UserRoles;
import google.registry.request.auth.AuthSettings.AuthLevel;
import google.registry.request.auth.AuthSettings.AuthMethod;
import google.registry.request.auth.AuthSettings.UserPolicy;
-import google.registry.security.XsrfTokenManager;
-import google.registry.testing.FakeClock;
-import google.registry.testing.FakeOAuthService;
-import google.registry.testing.FakeUserService;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link RequestAuthenticator}. */
class RequestAuthenticatorTest {
- @RegisterExtension
- final JpaIntegrationTestExtension jpa =
- new JpaTestExtensions.Builder().buildIntegrationTestExtension();
+ private static final AuthResult APP_AUTH = AuthResult.createApp("app@registry.example");
- private static final AuthSettings AUTH_NONE =
- AuthSettings.create(ImmutableList.of(AuthMethod.API), AuthLevel.NONE, UserPolicy.PUBLIC);
+ private static final AuthResult USER_PUBLIC_AUTH =
+ AuthResult.createUser(
+ UserAuthInfo.create(
+ new User.Builder()
+ .setEmailAddress("user@registry.example")
+ .setUserRoles(
+ new UserRoles.Builder()
+ .setIsAdmin(false)
+ .setGlobalRole(GlobalRole.NONE)
+ .build())
+ .build()));
- private static final AuthSettings AUTH_ANY_USER_ANY_METHOD =
- AuthSettings.create(
- ImmutableList.of(AuthMethod.API, AuthMethod.LEGACY), AuthLevel.USER, UserPolicy.PUBLIC);
+ private static final AuthResult USER_ADMIN_AUTH =
+ AuthResult.createUser(
+ UserAuthInfo.create(
+ new User.Builder()
+ .setEmailAddress("admin@registry.example")
+ .setUserRoles(
+ new UserRoles.Builder()
+ .setIsAdmin(true)
+ .setGlobalRole(GlobalRole.FTE)
+ .build())
+ .build()));
- private static final AuthSettings AUTH_ANY_USER_NO_LEGACY =
- AuthSettings.create(ImmutableList.of(AuthMethod.API), AuthLevel.USER, UserPolicy.PUBLIC);
-
- private static final AuthSettings AUTH_ADMIN_USER_ANY_METHOD =
- AuthSettings.create(
- ImmutableList.of(AuthMethod.API, AuthMethod.LEGACY), AuthLevel.USER, UserPolicy.ADMIN);
-
- private static final AuthSettings AUTH_NO_METHODS =
- AuthSettings.create(ImmutableList.of(), AuthLevel.APP, UserPolicy.PUBLIC);
-
- private static final AuthSettings AUTH_WRONG_METHOD_ORDERING =
- AuthSettings.create(
- ImmutableList.of(AuthMethod.LEGACY, AuthMethod.API), AuthLevel.APP, UserPolicy.PUBLIC);
-
- private static final AuthSettings AUTH_DUPLICATE_METHODS =
- AuthSettings.create(
- ImmutableList.of(AuthMethod.API, AuthMethod.API), AuthLevel.APP, UserPolicy.PUBLIC);
-
- private static final AuthSettings AUTH_NONE_REQUIRES_ADMIN =
- AuthSettings.create(ImmutableList.of(AuthMethod.API), AuthLevel.NONE, UserPolicy.ADMIN);
-
- private final UserService mockUserService = mock(UserService.class);
private final HttpServletRequest req = mock(HttpServletRequest.class);
- private final User testUser = new User("test@google.com", "test@google.com");
- private final FakeUserService fakeUserService = new FakeUserService();
- private final XsrfTokenManager xsrfTokenManager =
- new XsrfTokenManager(new FakeClock(), fakeUserService);
- private final FakeOAuthService fakeOAuthService =
- new FakeOAuthService(
- false /* isOAuthEnabled */,
- testUser,
- false /* isUserAdmin */,
- "test-client-id",
- ImmutableList.of("test-scope1", "test-scope2", "nontest-scope"));
+ private final AuthenticationMechanism apiAuthenticationMechanism1 =
+ mock(AuthenticationMechanism.class);
+ private final AuthenticationMechanism apiAuthenticationMechanism2 =
+ mock(AuthenticationMechanism.class);
+ private final LegacyAuthenticationMechanism legacyAuthenticationMechanism =
+ mock(LegacyAuthenticationMechanism.class);
+
+ private Optional authorize(AuthLevel authLevel, UserPolicy userPolicy) {
+ return new RequestAuthenticator(
+ ImmutableList.of(apiAuthenticationMechanism1, apiAuthenticationMechanism2),
+ legacyAuthenticationMechanism)
+ .authorize(AuthSettings.create(ImmutableList.of(API, LEGACY), authLevel, userPolicy), req);
+ }
+
+ private AuthResult authenticate(AuthMethod... methods) {
+ return new RequestAuthenticator(
+ ImmutableList.of(apiAuthenticationMechanism1, apiAuthenticationMechanism2),
+ legacyAuthenticationMechanism)
+ .authenticate(AuthSettings.create(ImmutableList.copyOf(methods), NONE, PUBLIC), req);
+ }
@BeforeEach
void beforeEach() {
- when(req.getMethod()).thenReturn("POST");
- }
-
- private RequestAuthenticator createRequestAuthenticator(UserService userService) {
- return new RequestAuthenticator(
- ImmutableList.of(
- new OAuthAuthenticationMechanism(
- fakeOAuthService,
- ImmutableSet.of("test-scope1", "test-scope2", "test-scope3"),
- ImmutableSet.of("test-scope1", "test-scope2"),
- ImmutableSet.of("test-client-id", "other-test-client-id"))),
- new LegacyAuthenticationMechanism(userService, xsrfTokenManager));
- }
-
- private Optional runTest(UserService userService, AuthSettings auth) {
- return createRequestAuthenticator(userService).authorize(auth, req);
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(NOT_AUTHENTICATED);
+ when(apiAuthenticationMechanism2.authenticate(req)).thenReturn(NOT_AUTHENTICATED);
+ when(legacyAuthenticationMechanism.authenticate(req)).thenReturn(NOT_AUTHENTICATED);
}
@Test
- void testNoAuthNeeded_noneFound() {
- Optional authResult = runTest(mockUserService, AUTH_NONE);
-
- verifyNoInteractions(mockUserService);
- assertThat(authResult).isPresent();
- assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.NONE);
+ void testAuthorize_noneRequired() {
+ for (AuthResult resultFound :
+ ImmutableList.of(NOT_AUTHENTICATED, APP_AUTH, USER_ADMIN_AUTH, USER_PUBLIC_AUTH)) {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(resultFound);
+ assertThat(authorize(NONE, PUBLIC)).hasValue(resultFound);
+ }
}
@Test
- void testAnyUserAnyMethod_notLoggedIn() {
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_ANY_METHOD);
+ void testAuthorize_appPublicRequired() {
+ authorize(APP, PUBLIC);
+ assertThat(authorize(APP, PUBLIC)).isEmpty();
- assertThat(authResult).isEmpty();
+ for (AuthResult resultFound : ImmutableList.of(APP_AUTH, USER_ADMIN_AUTH, USER_PUBLIC_AUTH)) {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(resultFound);
+ assertThat(authorize(APP, PUBLIC)).hasValue(resultFound);
+ }
}
@Test
- void testAnyUserAnyMethod_xsrfFailure() {
- fakeUserService.setUser(testUser, false);
+ void testAuthorize_appAdminRequired() {
+ for (AuthResult resultFound : ImmutableList.of(NOT_AUTHENTICATED, USER_PUBLIC_AUTH)) {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(resultFound);
+ assertThat(authorize(APP, ADMIN)).isEmpty();
+ }
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_ANY_METHOD);
-
- assertThat(authResult).isEmpty();
+ for (AuthResult resultFound : ImmutableList.of(APP_AUTH, USER_ADMIN_AUTH)) {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(resultFound);
+ assertThat(authorize(APP, ADMIN)).hasValue(resultFound);
+ }
}
@Test
- void testAnyUserAnyMethod_success() {
- fakeUserService.setUser(testUser, false /* isAdmin */);
- when(req.getHeader(XsrfTokenManager.X_CSRF_TOKEN))
- .thenReturn(xsrfTokenManager.generateToken(testUser.getEmail()));
+ void testAuthorize_userPublicRequired() {
+ for (AuthResult resultFound : ImmutableList.of(NOT_AUTHENTICATED, APP_AUTH)) {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(resultFound);
+ assertThat(authorize(USER, PUBLIC)).isEmpty();
+ }
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_ANY_METHOD);
-
- assertThat(authResult).isPresent();
- assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
- assertThat(authResult.get().userAuthInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser);
- assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse();
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isEmpty();
+ for (AuthResult resultFound : ImmutableList.of(USER_PUBLIC_AUTH, USER_ADMIN_AUTH)) {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(resultFound);
+ assertThat(authorize(USER, PUBLIC)).hasValue(resultFound);
+ }
}
@Test
- void testAnyUserAnyMethod_xsrfNotRequiredForGet() {
- fakeUserService.setUser(testUser, false);
- when(req.getMethod()).thenReturn("GET");
+ void testAuthorize_userAdminRequired() {
+ for (AuthResult resultFound : ImmutableList.of(NOT_AUTHENTICATED, APP_AUTH, USER_PUBLIC_AUTH)) {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(resultFound);
+ assertThat(authorize(USER, ADMIN)).isEmpty();
+ }
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_ANY_METHOD);
-
- assertThat(authResult).isPresent();
- assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
- assertThat(authResult.get().userAuthInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser);
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isEmpty();
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(USER_ADMIN_AUTH);
+ assertThat(authorize(USER, ADMIN)).hasValue(USER_ADMIN_AUTH);
}
@Test
- void testAdminUserAnyMethod_notLoggedIn() {
- Optional authResult = runTest(fakeUserService, AUTH_ADMIN_USER_ANY_METHOD);
-
- assertThat(authResult).isEmpty();
+ void testAuthenticate_apiFirst() {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(APP_AUTH);
+ assertThat(authenticate(API, LEGACY)).isEqualTo(APP_AUTH);
+ verify(apiAuthenticationMechanism1).authenticate(req);
+ verifyNoMoreInteractions(apiAuthenticationMechanism1);
+ verifyNoMoreInteractions(apiAuthenticationMechanism2);
+ verifyNoMoreInteractions(legacyAuthenticationMechanism);
}
@Test
- void testAdminUserAnyMethod_notAdminUser() {
- fakeUserService.setUser(testUser, false /* isAdmin */);
-
- Optional authResult = runTest(fakeUserService, AUTH_ADMIN_USER_ANY_METHOD);
-
- assertThat(authResult).isEmpty();
+ void testAuthenticate_apiSecond() {
+ when(apiAuthenticationMechanism2.authenticate(req)).thenReturn(APP_AUTH);
+ assertThat(authenticate(API, LEGACY)).isEqualTo(APP_AUTH);
+ verify(apiAuthenticationMechanism1).authenticate(req);
+ verify(apiAuthenticationMechanism2).authenticate(req);
+ verifyNoMoreInteractions(apiAuthenticationMechanism1);
+ verifyNoMoreInteractions(apiAuthenticationMechanism2);
+ verifyNoMoreInteractions(legacyAuthenticationMechanism);
}
@Test
- void testAdminUserAnyMethod_xsrfFailure() {
- fakeUserService.setUser(testUser, true);
-
- Optional authResult = runTest(fakeUserService, AUTH_ADMIN_USER_ANY_METHOD);
-
- assertThat(authResult).isEmpty();
+ void testAuthenticate_legacy() {
+ when(legacyAuthenticationMechanism.authenticate(req)).thenReturn(APP_AUTH);
+ assertThat(authenticate(API, LEGACY)).isEqualTo(APP_AUTH);
+ verify(apiAuthenticationMechanism1).authenticate(req);
+ verify(apiAuthenticationMechanism2).authenticate(req);
+ verify(legacyAuthenticationMechanism).authenticate(req);
+ verifyNoMoreInteractions(apiAuthenticationMechanism1);
+ verifyNoMoreInteractions(apiAuthenticationMechanism2);
+ verifyNoMoreInteractions(legacyAuthenticationMechanism);
}
@Test
- void testAdminUserAnyMethod_success() {
- fakeUserService.setUser(testUser, true /* isAdmin */);
- when(req.getHeader(XsrfTokenManager.X_CSRF_TOKEN))
- .thenReturn(xsrfTokenManager.generateToken(testUser.getEmail()));
-
- Optional authResult = runTest(fakeUserService, AUTH_ADMIN_USER_ANY_METHOD);
-
- assertThat(authResult).isPresent();
- assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
- assertThat(authResult.get().userAuthInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser);
- assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isTrue();
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isEmpty();
+ void testAuthenticate_returnFirstResult() {
+ // API auth 2 returns an authenticted auth result, so we don't bother trying the next auth
+ // (legacy auth).
+ when(apiAuthenticationMechanism2.authenticate(req)).thenReturn(APP_AUTH);
+ when(legacyAuthenticationMechanism.authenticate(req)).thenReturn(USER_PUBLIC_AUTH);
+ assertThat(authenticate(API, LEGACY)).isEqualTo(APP_AUTH);
+ verify(apiAuthenticationMechanism1).authenticate(req);
+ verify(apiAuthenticationMechanism2).authenticate(req);
+ verifyNoMoreInteractions(apiAuthenticationMechanism1);
+ verifyNoMoreInteractions(apiAuthenticationMechanism2);
+ verifyNoMoreInteractions(legacyAuthenticationMechanism);
}
@Test
- void testOAuth_success() {
- fakeOAuthService.setUser(testUser);
- fakeOAuthService.setOAuthEnabled(true);
- when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
-
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY);
-
- assertThat(authResult).isPresent();
- assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
- assertThat(authResult.get().userAuthInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser);
- assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse();
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes())
- .containsAtLeast("test-scope1", "test-scope2");
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().oauthClientId())
- .isEqualTo("test-client-id");
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().rawAccessToken())
- .isEqualTo("TOKEN");
+ void testAuthenticate_notAuthenticated() {
+ assertThat(authenticate(API, LEGACY)).isEqualTo(NOT_AUTHENTICATED);
+ verify(apiAuthenticationMechanism1).authenticate(req);
+ verify(apiAuthenticationMechanism2).authenticate(req);
+ verify(legacyAuthenticationMechanism).authenticate(req);
+ verifyNoMoreInteractions(apiAuthenticationMechanism1);
+ verifyNoMoreInteractions(apiAuthenticationMechanism2);
+ verifyNoMoreInteractions(legacyAuthenticationMechanism);
}
@Test
- void testOAuthAdmin_success() {
- fakeOAuthService.setUser(testUser);
- fakeOAuthService.setUserAdmin(true);
- fakeOAuthService.setOAuthEnabled(true);
- when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
-
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY);
-
- assertThat(authResult).isPresent();
- assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
- assertThat(authResult.get().userAuthInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser);
- assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isTrue();
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes())
- .containsAtLeast("test-scope1", "test-scope2");
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().oauthClientId())
- .isEqualTo("test-client-id");
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().rawAccessToken())
- .isEqualTo("TOKEN");
+ void testAuthenticate_apiOnly() {
+ when(legacyAuthenticationMechanism.authenticate(req)).thenReturn(USER_PUBLIC_AUTH);
+ assertThat(authenticate(API)).isEqualTo(NOT_AUTHENTICATED);
+ verify(apiAuthenticationMechanism1).authenticate(req);
+ verify(apiAuthenticationMechanism2).authenticate(req);
+ verifyNoMoreInteractions(apiAuthenticationMechanism1);
+ verifyNoMoreInteractions(apiAuthenticationMechanism2);
+ verifyNoMoreInteractions(legacyAuthenticationMechanism);
}
@Test
- void testOAuthMissingAuthenticationToken_failure() {
- fakeOAuthService.setUser(testUser);
- fakeOAuthService.setOAuthEnabled(true);
-
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY);
-
- assertThat(authResult).isEmpty();
+ void testAuthenticate_legacyOnly() {
+ when(apiAuthenticationMechanism1.authenticate(req)).thenReturn(USER_PUBLIC_AUTH);
+ assertThat(authenticate(LEGACY)).isEqualTo(NOT_AUTHENTICATED);
+ verify(legacyAuthenticationMechanism).authenticate(req);
+ verifyNoMoreInteractions(apiAuthenticationMechanism1);
+ verifyNoMoreInteractions(apiAuthenticationMechanism2);
+ verifyNoMoreInteractions(legacyAuthenticationMechanism);
}
@Test
- void testOAuthClientIdMismatch_failure() {
- fakeOAuthService.setUser(testUser);
- fakeOAuthService.setOAuthEnabled(true);
- fakeOAuthService.setClientId("wrong-client-id");
- when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
-
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY);
-
- assertThat(authResult).isEmpty();
- }
-
- @Test
- void testOAuthNoScopes_failure() {
- fakeOAuthService.setUser(testUser);
- fakeOAuthService.setOAuthEnabled(true);
- fakeOAuthService.setAuthorizedScopes();
- when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
-
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY);
-
- assertThat(authResult).isEmpty();
- }
-
- @Test
- void testOAuthMissingScope_failure() {
- fakeOAuthService.setUser(testUser);
- fakeOAuthService.setOAuthEnabled(true);
- fakeOAuthService.setAuthorizedScopes("test-scope1", "test-scope3");
- when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
-
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY);
-
- assertThat(authResult).isEmpty();
- }
-
- @Test
- void testOAuthExtraScope_success() {
- fakeOAuthService.setUser(testUser);
- fakeOAuthService.setOAuthEnabled(true);
- fakeOAuthService.setAuthorizedScopes("test-scope1", "test-scope2", "test-scope3");
- when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
-
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY);
-
- assertThat(authResult).isPresent();
- assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
- assertThat(authResult.get().userAuthInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser);
- assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse();
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent();
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes())
- .containsAtLeast("test-scope1", "test-scope2", "test-scope3");
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().oauthClientId())
- .isEqualTo("test-client-id");
- assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().rawAccessToken())
- .isEqualTo("TOKEN");
- }
-
- @Test
- void testAnyUserNoLegacy_failureWithLegacyUser() {
- fakeUserService.setUser(testUser, false /* isAdmin */);
-
- Optional authResult = runTest(fakeUserService, AUTH_ANY_USER_NO_LEGACY);
-
- assertThat(authResult).isEmpty();
- }
-
- @Test
- void testCheckAuthConfig_noMethods_failure() {
+ void testFailure_checkAuthConfig_noMethods() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
- () -> RequestAuthenticator.checkAuthConfig(AUTH_NO_METHODS));
+ () ->
+ RequestAuthenticator.checkAuthConfig(
+ AuthSettings.create(ImmutableList.of(), NONE, PUBLIC)));
assertThat(thrown).hasMessageThat().contains("Must specify at least one auth method");
}
@Test
- void testCheckAuthConfig_wrongMethodOrdering_failure() {
+ void testFailure_checkAuthConfig_wrongMethodOrder() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
- () -> RequestAuthenticator.checkAuthConfig(AUTH_WRONG_METHOD_ORDERING));
+ () ->
+ RequestAuthenticator.checkAuthConfig(
+ AuthSettings.create(ImmutableList.of(LEGACY, API), NONE, PUBLIC)));
assertThat(thrown)
.hasMessageThat()
.contains("Auth methods must be unique and strictly in order - API, LEGACY");
}
@Test
- void testCheckAuthConfig_noneAuthLevelRequiresAdmin_failure() {
+ void testFailure_CheckAuthConfig_duplicateMethods() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
- () -> RequestAuthenticator.checkAuthConfig(AUTH_NONE_REQUIRES_ADMIN));
+ () ->
+ RequestAuthenticator.checkAuthConfig(
+ AuthSettings.create(ImmutableList.of(API, API), NONE, PUBLIC)));
+ assertThat(thrown)
+ .hasMessageThat()
+ .contains("Auth methods must be unique and strictly in order - API, LEGACY");
+ }
+
+ @Test
+ void testFailure_checkAuthConfig_noneAuthLevelRequiresAdmin() {
+ IllegalArgumentException thrown =
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ RequestAuthenticator.checkAuthConfig(
+ AuthSettings.create(ImmutableList.of(API, LEGACY), NONE, ADMIN)));
assertThat(thrown)
.hasMessageThat()
.contains("Actions with minimal auth level at NONE should not specify ADMIN user policy");
}
-
- @Test
- void testCheckAuthConfig_DuplicateMethods_failure() {
- IllegalArgumentException thrown =
- assertThrows(
- IllegalArgumentException.class,
- () -> RequestAuthenticator.checkAuthConfig(AUTH_DUPLICATE_METHODS));
- assertThat(thrown)
- .hasMessageThat()
- .contains("Auth methods must be unique and strictly in order - API, LEGACY");
- }
}
diff --git a/core/src/test/java/google/registry/security/XsrfTokenManagerTest.java b/core/src/test/java/google/registry/security/XsrfTokenManagerTest.java
index c1cbdc4d4..363293db7 100644
--- a/core/src/test/java/google/registry/security/XsrfTokenManagerTest.java
+++ b/core/src/test/java/google/registry/security/XsrfTokenManagerTest.java
@@ -16,13 +16,15 @@ package google.registry.security;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import com.google.appengine.api.users.User;
+import com.google.appengine.api.users.UserService;
import com.google.common.base.Splitter;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.FakeClock;
-import google.registry.testing.FakeUserService;
import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -37,14 +39,16 @@ class XsrfTokenManagerTest {
private final User testUser = new User("test@example.com", "test@example.com");
private final FakeClock clock = new FakeClock(START_OF_TIME);
- private final FakeUserService userService = new FakeUserService();
+ private final UserService userService = mock(UserService.class);
private final XsrfTokenManager xsrfTokenManager = new XsrfTokenManager(clock, userService);
private String token;
@BeforeEach
void beforeEach() {
- userService.setUser(testUser, false);
+ when(userService.isUserLoggedIn()).thenReturn(true);
+ when(userService.getCurrentUser()).thenReturn(testUser);
+ when(userService.isUserAdmin()).thenReturn(false);
token = xsrfTokenManager.generateToken(testUser.getEmail());
}
diff --git a/core/src/test/java/google/registry/server/RegistryTestServer.java b/core/src/test/java/google/registry/server/RegistryTestServer.java
index 4d44d23e1..b8a846dbb 100644
--- a/core/src/test/java/google/registry/server/RegistryTestServer.java
+++ b/core/src/test/java/google/registry/server/RegistryTestServer.java
@@ -84,7 +84,7 @@ public final class RegistryTestServer {
private final TestServer server;
- /** @see TestServer#TestServer(HostAndPort, ImmutableMap, ImmutableList, ImmutableList) */
+ /** @see TestServer#TestServer(HostAndPort, ImmutableMap, ImmutableList) */
public RegistryTestServer(HostAndPort address) {
server = new TestServer(address, RUNFILES, ROUTES);
}
@@ -104,7 +104,7 @@ public final class RegistryTestServer {
server.stop();
}
- /** @see TestServer#getUrl(java.lang.String) */
+ /** @see TestServer#getUrl(String) */
public URL getUrl(String path) {
return server.getUrl(path);
}
diff --git a/core/src/test/java/google/registry/server/RegistryTestServerMain.java b/core/src/test/java/google/registry/server/RegistryTestServerMain.java
index 762fe3132..13e71586a 100644
--- a/core/src/test/java/google/registry/server/RegistryTestServerMain.java
+++ b/core/src/test/java/google/registry/server/RegistryTestServerMain.java
@@ -25,7 +25,6 @@ import google.registry.model.console.UserRoles;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTransactionManagerExtension;
import google.registry.request.auth.AuthResult;
-import google.registry.request.auth.AuthSettings.AuthLevel;
import google.registry.request.auth.OidcTokenAuthenticationMechanism;
import google.registry.request.auth.UserAuthInfo;
import google.registry.testing.UserInfo;
@@ -148,7 +147,7 @@ public final class RegistryTestServerMain {
.setRegistryLockPassword("registryLockPassword")
.build();
OidcTokenAuthenticationMechanism.setAuthResultForTesting(
- AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user)));
+ AuthResult.createUser(UserAuthInfo.create(user)));
new JpaTestExtensions.Builder().buildIntegrationTestExtension().beforeEach(null);
JpaTransactionManagerExtension.loadInitialData();
System.out.printf("%sLoading fixtures...%s\n", BLUE, RESET);
diff --git a/core/src/test/java/google/registry/testing/FakeOAuthService.java b/core/src/test/java/google/registry/testing/FakeOAuthService.java
deleted file mode 100644
index c74beb93c..000000000
--- a/core/src/test/java/google/registry/testing/FakeOAuthService.java
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2017 The Nomulus Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package google.registry.testing;
-
-import com.google.appengine.api.oauth.OAuthRequestException;
-import com.google.appengine.api.oauth.OAuthService;
-import com.google.appengine.api.users.User;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-
-/** A fake {@link OAuthService} implementation for testing. */
-public class FakeOAuthService implements OAuthService {
-
- private boolean isOAuthEnabled;
- private User currentUser;
- private boolean isUserAdmin;
- private String clientId;
- private ImmutableList authorizedScopes;
-
- public FakeOAuthService(
- boolean isOAuthEnabled,
- User currentUser,
- boolean isUserAdmin,
- String clientId,
- List authorizedScopes) {
- this.isOAuthEnabled = isOAuthEnabled;
- this.currentUser = currentUser;
- this.isUserAdmin = isUserAdmin;
- this.clientId = clientId;
- this.authorizedScopes = ImmutableList.copyOf(authorizedScopes);
- }
-
- public void setOAuthEnabled(boolean isOAuthEnabled) {
- this.isOAuthEnabled = isOAuthEnabled;
- }
-
- public void setUser(User currentUser) {
- this.currentUser = currentUser;
- }
-
- public void setUserAdmin(boolean isUserAdmin) {
- this.isUserAdmin = isUserAdmin;
- }
-
- public void setClientId(String clientId) {
- this.clientId = clientId;
- }
-
- public void setAuthorizedScopes(String... scopes) {
- this.authorizedScopes = ImmutableList.copyOf(scopes);
- }
-
- @Override
- public User getCurrentUser() throws OAuthRequestException {
- if (!isOAuthEnabled) {
- throw new OAuthRequestException("invalid OAuth request");
- }
- return currentUser;
- }
-
- @Override
- public User getCurrentUser(String scope) throws OAuthRequestException {
- return getCurrentUser();
- }
-
- @Override
- public User getCurrentUser(String... scopes) throws OAuthRequestException {
- return getCurrentUser();
- }
-
- @Override
- public boolean isUserAdmin() throws OAuthRequestException {
- if (!isOAuthEnabled) {
- throw new OAuthRequestException("invalid OAuth request");
- }
- return isUserAdmin;
- }
-
- @Override
- public boolean isUserAdmin(String scope) throws OAuthRequestException {
- return isUserAdmin();
- }
-
- @Override
- public boolean isUserAdmin(String... scopes) throws OAuthRequestException {
- return isUserAdmin();
- }
-
- @Override
- public String getClientId(String scope) throws OAuthRequestException {
- if (!isOAuthEnabled) {
- throw new OAuthRequestException("invalid OAuth request");
- }
- return clientId;
- }
-
- @Override
- public String getClientId(String... scopes) throws OAuthRequestException {
- if (!isOAuthEnabled) {
- throw new OAuthRequestException("invalid OAuth request");
- }
- return clientId;
- }
-
- @Override
- public String[] getAuthorizedScopes(String... scopes) throws OAuthRequestException {
- if (!isOAuthEnabled) {
- throw new OAuthRequestException("invalid OAuth request");
- }
- return authorizedScopes.toArray(new String[0]);
- }
-
- @Deprecated
- @Override
- public String getOAuthConsumerKey() {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/core/src/test/java/google/registry/testing/FakeUserService.java b/core/src/test/java/google/registry/testing/FakeUserService.java
deleted file mode 100644
index a78a5fcb5..000000000
--- a/core/src/test/java/google/registry/testing/FakeUserService.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2017 The Nomulus Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package google.registry.testing;
-
-import com.google.appengine.api.users.User;
-import com.google.appengine.api.users.UserService;
-import google.registry.model.annotations.DeleteAfterMigration;
-import java.util.Set;
-import javax.annotation.Nullable;
-
-/** Fake implementation of {@link UserService} for testing. */
-@DeleteAfterMigration
-public class FakeUserService implements UserService {
-
- @Nullable private User user = null;
- private boolean isAdmin = false;
-
- public void setUser(@Nullable User user, boolean isAdmin) {
- this.user = user;
- this.isAdmin = isAdmin;
- }
-
- @Override
- public String createLoginURL(String destinationURL) {
- return String.format("/login?dest=%s", destinationURL);
- }
-
- @Override
- public String createLoginURL(String destinationURL, String authDomain) {
- return createLoginURL(destinationURL);
- }
-
- @Deprecated
- @Override
- public String createLoginURL(String destinationURL, String authDomain, String federatedIdentity,
- Set attributesRequest) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String createLogoutURL(String destinationURL) {
- return String.format("/logout?dest=%s", destinationURL);
- }
-
- @Override
- public String createLogoutURL(String destinationURL, String authDomain) {
- return createLogoutURL(destinationURL);
- }
-
- @Override
- public boolean isUserLoggedIn() {
- return user != null;
- }
-
- @Override
- public boolean isUserAdmin() {
- return isAdmin;
- }
-
- @Override
- public User getCurrentUser() {
- return user;
- }
-}
diff --git a/core/src/test/java/google/registry/tools/AuthModuleTest.java b/core/src/test/java/google/registry/tools/AuthModuleTest.java
index 3e32e1688..e3676d6bf 100644
--- a/core/src/test/java/google/registry/tools/AuthModuleTest.java
+++ b/core/src/test/java/google/registry/tools/AuthModuleTest.java
@@ -72,7 +72,7 @@ class AuthModuleTest {
}
})
// We need to set the following fields because they are checked when
- // Credential#setRefreshToken is called. However they are not actually persisted in the
+ // Credential#setRefreshToken is called. However, they are not actually persisted in the
// DataStore and not actually used in tests.
.setJsonFactory(new GsonFactory())
.setTransport(new NetHttpTransport())
@@ -104,7 +104,7 @@ class AuthModuleTest {
AuthModule.provideClientScopeQualifier("client-id", ImmutableList.of("foo", "bar"));
// If we change the way we encode client id and scopes, this assertion will break. That's
- // probably ok and you can just change the text. The things you have to be aware of are:
+ // probably ok, and you can just change the text. The things you have to be aware of are:
// - Names in the new encoding should have a low risk of collision with the old encoding.
// - Changing the encoding will force all OAuth users of the nomulus tool to do a new login
// (existing credentials will not be used).
@@ -155,7 +155,7 @@ class AuthModuleTest {
AuthModule.provideClientScopeQualifier(AuthModule.provideClientId(clientSecrets), scopes));
}
- private GoogleClientSecrets getSecrets() {
+ private static GoogleClientSecrets getSecrets() {
return new GoogleClientSecrets()
.setInstalled(
AuthModule.provideDefaultInstalledDetails()
@@ -166,7 +166,8 @@ class AuthModuleTest {
@Test
void test_provideLocalCredentialJson() {
String credentialJson =
- AuthModule.provideLocalCredentialJson(this::getSecrets, this::getCredential, null);
+ AuthModule.provideLocalCredentialJson(
+ AuthModuleTest::getSecrets, this::getCredential, null);
Map jsonMap =
new Gson().fromJson(credentialJson, new TypeToken