Add XSRF protection to legacy authentication mechanism

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=148689952
This commit is contained in:
mountford 2017-02-27 13:53:10 -08:00 committed by Ben McIlwain
parent a5932c0fc3
commit c7a62e9b98
12 changed files with 227 additions and 56 deletions

View file

@ -42,6 +42,7 @@ abstract class Route {
}
boolean shouldXsrfProtect(Action.Method requestMethod) {
return action().xsrfProtection() && requestMethod != Action.Method.GET;
return action().xsrfProtection()
&& (requestMethod != Action.Method.GET) && (requestMethod != Action.Method.HEAD);
}
}

View file

@ -17,6 +17,7 @@ package google.registry.request.auth;
import static google.registry.request.auth.AuthLevel.APP;
import static google.registry.request.auth.AuthLevel.NONE;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
/**
@ -56,6 +57,9 @@ public class AppEngineInternalAuthenticationMechanism implements AuthenticationM
// As defined in the App Engine request header documentation.
private static final String QUEUE_NAME_HEADER = "X-AppEngine-QueueName";
@Inject
public AppEngineInternalAuthenticationMechanism() {}
@Override
public AuthResult authenticate(HttpServletRequest request) {
if (request.getHeader(QUEUE_NAME_HEADER) == null) {

View file

@ -16,12 +16,9 @@ package google.registry.request.auth;
import com.google.appengine.api.oauth.OAuthService;
import com.google.appengine.api.oauth.OAuthServiceFactory;
import com.google.appengine.api.users.UserService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import dagger.Module;
import dagger.Provides;
import google.registry.config.RegistryConfig.Config;
/**
* Dagger module for authentication routines.
@ -29,28 +26,12 @@ import google.registry.config.RegistryConfig.Config;
@Module
public class AuthModule {
/** Provides the internal authentication mechanism. */
@Provides
AppEngineInternalAuthenticationMechanism provideAppEngineInternalAuthenticationMechanism() {
return new AppEngineInternalAuthenticationMechanism();
}
/** Provides the custom authentication mechanisms (including OAuth). */
@Provides
ImmutableList<AuthenticationMechanism> provideApiAuthenticationMechanisms(
OAuthService oauthService,
@Config("availableOauthScopes") ImmutableSet<String> availableOauthScopes,
@Config("requiredOauthScopes") ImmutableSet<String> requiredOauthScopes,
@Config("allowedOauthClientIds") ImmutableSet<String> allowedOauthClientIds) {
OAuthAuthenticationMechanism oauthAuthenticationMechanism) {
return ImmutableList.<AuthenticationMechanism>of(
new OAuthAuthenticationMechanism(
oauthService, availableOauthScopes, requiredOauthScopes, allowedOauthClientIds));
}
/** Provides the legacy authentication mechanism. */
@Provides
LegacyAuthenticationMechanism provideLegacyAuthenticationMechanism(UserService userService) {
return new LegacyAuthenticationMechanism(userService);
oauthAuthenticationMechanism);
}
/** Provides the OAuthService instance. */

View file

@ -9,6 +9,7 @@ java_library(
srcs = glob(["*.java"]),
deps = [
"//java/google/registry/config",
"//java/google/registry/security",
"//java/google/registry/util",
"@com_google_appengine_api_1_0_sdk",
"@com_google_auto_value",

View file

@ -14,11 +14,15 @@
package google.registry.request.auth;
import static com.google.common.base.Strings.nullToEmpty;
import static google.registry.request.auth.AuthLevel.NONE;
import static google.registry.request.auth.AuthLevel.USER;
import static google.registry.security.XsrfTokenManager.X_CSRF_TOKEN;
import com.google.appengine.api.users.UserService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import google.registry.security.XsrfTokenManager;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
@ -27,25 +31,36 @@ import javax.servlet.http.HttpServletRequest;
*
* <p>Just use the values returned by UserService.
*/
// TODO(mountford) Add XSRF protection here or elsewhere, from RequestHandler
public class LegacyAuthenticationMechanism implements AuthenticationMechanism {
private final UserService userService;
private final XsrfTokenManager xsrfTokenManager;
/** HTTP methods which are considered safe, and do not require XSRF protection. */
private static final ImmutableSet<String> SAFE_METHODS = ImmutableSet.of("GET", "HEAD");
@VisibleForTesting
@Inject
public LegacyAuthenticationMechanism(UserService userService) {
public LegacyAuthenticationMechanism(UserService userService, XsrfTokenManager xsrfTokenManager) {
this.userService = userService;
this.xsrfTokenManager = xsrfTokenManager;
}
@Override
public AuthResult authenticate(HttpServletRequest request) {
if (!userService.isUserLoggedIn()) {
return AuthResult.create(NONE);
} else {
return AuthResult.create(
USER,
UserAuthInfo.create(userService.getCurrentUser(), userService.isUserAdmin()));
}
if (!SAFE_METHODS.contains(request.getMethod())
&& !xsrfTokenManager.validateToken(
nullToEmpty(request.getHeader(X_CSRF_TOKEN)),
"console")) { // hard-coded for now; in the long run, this will be removed
return AuthResult.create(NONE);
}
return AuthResult.create(
USER,
UserAuthInfo.create(userService.getCurrentUser(), userService.isUserAdmin()));
}
}