mirror of
https://github.com/google/nomulus.git
synced 2025-07-23 11:16:04 +02:00
Remove OAuthAuthenticationMechanism (#2171)
Also made some refactoring to various Auth related classes to clean up things a bit and make the logic less convoluted: 1. In Auth, remove AUTH_API_PUBLIC as it is only used by the WHOIS and EPP endpoints accessed by the proxy. Previously, the proxy relies on OAuth and its service account is not given admin role (in OAuth parlance), so we made them accessible by a public user, deferring authorization to the actions themselves. In practice, OAuth checks for allowlisted client IDs and only the proxy client ID was allowlisted, which effectively limited access to only the proxy anyway. 2. In AuthResult, expose the service account email if it is at APP level. RequestAuthenticator will print out the auth result and therefore log the email, making it easy to identify which account was used. This field is mutually exclusive to the user auth info field. As a result, the factory methods are refactored to explicitly create either APP or USER level auth result. 3. Completely re-wrote RequestAuthenticatorTest. Previously, the test mingled testing functionalities of the target class with testing how various authentication mechanisms work. Now they are cleanly decoupled, and each method in RequestAuthenticator is tested individually. 4. Removed nomulus-config-production-sample.yaml as it is vastly out of date.
This commit is contained in:
parent
bbdbfe85ed
commit
36bd508bf9
49 changed files with 365 additions and 1098 deletions
|
@ -1174,44 +1174,6 @@ public final class RegistryConfig {
|
|||
return CONFIG_SETTINGS.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the OAuth scopes that authentication logic should detect on access tokens.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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<String> provideAvailableOauthScopes(RegistryConfigSettings config) {
|
||||
return ImmutableSet.copyOf(config.auth.availableOauthScopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the OAuth scopes that are required for authenticating successfully.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>If we feel the need, we could define additional fixed scopes, similar to the Java remote
|
||||
* API, which requires at least one of:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code https://www.googleapis.com/auth/appengine.apis}
|
||||
* <li>{@code https://www.googleapis.com/auth/cloud-platform}
|
||||
* </ul>
|
||||
*/
|
||||
@Provides
|
||||
@Config("requiredOauthScopes")
|
||||
public static ImmutableSet<String> 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<String> provideAllowedOauthClientIds(RegistryConfigSettings config) {
|
||||
return ImmutableSet.copyOf(config.auth.allowedOauthClientIds);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("oauthClientId")
|
||||
public static String provideOauthClientId(RegistryConfigSettings config) {
|
||||
|
|
|
@ -58,9 +58,6 @@ public class RegistryConfigSettings {
|
|||
|
||||
/** Configuration options for authenticating users. */
|
||||
public static class Auth {
|
||||
public List<String> availableOauthScopes;
|
||||
public List<String> requiredOauthScopes;
|
||||
public List<String> allowedOauthClientIds;
|
||||
public List<String> allowedServiceAccountEmails;
|
||||
public String oauthClientId;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 "<service>-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
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>This applies to the majority of the endpoints.
|
||||
* <p>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);
|
||||
|
||||
|
|
|
@ -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<AuthenticationMechanism> 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());
|
||||
}
|
||||
|
|
|
@ -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> 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<String> appServiceAccount();
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
return authLevel() != AuthLevel.NONE;
|
||||
}
|
||||
|
@ -47,15 +53,27 @@ public abstract class AuthResult {
|
|||
.orElse("<logged-out user>");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <p>In Auth: Authentication is required, but app-internal authentication (which isn't
|
||||
* associated with a specific user) is permitted.
|
||||
* <p>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.
|
||||
*
|
||||
* <p>In AuthResult: App-internal authentication was successful.
|
||||
* <p>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()}.
|
||||
*
|
||||
* <p>Note that, according to App Engine, anybody with access to the app in the GCP Console,
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
/**
|
||||
* A particular way to authenticate an HTTP request, returning an {@link AuthResult}.
|
||||
*
|
||||
* <p>For instance, a request could be authenticated using OAuth, via special request headers, etc.
|
||||
* <p>For instance, a request could be authenticated using OIDC, via special request headers, etc.
|
||||
*/
|
||||
public interface AuthenticationMechanism {
|
||||
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <p>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<String> availableOauthScopes;
|
||||
|
||||
/** The OAuth scopes which must all be present for authentication to succeed. */
|
||||
private final ImmutableSet<String> requiredOauthScopes;
|
||||
|
||||
private final ImmutableSet<String> allowedOauthClientIds;
|
||||
|
||||
@Inject
|
||||
public OAuthAuthenticationMechanism(
|
||||
OAuthService oauthService,
|
||||
@Config("availableOauthScopes") ImmutableSet<String> availableOauthScopes,
|
||||
@Config("requiredOauthScopes") ImmutableSet<String> requiredOauthScopes,
|
||||
@Config("allowedOauthClientIds") ImmutableSet<String> 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<String> 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)));
|
||||
}
|
||||
}
|
|
@ -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<String> 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.
|
||||
*
|
||||
* <p>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<String> authorizedScopes, String oauthClientId, String rawAccessToken) {
|
||||
return new AutoValue_OAuthTokenInfo(authorizedScopes, oauthClientId, rawAccessToken);
|
||||
}
|
||||
}
|
|
@ -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<User> 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
|
|||
*
|
||||
* <p>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).
|
||||
*
|
||||
* <p>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 <a href=https://datatracker.ietf.org/doc/html/rfc6750>Bearer Token Usage</a>
|
||||
*/
|
||||
|
|
|
@ -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<AuthMethod> 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),
|
||||
|
|
|
@ -22,6 +22,8 @@ import java.util.Optional;
|
|||
@AutoValue
|
||||
public abstract class UserAuthInfo {
|
||||
|
||||
public abstract Optional<google.registry.model.console.User> consoleUser();
|
||||
|
||||
/** User object from the AppEngine Users API. */
|
||||
public abstract Optional<User> appEngineUser();
|
||||
|
||||
|
@ -34,11 +36,6 @@ public abstract class UserAuthInfo {
|
|||
*/
|
||||
public abstract boolean isUserAdmin();
|
||||
|
||||
public abstract Optional<google.registry.model.console.User> consoleUser();
|
||||
|
||||
/** Used by the OAuth authentication mechanism (only) to return information about the session. */
|
||||
public abstract Optional<OAuthTokenInfo> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -191,9 +191,6 @@ interface RegistryToolComponent {
|
|||
@BindsInstance
|
||||
Builder sqlAccessInfoFile(@Nullable @Config("sqlAccessInfoFile") String sqlAccessInfoFile);
|
||||
|
||||
@BindsInstance
|
||||
Builder addOAuthHeader(@Config("addOauthHeader") boolean addOauthHeader);
|
||||
|
||||
RegistryToolComponent build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<A extends RdapActionBase> {
|
|||
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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String> 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<AuthResult> 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<AuthResult> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<String> authorizedScopes;
|
||||
|
||||
public FakeOAuthService(
|
||||
boolean isOAuthEnabled,
|
||||
User currentUser,
|
||||
boolean isUserAdmin,
|
||||
String clientId,
|
||||
List<String> 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();
|
||||
}
|
||||
}
|
|
@ -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<String> 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;
|
||||
}
|
||||
}
|
|
@ -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<String, String> jsonMap =
|
||||
new Gson().fromJson(credentialJson, new TypeToken<Map<String, String>>() {}.getType());
|
||||
assertThat(jsonMap.get("type")).isEqualTo("authorized_user");
|
||||
|
@ -182,7 +183,7 @@ class AuthModuleTest {
|
|||
Files.write(credentialFile.toPath(), "{some_field: some_value}".getBytes(UTF_8));
|
||||
String credentialJson =
|
||||
AuthModule.provideLocalCredentialJson(
|
||||
this::getSecrets, this::getCredential, credentialFile.getCanonicalPath());
|
||||
AuthModuleTest::getSecrets, this::getCredential, credentialFile.getCanonicalPath());
|
||||
assertThat(credentialJson).isEqualTo("{some_field: some_value}");
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,6 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import static google.registry.tools.RequestFactoryModule.REQUEST_TIMEOUT_MS;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
|
@ -35,6 +32,7 @@ import com.google.auth.oauth2.UserCredentials;
|
|||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.testing.SystemPropertyExtension;
|
||||
import google.registry.util.GoogleCredentialsBundle;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
@ -50,7 +48,6 @@ public class RequestFactoryModuleTest {
|
|||
final SystemPropertyExtension systemPropertyExtension = new SystemPropertyExtension();
|
||||
|
||||
@Mock public GoogleCredentialsBundle credentialsBundle;
|
||||
@Mock public HttpRequestInitializer httpRequestInitializer;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
|
@ -64,12 +61,11 @@ public class RequestFactoryModuleTest {
|
|||
RegistryConfig.CONFIG_SETTINGS.get().gcpProject.isLocal = true;
|
||||
try {
|
||||
HttpRequestFactory factory =
|
||||
RequestFactoryModule.provideHttpRequestFactory(credentialsBundle, "client-id", false);
|
||||
RequestFactoryModule.provideHttpRequestFactory(credentialsBundle, "client-id");
|
||||
HttpRequestInitializer initializer = factory.getInitializer();
|
||||
assertThat(initializer).isNotNull();
|
||||
HttpRequest request = factory.buildGetRequest(new GenericUrl("http://localhost"));
|
||||
initializer.initialize(request);
|
||||
verifyNoInteractions(httpRequestInitializer);
|
||||
} finally {
|
||||
RegistryConfig.CONFIG_SETTINGS.get().gcpProject.isLocal = origIsLocal;
|
||||
}
|
||||
|
@ -77,7 +73,6 @@ public class RequestFactoryModuleTest {
|
|||
|
||||
@Test
|
||||
void test_provideHttpRequestFactory_remote() throws Exception {
|
||||
when(credentialsBundle.getHttpRequestInitializer()).thenReturn(httpRequestInitializer);
|
||||
// Mock the request/response to/from the OIDC server requesting an ID token
|
||||
UserCredentials mockUserCredentials = mock(UserCredentials.class);
|
||||
when(credentialsBundle.getGoogleCredentials()).thenReturn(mockUserCredentials);
|
||||
|
@ -97,23 +92,15 @@ public class RequestFactoryModuleTest {
|
|||
boolean origIsLocal = RegistryConfig.CONFIG_SETTINGS.get().gcpProject.isLocal;
|
||||
RegistryConfig.CONFIG_SETTINGS.get().gcpProject.isLocal = false;
|
||||
try {
|
||||
// With OAuth header.
|
||||
HttpRequestFactory factory =
|
||||
RequestFactoryModule.provideHttpRequestFactory(credentialsBundle, "clientId", true);
|
||||
RequestFactoryModule.provideHttpRequestFactory(credentialsBundle, "clientId");
|
||||
HttpRequest request = factory.buildGetRequest(new GenericUrl("http://localhost"));
|
||||
assertThat(request.getHeaders().get("Proxy-Authorization")).isEqualTo("Bearer oidc.token");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> authHeaders = (List<String>) request.getHeaders().get("Authorization");
|
||||
assertThat(authHeaders.size()).isEqualTo(1);
|
||||
assertThat(authHeaders.get(0)).isEqualTo("Bearer oidc.token");
|
||||
assertThat(request.getConnectTimeout()).isEqualTo(REQUEST_TIMEOUT_MS);
|
||||
assertThat(request.getReadTimeout()).isEqualTo(REQUEST_TIMEOUT_MS);
|
||||
verify(httpRequestInitializer).initialize(request);
|
||||
verifyNoMoreInteractions(httpRequestInitializer);
|
||||
// No OAuth header.
|
||||
factory =
|
||||
RequestFactoryModule.provideHttpRequestFactory(credentialsBundle, "clientId", false);
|
||||
request = factory.buildGetRequest(new GenericUrl("http://localhost"));
|
||||
assertThat(request.getHeaders().get("Proxy-Authorization")).isEqualTo("Bearer oidc.token");
|
||||
assertThat(request.getConnectTimeout()).isEqualTo(REQUEST_TIMEOUT_MS);
|
||||
assertThat(request.getReadTimeout()).isEqualTo(REQUEST_TIMEOUT_MS);
|
||||
verifyNoMoreInteractions(httpRequestInitializer);
|
||||
} finally {
|
||||
RegistryConfig.CONFIG_SETTINGS.get().gcpProject.isLocal = origIsLocal;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import google.registry.model.console.UserRoles;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeResponse;
|
||||
|
@ -55,8 +54,7 @@ public class ConsoleDomainGetActionTest {
|
|||
void testSuccess_fullJsonRepresentation() {
|
||||
ConsoleDomainGetAction action =
|
||||
createAction(
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(
|
||||
new UserRoles.Builder()
|
||||
|
@ -85,7 +83,8 @@ public class ConsoleDomainGetActionTest {
|
|||
|
||||
@Test
|
||||
void testFailure_appAuth() {
|
||||
ConsoleDomainGetAction action = createAction(AuthResult.create(AuthLevel.APP), "exists.tld");
|
||||
ConsoleDomainGetAction action =
|
||||
createAction(AuthResult.createApp("service@registry.example"), "exists.tld");
|
||||
action.run();
|
||||
assertThat(RESPONSE.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
||||
}
|
||||
|
@ -94,8 +93,7 @@ public class ConsoleDomainGetActionTest {
|
|||
void testFailure_wrongTypeOfUser() {
|
||||
ConsoleDomainGetAction action =
|
||||
createAction(
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(mock(com.google.appengine.api.users.User.class), false)),
|
||||
"exists.tld");
|
||||
action.run();
|
||||
|
@ -106,8 +104,7 @@ public class ConsoleDomainGetActionTest {
|
|||
void testFailure_noAccessToRegistrar() {
|
||||
ConsoleDomainGetAction action =
|
||||
createAction(
|
||||
AuthResult.create(
|
||||
AuthLevel.USER, UserAuthInfo.create(createUser(new UserRoles.Builder().build()))),
|
||||
AuthResult.createUser(UserAuthInfo.create(createUser(new UserRoles.Builder().build()))),
|
||||
"exists.tld");
|
||||
action.run();
|
||||
assertThat(RESPONSE.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
|
||||
|
@ -117,8 +114,7 @@ public class ConsoleDomainGetActionTest {
|
|||
void testFailure_nonexistentDomain() {
|
||||
ConsoleDomainGetAction action =
|
||||
createAction(
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(createUser(new UserRoles.Builder().setIsAdmin(true).build()))),
|
||||
"nonexistent.tld");
|
||||
action.run();
|
||||
|
|
|
@ -24,7 +24,6 @@ import google.registry.model.console.UserRoles;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import java.io.IOException;
|
||||
|
@ -50,8 +49,7 @@ class ConsoleUserDataActionTest {
|
|||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||
.build();
|
||||
|
||||
ConsoleUserDataAction action =
|
||||
createAction(AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user)));
|
||||
ConsoleUserDataAction action = createAction(AuthResult.createUser(UserAuthInfo.create(user)));
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
|
||||
Map jsonObject = GSON.fromJson(response.getPayload(), Map.class);
|
||||
|
@ -63,8 +61,7 @@ class ConsoleUserDataActionTest {
|
|||
void testFailure_notAConsoleUser() throws IOException {
|
||||
ConsoleUserDataAction action =
|
||||
createAction(
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
new com.google.appengine.api.users.User(
|
||||
"JohnDoe@theregistrar.com", "theregistrar.com"),
|
||||
|
|
|
@ -38,7 +38,6 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
|||
import google.registry.request.Action;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.DeterministicStringGenerator;
|
||||
import google.registry.testing.FakeResponse;
|
||||
|
@ -108,8 +107,7 @@ class RegistrarsActionTest {
|
|||
RegistrarsAction action =
|
||||
createAction(
|
||||
Action.Method.GET,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(
|
||||
new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_LEAD).build()))));
|
||||
|
@ -129,8 +127,7 @@ class RegistrarsActionTest {
|
|||
RegistrarsAction action =
|
||||
createAction(
|
||||
Action.Method.GET,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()))));
|
||||
action.run();
|
||||
|
@ -151,8 +148,7 @@ class RegistrarsActionTest {
|
|||
RegistrarsAction action =
|
||||
createAction(
|
||||
Action.Method.POST,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(createUser(new UserRoles.Builder().setIsAdmin(true).build()))));
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
|
||||
|
@ -180,8 +176,7 @@ class RegistrarsActionTest {
|
|||
RegistrarsAction action =
|
||||
createAction(
|
||||
Action.Method.POST,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(new UserRoles.Builder().setIsAdmin(true).build()))));
|
||||
action.run();
|
||||
|
@ -200,8 +195,7 @@ class RegistrarsActionTest {
|
|||
RegistrarsAction action =
|
||||
createAction(
|
||||
Action.Method.POST,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(createUser(new UserRoles.Builder().setIsAdmin(true).build()))));
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
|
||||
|
@ -215,8 +209,7 @@ class RegistrarsActionTest {
|
|||
RegistrarsAction action =
|
||||
createAction(
|
||||
Action.Method.GET,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(
|
||||
new UserRoles.Builder()
|
||||
|
|
|
@ -37,7 +37,6 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
|||
import google.registry.request.Action;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.ui.server.registrar.RegistrarConsoleModule;
|
||||
|
@ -103,8 +102,7 @@ class ContactActionTest {
|
|||
ContactAction action =
|
||||
createAction(
|
||||
Action.Method.GET,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()))),
|
||||
testRegistrar.getRegistrarId(),
|
||||
|
@ -121,8 +119,7 @@ class ContactActionTest {
|
|||
ContactAction action =
|
||||
createAction(
|
||||
Action.Method.GET,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()))),
|
||||
testRegistrar.getRegistrarId(),
|
||||
|
@ -137,8 +134,7 @@ class ContactActionTest {
|
|||
ContactAction action =
|
||||
createAction(
|
||||
Action.Method.POST,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()))),
|
||||
testRegistrar.getRegistrarId(),
|
||||
|
@ -160,8 +156,7 @@ class ContactActionTest {
|
|||
ContactAction action =
|
||||
createAction(
|
||||
Action.Method.POST,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()))),
|
||||
testRegistrar.getRegistrarId(),
|
||||
|
@ -186,8 +181,7 @@ class ContactActionTest {
|
|||
ContactAction action =
|
||||
createAction(
|
||||
Action.Method.POST,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()))),
|
||||
testRegistrar.getRegistrarId(),
|
||||
|
@ -208,8 +202,7 @@ class ContactActionTest {
|
|||
ContactAction action =
|
||||
createAction(
|
||||
Action.Method.POST,
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(
|
||||
new UserRoles.Builder()
|
||||
|
|
|
@ -35,7 +35,6 @@ import google.registry.model.registrar.Registrar;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.FakeClock;
|
||||
|
@ -92,8 +91,7 @@ class SecurityActionTest {
|
|||
clock.setTo(DateTime.parse("2020-11-01T00:00:00Z"));
|
||||
SecurityAction action =
|
||||
createAction(
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
createUser(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()))),
|
||||
testRegistrar.getRegistrarId());
|
||||
|
|
|
@ -33,7 +33,6 @@ import google.registry.model.registrar.Registrar;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.Role;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
|
@ -127,8 +126,7 @@ public class WhoisRegistrarFieldsActionTest {
|
|||
void testFailure_noAccessToRegistrar() throws Exception {
|
||||
Registrar newRegistrar = Registrar.loadByRegistrarIdCached("NewRegistrar").get();
|
||||
AuthResult onlyTheRegistrar =
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.example")
|
||||
|
@ -147,8 +145,7 @@ public class WhoisRegistrarFieldsActionTest {
|
|||
}
|
||||
|
||||
private AuthResult defaultUserAuth() {
|
||||
return AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
return AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.example")
|
||||
|
|
|
@ -37,7 +37,6 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
|
@ -93,7 +92,7 @@ public final class ConsoleOteSetupActionTest {
|
|||
ImmutableSetMultimap.of("unused", AuthenticatedRegistrarAccessor.Role.ADMIN));
|
||||
action.userService = UserServiceFactory.getUserService();
|
||||
action.xsrfTokenManager = new XsrfTokenManager(new FakeClock(), action.userService);
|
||||
action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
||||
action.authResult = AuthResult.createUser(UserAuthInfo.create(user, false));
|
||||
action.sendEmailUtils =
|
||||
new SendEmailUtils(
|
||||
new InternetAddress("outgoing@registry.example"),
|
||||
|
|
|
@ -37,7 +37,6 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
|
@ -93,7 +92,7 @@ final class ConsoleRegistrarCreatorActionTest {
|
|||
ImmutableSetMultimap.of("unused", AuthenticatedRegistrarAccessor.Role.ADMIN));
|
||||
action.userService = UserServiceFactory.getUserService();
|
||||
action.xsrfTokenManager = new XsrfTokenManager(new FakeClock(), action.userService);
|
||||
action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
||||
action.authResult = AuthResult.createUser(UserAuthInfo.create(user, false));
|
||||
action.sendEmailUtils =
|
||||
new SendEmailUtils(
|
||||
new InternetAddress("outgoing@registry.example"),
|
||||
|
|
|
@ -32,7 +32,6 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
|
@ -78,7 +77,7 @@ class ConsoleUiActionTest {
|
|||
action.xsrfTokenManager = new XsrfTokenManager(new FakeClock(), action.userService);
|
||||
action.method = Method.GET;
|
||||
action.paramClientId = Optional.empty();
|
||||
action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
||||
action.authResult = AuthResult.createUser(UserAuthInfo.create(user, false));
|
||||
action.analyticsConfig = ImmutableMap.of("googleAnalyticsId", "sampleId");
|
||||
|
||||
action.registrarAccessor =
|
||||
|
|
|
@ -44,7 +44,6 @@ import google.registry.request.JsonActionRunner;
|
|||
import google.registry.request.JsonResponse;
|
||||
import google.registry.request.ResponseImpl;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
|
@ -113,8 +112,7 @@ public abstract class RegistrarSettingsActionTestCase {
|
|||
gmailClient);
|
||||
action.registrarConsoleMetrics = new RegistrarConsoleMetrics();
|
||||
action.authResult =
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(new User("user@email.com", "email.com", "12345"), false));
|
||||
action.certificateChecker =
|
||||
new CertificateChecker(
|
||||
|
|
|
@ -40,7 +40,6 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.FakeClock;
|
||||
|
@ -75,7 +74,7 @@ final class RegistryLockGetActionTest {
|
|||
void beforeEach() {
|
||||
user = userFromRegistrarPoc(makeRegistrarContact3());
|
||||
fakeClock.setTo(DateTime.parse("2000-06-08T22:00:00.0Z"));
|
||||
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
||||
authResult = AuthResult.createUser(UserAuthInfo.create(user, false));
|
||||
accessor =
|
||||
AuthenticatedRegistrarAccessor.createForTesting(
|
||||
ImmutableSetMultimap.of(
|
||||
|
@ -109,7 +108,7 @@ final class RegistryLockGetActionTest {
|
|||
.build())
|
||||
.build();
|
||||
|
||||
action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser));
|
||||
action.authResult = AuthResult.createUser(UserAuthInfo.create(consoleUser));
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
|
||||
assertThat(GSON.fromJson(response.getPayload(), Map.class))
|
||||
|
@ -336,7 +335,7 @@ final class RegistryLockGetActionTest {
|
|||
persistResource(makeRegistrar2().asBuilder().setRegistryLockAllowed(false).build());
|
||||
// disallow the other user
|
||||
persistResource(makeRegistrarContact2().asBuilder().setLoginEmailAddress(null).build());
|
||||
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, true));
|
||||
authResult = AuthResult.createUser(UserAuthInfo.create(user, true));
|
||||
accessor =
|
||||
AuthenticatedRegistrarAccessor.createForTesting(
|
||||
ImmutableSetMultimap.of(
|
||||
|
@ -364,7 +363,7 @@ final class RegistryLockGetActionTest {
|
|||
void testSuccess_linkedToLoginContactEmail() {
|
||||
// Note that the email address is case-insensitive.
|
||||
user = new User("marla.singer@crr.com", "crr.com", user.getUserId());
|
||||
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
||||
authResult = AuthResult.createUser(UserAuthInfo.create(user, false));
|
||||
action =
|
||||
new RegistryLockGetAction(
|
||||
Method.GET, response, accessor, authResult, Optional.of("TheRegistrar"));
|
||||
|
|
|
@ -45,7 +45,6 @@ import google.registry.request.JsonActionRunner;
|
|||
import google.registry.request.JsonResponse;
|
||||
import google.registry.request.ResponseImpl;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.Role;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
|
@ -115,8 +114,7 @@ final class RegistryLockPostActionTest {
|
|||
when(mockRequest.getServerName()).thenReturn("registrarconsole.tld");
|
||||
|
||||
action =
|
||||
createAction(
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithLockPermission, false)));
|
||||
createAction(AuthResult.createUser(UserAuthInfo.create(userWithLockPermission, false)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -154,9 +152,7 @@ final class RegistryLockPostActionTest {
|
|||
saveRegistryLock(
|
||||
createLock().asBuilder().isSuperuser(true).setLockCompletionTime(clock.nowUtc()).build());
|
||||
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
|
||||
action =
|
||||
createAction(
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true)));
|
||||
action = createAction(AuthResult.createUser(UserAuthInfo.create(userWithoutPermission, true)));
|
||||
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
|
||||
// we should still email the admin user's email address
|
||||
assertSuccess(response, "unlock", "johndoe@theregistrar.com");
|
||||
|
@ -166,8 +162,7 @@ final class RegistryLockPostActionTest {
|
|||
void testSuccess_linkedToLoginEmail() throws Exception {
|
||||
userWithLockPermission = new User("Marla.Singer@crr.com", "crr.com");
|
||||
action =
|
||||
createAction(
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithLockPermission, false)));
|
||||
createAction(AuthResult.createUser(UserAuthInfo.create(userWithLockPermission, false)));
|
||||
Map<String, ?> response = action.handleJsonRequest(lockRequest());
|
||||
assertSuccess(response, "lock", "Marla.Singer.RegistryLock@crr.com");
|
||||
}
|
||||
|
@ -205,18 +200,14 @@ final class RegistryLockPostActionTest {
|
|||
@Test
|
||||
void testSuccess_adminUser() throws Exception {
|
||||
// Admin user should be able to lock/unlock regardless -- and we use the admin user's email
|
||||
action =
|
||||
createAction(
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true)));
|
||||
action = createAction(AuthResult.createUser(UserAuthInfo.create(userWithoutPermission, true)));
|
||||
Map<String, ?> response = action.handleJsonRequest(lockRequest());
|
||||
assertSuccess(response, "lock", "johndoe@theregistrar.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_adminUser_doesNotRequirePassword() throws Exception {
|
||||
action =
|
||||
createAction(
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true)));
|
||||
action = createAction(AuthResult.createUser(UserAuthInfo.create(userWithoutPermission, true)));
|
||||
Map<String, ?> response =
|
||||
action.handleJsonRequest(
|
||||
ImmutableMap.of(
|
||||
|
@ -239,8 +230,7 @@ final class RegistryLockPostActionTest {
|
|||
.build())
|
||||
.setRegistryLockPassword("hi")
|
||||
.build();
|
||||
AuthResult consoleAuthResult =
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser));
|
||||
AuthResult consoleAuthResult = AuthResult.createUser(UserAuthInfo.create(consoleUser));
|
||||
action = createAction(consoleAuthResult);
|
||||
Map<String, ?> response = action.handleJsonRequest(lockRequest());
|
||||
assertSuccess(response, "lock", "johndoe@theregistrar.com");
|
||||
|
@ -253,8 +243,7 @@ final class RegistryLockPostActionTest {
|
|||
.setEmailAddress("johndoe@theregistrar.com")
|
||||
.setUserRoles(new UserRoles.Builder().setIsAdmin(true).build())
|
||||
.build();
|
||||
AuthResult consoleAuthResult =
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser));
|
||||
AuthResult consoleAuthResult = AuthResult.createUser(UserAuthInfo.create(consoleUser));
|
||||
action = createAction(consoleAuthResult);
|
||||
Map<String, Object> requestMapWithoutPassword =
|
||||
ImmutableMap.of(
|
||||
|
@ -286,7 +275,7 @@ final class RegistryLockPostActionTest {
|
|||
@Test
|
||||
void testFailure_unauthorizedRegistrarId() {
|
||||
AuthResult authResult =
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithLockPermission, false));
|
||||
AuthResult.createUser(UserAuthInfo.create(userWithLockPermission, false));
|
||||
action = createAction(authResult, ImmutableSet.of("TheRegistrar"));
|
||||
Map<String, ?> response =
|
||||
action.handleJsonRequest(
|
||||
|
@ -358,9 +347,7 @@ final class RegistryLockPostActionTest {
|
|||
|
||||
@Test
|
||||
void testFailure_notEnabledForRegistrarPoc() {
|
||||
action =
|
||||
createAction(
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, false)));
|
||||
action = createAction(AuthResult.createUser(UserAuthInfo.create(userWithoutPermission, false)));
|
||||
Map<String, ?> response =
|
||||
action.handleJsonRequest(
|
||||
ImmutableMap.of(
|
||||
|
@ -453,8 +440,7 @@ final class RegistryLockPostActionTest {
|
|||
.build())
|
||||
.setRegistryLockPassword("hi")
|
||||
.build();
|
||||
AuthResult consoleAuthResult =
|
||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser));
|
||||
AuthResult consoleAuthResult = AuthResult.createUser(UserAuthInfo.create(consoleUser));
|
||||
action = createAction(consoleAuthResult);
|
||||
Map<String, ?> response =
|
||||
action.handleJsonRequest(
|
||||
|
|
|
@ -43,7 +43,6 @@ import google.registry.model.tld.Tld;
|
|||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.AuthSettings.AuthLevel;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
|
@ -132,7 +131,7 @@ final class RegistryLockVerifyActionTest {
|
|||
|
||||
@Test
|
||||
void testSuccess_adminLock_createsOnlyHistoryEntry() {
|
||||
action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, true));
|
||||
action.authResult = AuthResult.createUser(UserAuthInfo.create(user, true));
|
||||
saveRegistryLock(createLock().asBuilder().isSuperuser(true).build());
|
||||
|
||||
action.run();
|
||||
|
@ -332,7 +331,7 @@ final class RegistryLockVerifyActionTest {
|
|||
stringGenerator, "adminreg", cloudTasksHelper.getTestCloudTasksUtils()),
|
||||
lockVerificationCode,
|
||||
isLock);
|
||||
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
||||
authResult = AuthResult.createUser(UserAuthInfo.create(user, false));
|
||||
action.req = request;
|
||||
action.response = response;
|
||||
action.authResult = authResult;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
PATH CLASS METHODS OK AUTH_METHODS MIN USER_POLICY
|
||||
/_dr/epp EppTlsAction POST n API APP PUBLIC
|
||||
/_dr/epp EppTlsAction POST n API APP ADMIN
|
||||
/console-api/domain ConsoleDomainGetAction GET n API,LEGACY USER PUBLIC
|
||||
/console-api/registrars RegistrarsAction GET,POST n API,LEGACY USER PUBLIC
|
||||
/console-api/settings/contacts ContactAction GET,POST n API,LEGACY USER PUBLIC
|
||||
|
@ -13,4 +13,4 @@ PATH CLASS METHODS OK AUT
|
|||
/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC
|
||||
/registry-lock-get RegistryLockGetAction GET n API,LEGACY USER PUBLIC
|
||||
/registry-lock-post RegistryLockPostAction POST n API,LEGACY USER PUBLIC
|
||||
/registry-lock-verify RegistryLockVerifyAction GET n API,LEGACY NONE PUBLIC
|
||||
/registry-lock-verify RegistryLockVerifyAction GET n API,LEGACY NONE PUBLIC
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
PATH CLASS METHODS OK AUTH_METHODS MIN USER_POLICY
|
||||
/_dr/whois WhoisAction POST n API APP PUBLIC
|
||||
/_dr/whois WhoisAction POST n API APP ADMIN
|
||||
/check CheckApiAction GET n API,LEGACY NONE PUBLIC
|
||||
/rdap/autnum/(*) RdapAutnumAction GET,HEAD n API,LEGACY NONE PUBLIC
|
||||
/rdap/domain/(*) RdapDomainAction GET,HEAD n API,LEGACY NONE PUBLIC
|
||||
|
|
|
@ -88,8 +88,7 @@ gSuite:
|
|||
|
||||
For fully-featured production environments that need the full range of features
|
||||
(e.g. RDE, correct contact information on the registrar console, etc.) you will
|
||||
need to specify more settings. The `nomulus-config-production-sample.yaml` file
|
||||
contains an exhaustive list of all settings to override.
|
||||
need to specify more settings.
|
||||
|
||||
From a code perspective, all configuration settings ultimately come through the
|
||||
[`RegistryConfig`][registry-config] class. This includes a Dagger module called
|
||||
|
|
|
@ -134,16 +134,16 @@ takes a couple of minutes.
|
|||
### Setup Nomulus
|
||||
|
||||
After terraform completes, it outputs some information, among which is the
|
||||
client id of the service account created for the proxy. This needs to be added
|
||||
to the Nomulus configuration file so that Nomulus accepts traffic from the
|
||||
email address of the service account created for the proxy. This needs to be
|
||||
added to the Nomulus configuration file so that Nomulus accepts traffic from the
|
||||
proxy. Edit the following section in
|
||||
`java/google/registry/config/files/nomulus-config-<env>.yaml` and redeploy
|
||||
Nomulus:
|
||||
|
||||
```yaml
|
||||
oAuth:
|
||||
allowedOauthClientIds:
|
||||
- <client_id>
|
||||
auth:
|
||||
allowedServiceAccountEmails:
|
||||
- <email address>
|
||||
```
|
||||
|
||||
### Setup nameservers
|
||||
|
@ -304,15 +304,15 @@ $ gcloud iam service-accounts keys create proxy-key.json --iam-account \
|
|||
|
||||
A `proxy-key.json` file will be created inside the current working directory.
|
||||
|
||||
The `client_id` inside the key file needs to be added to the Nomulus
|
||||
The service account email address needs to be added to the Nomulus
|
||||
configuration file so that Nomulus accepts the OAuth tokens generated for this
|
||||
service account. Add its value to
|
||||
`java/google/registry/config/files/nomulus-config-<env>.yaml`:
|
||||
|
||||
```yaml
|
||||
oAuth:
|
||||
allowedOauthClientIds:
|
||||
- <client_id>
|
||||
auth:
|
||||
allowedServiceAccountEmails:
|
||||
- <email address>
|
||||
```
|
||||
|
||||
Redeploy Nomulus for the change to take effect.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue