diff --git a/opentech/apply/users/tests/factories.py b/opentech/apply/users/tests/factories.py
index 8db74b40f779c61361dc8f2b05e6805015b70cb5..ea11d35ec695ddcbff5333b98b14f357ad616271 100644
--- a/opentech/apply/users/tests/factories.py
+++ b/opentech/apply/users/tests/factories.py
@@ -1,5 +1,8 @@
+import uuid
+
 from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Group
+from django.utils.text import slugify
 
 import factory
 
@@ -18,7 +21,7 @@ class UserFactory(factory.DjangoModelFactory):
     class Meta:
         model = get_user_model()
 
-    email = factory.Sequence('email{}@email.com'.format)
+    email = factory.LazyAttribute(lambda o: '{}+{}@email.com'.format(slugify(o.full_name), uuid.uuid4()))
     full_name = factory.Faker('name')
     password = factory.PostGenerationMethodCall('set_password', 'defaultpassword')
 
diff --git a/opentech/apply/users/tests/test_views.py b/opentech/apply/users/tests/test_views.py
index 044a9566de15344b6d99487cfd18c2c462ac36d8..a62923d8a8ea701beadb2564f810b8a62c6182ac 100644
--- a/opentech/apply/users/tests/test_views.py
+++ b/opentech/apply/users/tests/test_views.py
@@ -3,7 +3,12 @@ from django.test import override_settings, TestCase
 from django.urls import reverse
 
 from opentech.apply.utils.testing.tests import BaseViewTestCase
-from .factories import OAuthUserFactory, StaffFactory, UserFactory
+from .factories import (
+    OAuthUserFactory,
+    StaffFactory,
+    SuperUserFactory,
+    UserFactory,
+)
 
 
 @override_settings(ROOT_URLCONF='opentech.apply.urls')
@@ -58,3 +63,47 @@ class TestPasswordReset(BaseViewTestCase):
         self.assertRedirects(response, self.url(None, view_name='password_reset_done'))
         self.assertEqual(len(mail.outbox), 1)
         self.assertIn('https://testserver/account/password/reset/confirm', mail.outbox[0].body)
+
+
+@override_settings(ROOT_URLCONF='opentech.apply.urls')
+class TestBecome(TestCase):
+    def setUp(self):
+        self.staff = StaffFactory()
+        self.user = UserFactory()
+        self.superuser = SuperUserFactory()
+
+    def become_request(self, user, target):
+        self.client.force_login(user)
+        url = reverse('users:become')
+        response = self.client.post(url, {'user': target.pk}, follow=True, secure=True)
+        return response
+
+    def test_staff_can_become_user(self):
+        response = self.become_request(self.staff, self.user)
+        self.assertEqual(response.status_code, 200)
+
+    def test_staff_cannot_become_superuser(self):
+        response = self.become_request(self.staff, self.superuser)
+        self.assertEqual(response.status_code, 403)
+
+    def test_superuser_can_become_staff(self):
+        response = self.become_request(self.superuser, self.staff)
+        self.assertEqual(response.status_code, 200)
+
+    def test_superuser_cannot_become_superuser(self):
+        other_superuser = SuperUserFactory()
+        response = self.become_request(self.superuser, other_superuser)
+        self.assertEqual(response.status_code, 403)
+
+    def test_user_cannot_become_staff(self):
+        response = self.become_request(self.user, self.staff)
+        self.assertEqual(response.status_code, 403)
+
+    def test_user_cannot_become_other_user(self):
+        other_user = UserFactory()
+        response = self.become_request(self.user, other_user)
+        self.assertEqual(response.status_code, 403)
+
+    def test_user_cannot_become_superuser(self):
+        response = self.become_request(self.user, self.superuser)
+        self.assertEqual(response.status_code, 403)
diff --git a/opentech/apply/users/views.py b/opentech/apply/users/views.py
index 86b54c1bd48823b171b537486f88b7ebbe5a4fe9..fdc63e60a2fd6867f82035fdb638ee08833d87d9 100644
--- a/opentech/apply/users/views.py
+++ b/opentech/apply/users/views.py
@@ -5,6 +5,7 @@ from django.contrib.auth.decorators import login_required
 from django.contrib.auth.forms import AdminPasswordChangeForm
 from django.contrib.auth.tokens import PasswordResetTokenGenerator
 from django.contrib.auth.views import SuccessURLAllowedHostsMixin
+from django.core.exceptions import PermissionDenied
 from django.http import HttpResponseRedirect
 from django.shortcuts import redirect, render, resolve_url
 from django.template.response import TemplateResponse
@@ -93,8 +94,15 @@ class AccountView(UpdateView):
 
 @login_required()
 def become(request):
-    id = request.POST['user']
+    if not request.user.is_apply_staff:
+        raise PermissionDenied()
+
+    id = request.POST.get('user')
     if request.POST and id:
+        target_user = User.objects.get(pk=id)
+        if target_user.is_superuser:
+            raise PermissionDenied()
+
         return login_with_id(request, id)
     return redirect('users:account')