mirror of
https://github.com/google/nomulus.git
synced 2025-05-15 08:57:12 +02:00
Refactor a few new XsrfTokenManager methods
Followup to comments on [] ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=148792464
This commit is contained in:
parent
822cbc0494
commit
726e925b4a
5 changed files with 28 additions and 61 deletions
|
@ -68,24 +68,13 @@ public final class XsrfTokenManager {
|
||||||
.asBytes());
|
.asBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate an xsrf token for a given scope using the email of the logged in user or else no user.
|
|
||||||
*
|
|
||||||
* <p>If there is no user, the entire xsrf check becomes basically a no-op, but that's ok because
|
|
||||||
* any callback that doesn't have a user shouldn't be able to access any per-user resources
|
|
||||||
* anyways.
|
|
||||||
*
|
|
||||||
* <p>The scope (or lack thereof) is passed to {@link #encodeToken}. Use of a scope in xsrf tokens
|
|
||||||
* is deprecated; instead, use the no-argument version.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public String generateTokenWithCurrentUser(@Nullable String scope) {
|
|
||||||
return generateTokenSub(scope, getLoggedInEmailOrEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate an xsrf token for a given scope and user.
|
* Generate an xsrf token for a given scope and user.
|
||||||
*
|
*
|
||||||
|
* <p>If there is no user (email is an empty string), the entire xsrf check becomes basically a
|
||||||
|
* no-op, but that's ok because any callback that doesn't have a user shouldn't be able to access
|
||||||
|
* any per-user resources anyways.
|
||||||
|
*
|
||||||
* <p>The scope (or lack thereof) is passed to {@link #encodeToken}. Use of a scope in xsrf tokens
|
* <p>The scope (or lack thereof) is passed to {@link #encodeToken}. Use of a scope in xsrf tokens
|
||||||
* is deprecated; instead, use the no-argument version.
|
* is deprecated; instead, use the no-argument version.
|
||||||
*/
|
*/
|
||||||
|
@ -97,18 +86,13 @@ public final class XsrfTokenManager {
|
||||||
|
|
||||||
/** Generate an xsrf token for a given user. */
|
/** Generate an xsrf token for a given user. */
|
||||||
public String generateToken(String email) {
|
public String generateToken(String email) {
|
||||||
return generateTokenSub(null, email);
|
return generateToken(null, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getLoggedInEmailOrEmpty() {
|
private String getLoggedInEmailOrEmpty() {
|
||||||
return userService.isUserLoggedIn() ? userService.getCurrentUser().getEmail() : "";
|
return userService.isUserLoggedIn() ? userService.getCurrentUser().getEmail() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateTokenSub(@Nullable String scope, String email) {
|
|
||||||
long now = clock.nowUtc().getMillis();
|
|
||||||
return Joiner.on(':').join(encodeToken(now, scope, email), now);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate an xsrf token, given the scope it was used for.
|
* Validate an xsrf token, given the scope it was used for.
|
||||||
*
|
*
|
||||||
|
|
|
@ -383,7 +383,7 @@ public final class RequestHandlerTest {
|
||||||
userService.setUser(testUser, false);
|
userService.setUser(testUser, false);
|
||||||
when(req.getMethod()).thenReturn("POST");
|
when(req.getMethod()).thenReturn("POST");
|
||||||
when(req.getHeader("X-CSRF-Token"))
|
when(req.getHeader("X-CSRF-Token"))
|
||||||
.thenReturn(xsrfTokenManager.generateTokenWithCurrentUser("vampire"));
|
.thenReturn(xsrfTokenManager.generateToken("vampire", testUser.getEmail()));
|
||||||
when(req.getRequestURI()).thenReturn("/safe-sloth");
|
when(req.getRequestURI()).thenReturn("/safe-sloth");
|
||||||
handler.handleRequest(req, rsp);
|
handler.handleRequest(req, rsp);
|
||||||
verify(safeSlothTask).run();
|
verify(safeSlothTask).run();
|
||||||
|
@ -394,7 +394,7 @@ public final class RequestHandlerTest {
|
||||||
userService.setUser(testUser, false);
|
userService.setUser(testUser, false);
|
||||||
when(req.getMethod()).thenReturn("POST");
|
when(req.getMethod()).thenReturn("POST");
|
||||||
when(req.getHeader("X-CSRF-Token"))
|
when(req.getHeader("X-CSRF-Token"))
|
||||||
.thenReturn(xsrfTokenManager.generateTokenWithCurrentUser("blood"));
|
.thenReturn(xsrfTokenManager.generateToken("blood", testUser.getEmail()));
|
||||||
when(req.getRequestURI()).thenReturn("/safe-sloth");
|
when(req.getRequestURI()).thenReturn("/safe-sloth");
|
||||||
handler.handleRequest(req, rsp);
|
handler.handleRequest(req, rsp);
|
||||||
verify(rsp).sendError(403, "Invalid X-CSRF-Token");
|
verify(rsp).sendError(403, "Invalid X-CSRF-Token");
|
||||||
|
|
|
@ -220,7 +220,7 @@ public class RequestAuthenticatorTest {
|
||||||
public void testAnyUserAnyMethod_success() throws Exception {
|
public void testAnyUserAnyMethod_success() throws Exception {
|
||||||
fakeUserService.setUser(testUser, false /* isAdmin */);
|
fakeUserService.setUser(testUser, false /* isAdmin */);
|
||||||
when(req.getHeader(XsrfTokenManager.X_CSRF_TOKEN))
|
when(req.getHeader(XsrfTokenManager.X_CSRF_TOKEN))
|
||||||
.thenReturn(xsrfTokenManager.generateTokenWithCurrentUser("console"));
|
.thenReturn(xsrfTokenManager.generateToken("console", testUser.getEmail()));
|
||||||
|
|
||||||
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserAnyMethod.class);
|
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserAnyMethod.class);
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ public class RequestAuthenticatorTest {
|
||||||
public void testAdminUserAnyMethod_success() throws Exception {
|
public void testAdminUserAnyMethod_success() throws Exception {
|
||||||
fakeUserService.setUser(testUser, true /* isAdmin */);
|
fakeUserService.setUser(testUser, true /* isAdmin */);
|
||||||
when(req.getHeader(XsrfTokenManager.X_CSRF_TOKEN))
|
when(req.getHeader(XsrfTokenManager.X_CSRF_TOKEN))
|
||||||
.thenReturn(xsrfTokenManager.generateTokenWithCurrentUser("console"));
|
.thenReturn(xsrfTokenManager.generateToken("console", testUser.getEmail()));
|
||||||
|
|
||||||
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAdminUserAnyMethod.class);
|
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAdminUserAnyMethod.class);
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,12 @@ package google.registry.security;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
|
|
||||||
|
import com.google.appengine.api.users.User;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.FakeUserService;
|
import google.registry.testing.FakeUserService;
|
||||||
import google.registry.testing.InjectRule;
|
import google.registry.testing.InjectRule;
|
||||||
import google.registry.testing.UserInfo;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -33,31 +33,30 @@ import org.mockito.runners.MockitoJUnitRunner;
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class XsrfTokenManagerTest {
|
public class XsrfTokenManagerTest {
|
||||||
|
|
||||||
FakeClock clock = new FakeClock(START_OF_TIME);
|
|
||||||
FakeUserService userService = new FakeUserService();
|
|
||||||
|
|
||||||
XsrfTokenManager xsrfTokenManager = new XsrfTokenManager(clock, userService);
|
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public final AppEngineRule appEngine = AppEngineRule.builder()
|
public final AppEngineRule appEngine = AppEngineRule.builder()
|
||||||
.withDatastore()
|
.withDatastore()
|
||||||
.withUserService(UserInfo.createAdmin("a@example.com", "user1"))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public InjectRule inject = new InjectRule();
|
public InjectRule inject = new InjectRule();
|
||||||
|
|
||||||
|
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 XsrfTokenManager xsrfTokenManager = new XsrfTokenManager(clock, userService);
|
||||||
|
|
||||||
|
String realToken;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void init() {
|
public void init() {
|
||||||
// inject.setStaticField(XsrfTokenManager.class, "clock", clock);
|
userService.setUser(testUser, false);
|
||||||
|
realToken = xsrfTokenManager.generateToken("console", testUser.getEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess() {
|
public void testSuccess() {
|
||||||
assertThat(
|
assertThat(xsrfTokenManager.validateToken(realToken, "console")).isTrue();
|
||||||
xsrfTokenManager.validateToken(
|
|
||||||
xsrfTokenManager.generateTokenWithCurrentUser("console"), "console"))
|
|
||||||
.isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -72,17 +71,13 @@ public class XsrfTokenManagerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpired() {
|
public void testExpired() {
|
||||||
String token = xsrfTokenManager.generateTokenWithCurrentUser("console");
|
|
||||||
clock.setTo(START_OF_TIME.plusDays(2));
|
clock.setTo(START_OF_TIME.plusDays(2));
|
||||||
assertThat(xsrfTokenManager.validateToken(token, "console")).isFalse();
|
assertThat(xsrfTokenManager.validateToken(realToken, "console")).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTimestampTamperedWith() {
|
public void testTimestampTamperedWith() {
|
||||||
String encodedPart =
|
String encodedPart = Splitter.on(':').splitToList(realToken).get(0);
|
||||||
Splitter.on(':')
|
|
||||||
.splitToList(xsrfTokenManager.generateTokenWithCurrentUser("console"))
|
|
||||||
.get(0);
|
|
||||||
long tamperedTimestamp = clock.nowUtc().plusMillis(1).getMillis();
|
long tamperedTimestamp = clock.nowUtc().plusMillis(1).getMillis();
|
||||||
assertThat(xsrfTokenManager.validateToken(encodedPart + ":" + tamperedTimestamp, "console"))
|
assertThat(xsrfTokenManager.validateToken(encodedPart + ":" + tamperedTimestamp, "console"))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
@ -91,32 +86,25 @@ public class XsrfTokenManagerTest {
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentUser() {
|
public void testDifferentUser() {
|
||||||
assertThat(xsrfTokenManager
|
assertThat(xsrfTokenManager
|
||||||
.validateToken(xsrfTokenManager.generateToken("console", "b@example.com"), "console"))
|
.validateToken(xsrfTokenManager.generateToken("console", "eve@example.com"), "console"))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentScope() {
|
public void testDifferentScope() {
|
||||||
assertThat(
|
assertThat(xsrfTokenManager.validateToken(realToken, "foobar")).isFalse();
|
||||||
xsrfTokenManager.validateToken(
|
|
||||||
xsrfTokenManager.generateTokenWithCurrentUser("console"), "foobar"))
|
|
||||||
.isFalse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNullScope() {
|
public void testNullScope() {
|
||||||
assertThat(
|
String tokenWithNullScope = xsrfTokenManager.generateToken(null, testUser.getEmail());
|
||||||
xsrfTokenManager.validateToken(
|
assertThat(xsrfTokenManager.validateToken(tokenWithNullScope, null)).isTrue();
|
||||||
xsrfTokenManager.generateTokenWithCurrentUser(null), null))
|
|
||||||
.isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test checks that the server side will pass when we switch the client to use a null scope.
|
// This test checks that the server side will pass when we switch the client to use a null scope.
|
||||||
@Test
|
@Test
|
||||||
public void testNullScopePassesWhenTestedWithNonNullScope() {
|
public void testNullScopePassesWhenTestedWithNonNullScope() {
|
||||||
assertThat(
|
String tokenWithNullScope = xsrfTokenManager.generateToken(null, testUser.getEmail());
|
||||||
xsrfTokenManager.validateToken(
|
assertThat(xsrfTokenManager.validateToken(tokenWithNullScope, "console")).isTrue();
|
||||||
xsrfTokenManager.generateTokenWithCurrentUser(null), "console"))
|
|
||||||
.isTrue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailDispla
|
||||||
import static google.registry.security.JsonHttpTestUtils.createJsonPayload;
|
import static google.registry.security.JsonHttpTestUtils.createJsonPayload;
|
||||||
import static google.registry.security.JsonHttpTestUtils.createJsonResponseSupplier;
|
import static google.registry.security.JsonHttpTestUtils.createJsonResponseSupplier;
|
||||||
import static google.registry.util.ResourceUtils.readResourceUtf8;
|
import static google.registry.util.ResourceUtils.readResourceUtf8;
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.appengine.api.modules.ModulesService;
|
import com.google.appengine.api.modules.ModulesService;
|
||||||
|
@ -32,10 +31,8 @@ import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.request.JsonActionRunner;
|
import google.registry.request.JsonActionRunner;
|
||||||
import google.registry.request.JsonResponse;
|
import google.registry.request.JsonResponse;
|
||||||
import google.registry.request.ResponseImpl;
|
import google.registry.request.ResponseImpl;
|
||||||
import google.registry.security.XsrfTokenManager;
|
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.FakeUserService;
|
|
||||||
import google.registry.testing.InjectRule;
|
import google.registry.testing.InjectRule;
|
||||||
import google.registry.util.SendEmailService;
|
import google.registry.util.SendEmailService;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
@ -92,7 +89,6 @@ public class RegistrarSettingsActionTestCase {
|
||||||
final StringWriter writer = new StringWriter();
|
final StringWriter writer = new StringWriter();
|
||||||
final Supplier<Map<String, Object>> json = createJsonResponseSupplier(writer);
|
final Supplier<Map<String, Object>> json = createJsonResponseSupplier(writer);
|
||||||
final FakeClock clock = new FakeClock(DateTime.parse("2014-01-01T00:00:00Z"));
|
final FakeClock clock = new FakeClock(DateTime.parse("2014-01-01T00:00:00Z"));
|
||||||
final XsrfTokenManager xsrfTokenManager = new XsrfTokenManager(clock, new FakeUserService());
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
@ -113,7 +109,6 @@ public class RegistrarSettingsActionTestCase {
|
||||||
when(req.getMethod()).thenReturn("POST");
|
when(req.getMethod()).thenReturn("POST");
|
||||||
when(rsp.getWriter()).thenReturn(new PrintWriter(writer));
|
when(rsp.getWriter()).thenReturn(new PrintWriter(writer));
|
||||||
when(req.getContentType()).thenReturn("application/json");
|
when(req.getContentType()).thenReturn("application/json");
|
||||||
when(req.getHeader(eq("X-CSRF-Token"))).thenReturn(xsrfTokenManager.generateTokenWithCurrentUser("console"));
|
|
||||||
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of("op", "read")));
|
when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of("op", "read")));
|
||||||
when(sessionUtils.isLoggedIn()).thenReturn(true);
|
when(sessionUtils.isLoggedIn()).thenReturn(true);
|
||||||
when(sessionUtils.checkRegistrarConsoleLogin(req)).thenReturn(true);
|
when(sessionUtils.checkRegistrarConsoleLogin(req)).thenReturn(true);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue