mirror of
https://github.com/google/nomulus.git
synced 2025-05-15 08:57:12 +02:00
Make first pass at new OAuth-aware server authentication framework
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=147081745
This commit is contained in:
parent
cb215adac3
commit
c41f5bb31c
17 changed files with 327 additions and 22 deletions
|
@ -23,6 +23,7 @@ import com.google.common.base.Optional;
|
|||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
@ -904,6 +905,44 @@ public final class RegistryConfig {
|
|||
return CONFIG_SETTINGS.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the OAuth scopes to check for on access tokens.
|
||||
*
|
||||
* <p>This list should be a superset of the required OAuth scope set provided below.
|
||||
*
|
||||
* <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>https://www.googleapis.com/auth/appengine.apis</li>
|
||||
* <li>https://www.googleapis.com/auth/cloud-platform</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Provides
|
||||
@Config("availableOauthScopes")
|
||||
public static ImmutableSet<String> provideAvailableOauthScopes() {
|
||||
return ImmutableSet.of("https://www.googleapis.com/auth/userinfo.email");
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the required OAuth scopes for simply authenticating.
|
||||
*
|
||||
* <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.
|
||||
*/
|
||||
@Provides
|
||||
@Config("requiredOauthScopes")
|
||||
public static ImmutableSet<String> provideRequiredOauthScopes() {
|
||||
return ImmutableSet.of("https://www.googleapis.com/auth/userinfo.email");
|
||||
}
|
||||
|
||||
/** Provides the allowed OAuth client IDs (could be multibinding). */
|
||||
@Provides
|
||||
@Config("allowedOauthClientIds")
|
||||
public static ImmutableSet<String> provideAllowedOauthClientIds() {
|
||||
return ImmutableSet.of("PUT.YOUR.PROXY.CLIENT.ID.HERE", "PUT.YOUR.REGTOOL.CLIENT.ID.HERE");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the help path for the RDAP terms of service.
|
||||
*
|
||||
|
|
|
@ -31,6 +31,7 @@ java_library(
|
|||
"//java/google/registry/rde/imports",
|
||||
"//java/google/registry/request",
|
||||
"//java/google/registry/request:modules",
|
||||
"//java/google/registry/request/auth",
|
||||
"//java/google/registry/tmch",
|
||||
"//java/google/registry/util",
|
||||
"@com_google_appengine_api_1_0_sdk",
|
||||
|
|
|
@ -39,6 +39,7 @@ import google.registry.request.Modules.URLFetchServiceModule;
|
|||
import google.registry.request.Modules.UrlFetchTransportModule;
|
||||
import google.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.util.SystemClock.SystemClockModule;
|
||||
import google.registry.util.SystemSleeper.SystemSleeperModule;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -48,6 +49,7 @@ import javax.inject.Singleton;
|
|||
@Component(
|
||||
modules = {
|
||||
AppIdentityCredentialModule.class,
|
||||
AuthModule.class,
|
||||
BackendRequestComponentModule.class,
|
||||
BigqueryModule.class,
|
||||
ConfigModule.class,
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.module.backend;
|
|||
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import google.registry.request.RequestHandler;
|
||||
import google.registry.request.auth.RequestAuthenticator;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
||||
|
@ -25,7 +26,8 @@ public class BackendRequestHandler
|
|||
|
||||
@Inject BackendRequestHandler(
|
||||
Provider<BackendRequestComponent.Builder> componentBuilderProvider,
|
||||
UserService userService) {
|
||||
super(componentBuilderProvider, userService);
|
||||
UserService userService,
|
||||
RequestAuthenticator requestAuthenticator) {
|
||||
super(componentBuilderProvider, userService, requestAuthenticator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ java_library(
|
|||
"//java/google/registry/rdap",
|
||||
"//java/google/registry/request",
|
||||
"//java/google/registry/request:modules",
|
||||
"//java/google/registry/request/auth",
|
||||
"//java/google/registry/ui",
|
||||
"//java/google/registry/ui/server/registrar",
|
||||
"//java/google/registry/util",
|
||||
|
|
|
@ -29,6 +29,7 @@ import google.registry.request.Modules.ModulesServiceModule;
|
|||
import google.registry.request.Modules.UrlFetchTransportModule;
|
||||
import google.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.ui.ConsoleConfigModule;
|
||||
import google.registry.util.SystemClock.SystemClockModule;
|
||||
import google.registry.util.SystemSleeper.SystemSleeperModule;
|
||||
|
@ -39,6 +40,7 @@ import javax.inject.Singleton;
|
|||
@Component(
|
||||
modules = {
|
||||
AppIdentityCredentialModule.class,
|
||||
AuthModule.class,
|
||||
BraintreeModule.class,
|
||||
ConfigModule.class,
|
||||
ConsoleConfigModule.class,
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.module.frontend;
|
|||
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import google.registry.request.RequestHandler;
|
||||
import google.registry.request.auth.RequestAuthenticator;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
||||
|
@ -25,7 +26,8 @@ public class FrontendRequestHandler
|
|||
|
||||
@Inject FrontendRequestHandler(
|
||||
Provider<FrontendRequestComponent.Builder> componentBuilderProvider,
|
||||
UserService userService) {
|
||||
super(componentBuilderProvider, userService);
|
||||
UserService userService,
|
||||
RequestAuthenticator requestAuthenticator) {
|
||||
super(componentBuilderProvider, userService, requestAuthenticator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ java_library(
|
|||
"//java/google/registry/monitoring/whitebox",
|
||||
"//java/google/registry/request",
|
||||
"//java/google/registry/request:modules",
|
||||
"//java/google/registry/request/auth",
|
||||
"//java/google/registry/tools/server",
|
||||
"//java/google/registry/tools/server/javascrap",
|
||||
"//java/google/registry/util",
|
||||
|
|
|
@ -33,6 +33,7 @@ import google.registry.request.Modules.ModulesServiceModule;
|
|||
import google.registry.request.Modules.UrlFetchTransportModule;
|
||||
import google.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.request.auth.AuthModule;
|
||||
import google.registry.util.SystemClock.SystemClockModule;
|
||||
import google.registry.util.SystemSleeper.SystemSleeperModule;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -42,6 +43,7 @@ import javax.inject.Singleton;
|
|||
@Component(
|
||||
modules = {
|
||||
AppIdentityCredentialModule.class,
|
||||
AuthModule.class,
|
||||
ConfigModule.class,
|
||||
CustomLogicFactoryModule.class,
|
||||
DatastoreServiceModule.class,
|
||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.module.tools;
|
|||
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import google.registry.request.RequestHandler;
|
||||
import google.registry.request.auth.RequestAuthenticator;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
||||
|
@ -25,7 +26,8 @@ public class ToolsRequestHandler
|
|||
|
||||
@Inject ToolsRequestHandler(
|
||||
Provider<ToolsRequestComponent.Builder> componentBuilderProvider,
|
||||
UserService userService) {
|
||||
super(componentBuilderProvider, userService);
|
||||
UserService userService,
|
||||
RequestAuthenticator requestAuthenticator) {
|
||||
super(componentBuilderProvider, userService, requestAuthenticator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
package google.registry.request;
|
||||
|
||||
import google.registry.request.auth.Auth;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
@ -61,4 +62,7 @@ public @interface Action {
|
|||
* {@code web.xml} with {@code <role-name>*</role-name>}.
|
||||
*/
|
||||
boolean requireLogin() default false;
|
||||
|
||||
/** Authentication settings. */
|
||||
Auth auth() default @Auth;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ java_library(
|
|||
exclude = ["Modules.java"],
|
||||
),
|
||||
deps = [
|
||||
"//java/google/registry/request/auth",
|
||||
"//java/google/registry/security",
|
||||
"//java/google/registry/util",
|
||||
"@com_google_appengine_api_1_0_sdk",
|
||||
|
|
|
@ -27,6 +27,8 @@ import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
|
|||
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import com.google.common.base.Optional;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.RequestAuthenticator;
|
||||
import google.registry.util.FormattingLogger;
|
||||
import google.registry.util.TypeUtils.TypeInstantiator;
|
||||
import java.io.IOException;
|
||||
|
@ -77,6 +79,7 @@ public class RequestHandler<C, B extends RequestComponentBuilder<C, B>> {
|
|||
private final Router router;
|
||||
private final Provider<B> requestComponentBuilderProvider;
|
||||
private final UserService userService;
|
||||
private final RequestAuthenticator requestAuthenticator;
|
||||
|
||||
/**
|
||||
* Constructor for subclasses to create a new request handler for a specific request component.
|
||||
|
@ -89,22 +92,33 @@ public class RequestHandler<C, B extends RequestComponentBuilder<C, B>> {
|
|||
* be used to construct new instances of the request component (with the required
|
||||
* request-derived modules provided by this class)
|
||||
* @param userService an instance of the App Engine UserService API
|
||||
* @param requestAuthenticator an instance of the RequestAuthenticator class
|
||||
*/
|
||||
protected RequestHandler(Provider<B> requestComponentBuilderProvider, UserService userService) {
|
||||
this(null, requestComponentBuilderProvider, userService);
|
||||
protected RequestHandler(
|
||||
Provider<B> requestComponentBuilderProvider,
|
||||
UserService userService,
|
||||
RequestAuthenticator requestAuthenticator) {
|
||||
this(null, requestComponentBuilderProvider, userService, requestAuthenticator);
|
||||
}
|
||||
|
||||
/** Creates a new RequestHandler with an explicit component class for test purposes. */
|
||||
public static <C, B extends RequestComponentBuilder<C, B>> RequestHandler<C, B> createForTest(
|
||||
Class<C> component, Provider<B> requestComponentBuilderProvider, UserService userService) {
|
||||
Class<C> component,
|
||||
Provider<B> requestComponentBuilderProvider,
|
||||
UserService userService,
|
||||
RequestAuthenticator requestAuthenticator) {
|
||||
return new RequestHandler<>(
|
||||
checkNotNull(component), requestComponentBuilderProvider, userService);
|
||||
checkNotNull(component),
|
||||
requestComponentBuilderProvider,
|
||||
userService,
|
||||
requestAuthenticator);
|
||||
}
|
||||
|
||||
private RequestHandler(
|
||||
@Nullable Class<C> component,
|
||||
Provider<B> requestComponentBuilderProvider,
|
||||
UserService userService) {
|
||||
UserService userService,
|
||||
RequestAuthenticator requestAuthenticator) {
|
||||
// If the component class isn't explicitly provided, infer it from the class's own typing.
|
||||
// This is safe only for use by subclasses of RequestHandler where the generic parameter is
|
||||
// preserved at runtime, so only expose that option via the protected constructor.
|
||||
|
@ -112,6 +126,7 @@ public class RequestHandler<C, B extends RequestComponentBuilder<C, B>> {
|
|||
component != null ? component : new TypeInstantiator<C>(getClass()){}.getExactType());
|
||||
this.requestComponentBuilderProvider = checkNotNull(requestComponentBuilderProvider);
|
||||
this.userService = checkNotNull(userService);
|
||||
this.requestAuthenticator = checkNotNull(requestAuthenticator);
|
||||
}
|
||||
|
||||
/** Runs the appropriate action for a servlet request. */
|
||||
|
@ -152,9 +167,16 @@ public class RequestHandler<C, B extends RequestComponentBuilder<C, B>> {
|
|||
rsp.sendError(SC_FORBIDDEN, "Invalid " + X_CSRF_TOKEN);
|
||||
return;
|
||||
}
|
||||
Optional<AuthResult> authResult =
|
||||
requestAuthenticator.authorize(route.get().action().auth(), req);
|
||||
if (!authResult.isPresent()) {
|
||||
rsp.sendError(SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build a new request component using any modules we've constructed by this point.
|
||||
C component = requestComponentBuilderProvider.get()
|
||||
.requestModule(new RequestModule(req, rsp))
|
||||
.requestModule(new RequestModule(req, rsp, authResult.get()))
|
||||
.build();
|
||||
// Apply the selected Route to the component to produce an Action instance, and run it.
|
||||
try {
|
||||
|
|
|
@ -26,6 +26,7 @@ import dagger.Module;
|
|||
import dagger.Provides;
|
||||
import google.registry.request.HttpException.BadRequestException;
|
||||
import google.registry.request.HttpException.UnsupportedMediaTypeException;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -40,10 +41,18 @@ public final class RequestModule {
|
|||
|
||||
private final HttpServletRequest req;
|
||||
private final HttpServletResponse rsp;
|
||||
private final AuthResult authResult;
|
||||
|
||||
public RequestModule(HttpServletRequest req, HttpServletResponse rsp) {
|
||||
public RequestModule(
|
||||
HttpServletRequest req, HttpServletResponse rsp) {
|
||||
this(req, rsp, AuthResult.NOT_AUTHENTICATED);
|
||||
}
|
||||
|
||||
public RequestModule(
|
||||
HttpServletRequest req, HttpServletResponse rsp, AuthResult authResult) {
|
||||
this.req = req;
|
||||
this.rsp = rsp;
|
||||
this.authResult = authResult;
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -66,6 +75,11 @@ public final class RequestModule {
|
|||
return rsp;
|
||||
}
|
||||
|
||||
@Provides
|
||||
AuthResult provideAuthResult() {
|
||||
return authResult;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@RequestPath
|
||||
static String provideRequestPath(HttpServletRequest req) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue