Add more tests to new authentication framework

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=148459400
This commit is contained in:
mountford 2017-02-24 07:37:15 -08:00 committed by Ben McIlwain
parent dd400f30f5
commit 3ac74fa449
4 changed files with 353 additions and 28 deletions

View file

@ -14,36 +14,37 @@
package google.registry.request.auth;
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import com.google.appengine.api.oauth.OAuthServiceFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.request.Action;
import google.registry.testing.AppEngineRule;
import google.registry.testing.ExceptionRule;
import google.registry.testing.FakeOAuthService;
import google.registry.testing.FakeUserService;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.junit.runners.JUnit4;
/** Unit tests for {@link RequestAuthenticator}. */
@RunWith(MockitoJUnitRunner.class)
@RunWith(JUnit4.class)
public class RequestAuthenticatorTest {
private FakeUserService fakeUserService;
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().build();
@Mock
private UserService mockUserService;
@Mock
private HttpServletRequest req;
@Rule
public final ExceptionRule thrown = new ExceptionRule();
@Action(
path = "/auth/none",
@ -69,6 +70,15 @@ public class RequestAuthenticatorTest {
method = Action.Method.GET)
public static class AuthAnyUserAnyMethod {}
@Action(
path = "/auth/anyUserNoLegacy",
auth = @Auth(
methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API},
minimumLevel = AuthLevel.USER,
userPolicy = Auth.UserPolicy.PUBLIC),
method = Action.Method.GET)
public static class AuthAnyUserNoLegacy {}
@Action(
path = "/auth/adminUserAnyMethod",
auth = @Auth(
@ -76,25 +86,61 @@ public class RequestAuthenticatorTest {
minimumLevel = AuthLevel.USER,
userPolicy = Auth.UserPolicy.ADMIN),
method = Action.Method.GET)
public static class AuthAdminUserAnyMethod {
}
public static class AuthAdminUserAnyMethod {}
private final User testUser = new User("test@example.com", "test@example.com");
@Action(
path = "/auth/noMethods",
auth = @Auth(methods = {}))
public static class AuthNoMethods {}
@Before
public void before() throws Exception {
fakeUserService = new FakeUserService();
}
@Action(
path = "/auth/missingInternal",
auth = @Auth(methods = {Auth.AuthMethod.API, Auth.AuthMethod.LEGACY}))
public static class AuthMissingInternal {}
private static RequestAuthenticator createRequestAuthenticator(UserService userService) {
@Action(
path = "/auth/wrongMethodOrdering",
auth = @Auth(methods = {Auth.AuthMethod.API, Auth.AuthMethod.INTERNAL}))
public static class AuthWrongMethodOrdering {}
@Action(
path = "/auth/duplicateMethods",
auth = @Auth(methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API, Auth.AuthMethod.API}))
public static class AuthDuplicateMethods {}
@Action(
path = "/auth/internalWithUser",
auth = @Auth(methods = {Auth.AuthMethod.INTERNAL}, minimumLevel = AuthLevel.USER))
public static class AuthInternalWithUser {}
@Action(
path = "/auth/wronglyIgnoringUser",
auth = @Auth(
methods = {Auth.AuthMethod.INTERNAL, Auth.AuthMethod.API},
userPolicy = Auth.UserPolicy.IGNORED))
public static class AuthWronglyIgnoringUser {}
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 FakeOAuthService fakeOAuthService = new FakeOAuthService(
false /* isOAuthEnabled */,
testUser,
false /* isUserAdmin */,
"test-client-id",
ImmutableList.of("test-scope1", "test-scope2", "nontest-scope"));
private RequestAuthenticator createRequestAuthenticator(UserService userService) {
return new RequestAuthenticator(
new AppEngineInternalAuthenticationMechanism(),
ImmutableList.<AuthenticationMechanism>of(
new OAuthAuthenticationMechanism(
OAuthServiceFactory.getOAuthService(),
ImmutableSet.of("https://www.googleapis.com/auth/userinfo.email"),
ImmutableSet.of("https://www.googleapis.com/auth/userinfo.email"),
ImmutableSet.of("proxy-client-id", "regtool-client-id"))),
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));
}
@ -149,13 +195,14 @@ public class RequestAuthenticatorTest {
@Test
public void testAnyUserAnyMethod_success() throws Exception {
fakeUserService.setUser(testUser, false);
fakeUserService.setUser(testUser, false /* isAdmin */);
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserAnyMethod.class);
assertThat(authResult).isPresent();
assertThat(authResult.get()).isNotNull();
assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
assertThat(authResult.get().userAuthInfo()).isPresent();
assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser);
assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse();
assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isAbsent();
}
@ -167,21 +214,168 @@ public class RequestAuthenticatorTest {
@Test
public void testAdminUserAnyMethod_notAdminUser() throws Exception {
fakeUserService.setUser(testUser, false);
fakeUserService.setUser(testUser, false /* isAdmin */);
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAdminUserAnyMethod.class);
assertThat(authResult).isAbsent();
}
@Test
public void testAdminUserAnyMethod_success() throws Exception {
fakeUserService.setUser(testUser, true);
fakeUserService.setUser(testUser, true /* isAdmin */);
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAdminUserAnyMethod.class);
assertThat(authResult).isPresent();
assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
assertThat(authResult.get().userAuthInfo()).isPresent();
assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser);
assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isTrue();
assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isAbsent();
}
// TODO(mountford) Add more tests for OAuth, misconfiguration, etc., either here or separately
@Test
public void testOAuth_success() throws Exception {
fakeOAuthService.setUser(testUser);
fakeOAuthService.setOAuthEnabled(true);
when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class);
assertThat(authResult).isPresent();
assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
assertThat(authResult.get().userAuthInfo()).isPresent();
assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser);
assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse();
assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent();
assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes())
.containsAllOf("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");
}
@Test
public void testOAuthAdmin_success() throws Exception {
fakeOAuthService.setUser(testUser);
fakeOAuthService.setUserAdmin(true);
fakeOAuthService.setOAuthEnabled(true);
when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class);
assertThat(authResult).isPresent();
assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
assertThat(authResult.get().userAuthInfo()).isPresent();
assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser);
assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isTrue();
assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent();
assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes())
.containsAllOf("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");
}
@Test
public void testOAuthMissingAuthenticationToken_failure() throws Exception {
fakeOAuthService.setUser(testUser);
fakeOAuthService.setOAuthEnabled(true);
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class);
assertThat(authResult).isAbsent();
}
@Test
public void testOAuthClientIdMismatch_failure() throws Exception {
fakeOAuthService.setUser(testUser);
fakeOAuthService.setOAuthEnabled(true);
fakeOAuthService.setClientId("wrong-client-id");
when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class);
assertThat(authResult).isAbsent();
}
@Test
public void testOAuthNoScopes_failure() throws Exception {
fakeOAuthService.setUser(testUser);
fakeOAuthService.setOAuthEnabled(true);
fakeOAuthService.setAuthorizedScopes();
when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class);
assertThat(authResult).isAbsent();
}
@Test
public void testOAuthMissingScope_failure() throws Exception {
fakeOAuthService.setUser(testUser);
fakeOAuthService.setOAuthEnabled(true);
fakeOAuthService.setAuthorizedScopes("test-scope1", "test-scope3");
when(req.getHeader(AUTHORIZATION)).thenReturn("Bearer TOKEN");
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class);
assertThat(authResult).isAbsent();
}
@Test
public void testOAuthExtraScope_success() throws Exception {
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, AuthAnyUserNoLegacy.class);
assertThat(authResult).isPresent();
assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER);
assertThat(authResult.get().userAuthInfo()).isPresent();
assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser);
assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse();
assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent();
assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes())
.containsAllOf("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
public void testAnyUserNoLegacy_failureWithLegacyUser() throws Exception {
fakeUserService.setUser(testUser, false /* isAdmin */);
Optional<AuthResult> authResult = runTest(fakeUserService, AuthAnyUserNoLegacy.class);
assertThat(authResult).isAbsent();
}
@Test
public void testNoMethods_failure() throws Exception {
thrown.expect(IllegalArgumentException.class, "Must specify at least one auth method");
runTest(fakeUserService, AuthNoMethods.class);
}
@Test
public void testMissingInternal_failure() throws Exception {
thrown.expect(IllegalArgumentException.class,
"Auth method INTERNAL must always be specified, and as the first auth method");
runTest(fakeUserService, AuthMissingInternal.class);
}
@Test
public void testWrongMethodOrdering_failure() throws Exception {
thrown.expect(IllegalArgumentException.class,
"Auth methods must be unique and strictly in order - INTERNAL, API, LEGACY");
runTest(fakeUserService, AuthWrongMethodOrdering.class);
}
@Test
public void testDuplicateMethods_failure() throws Exception {
thrown.expect(IllegalArgumentException.class,
"Auth methods must be unique and strictly in order - INTERNAL, API, LEGACY");
runTest(fakeUserService, AuthDuplicateMethods.class);
}
@Test
public void testInternalWithUser_failure() throws Exception {
thrown.expect(IllegalArgumentException.class,
"Actions with only INTERNAL auth may not require USER auth level");
runTest(fakeUserService, AuthInternalWithUser.class);
}
@Test
public void testWronglyIgnoringUser_failure() throws Exception {
thrown.expect(IllegalArgumentException.class,
"Actions with auth methods beyond INTERNAL must not specify the IGNORED user policy");
runTest(fakeUserService, AuthWronglyIgnoringUser.class);
}
}