diff --git a/opentech/apply/users/decorators.py b/opentech/apply/users/decorators.py
new file mode 100644
index 0000000000000000000000000000000000000000..11539ef29a665407e74e55bfee226d0c8e0ec0b1
--- /dev/null
+++ b/opentech/apply/users/decorators.py
@@ -0,0 +1,20 @@
+from django.conf import settings
+from django.core.exceptions import PermissionDenied
+
+
+def require_oauth_whitelist(view_func):
+    """Simple decorator that limits the use of OAuth to the configure whitelisted domains"""
+    def decorated_view(request, *args, **kwargs):
+        user = request.user
+
+        try:
+            if settings.SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS:
+                for domain in settings.SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS:
+                    if user.email.endswith(f'@{domain}'):
+                        return view_func(request, *args, **kwargs)
+        except AttributeError:
+            raise PermissionDenied
+
+        raise PermissionDenied
+
+    return decorated_view
diff --git a/opentech/apply/users/templates/users/account.html b/opentech/apply/users/templates/users/account.html
index 725d615316bb18d3700f3dc45ed61a22253c7ad1..5873285edc434ff180aefffdfdc9a06d7745d72b 100644
--- a/opentech/apply/users/templates/users/account.html
+++ b/opentech/apply/users/templates/users/account.html
@@ -1,12 +1,17 @@
 {% extends 'base.html' %}
-{% load i18n %}
+{% load i18n users_tags %}
 
 {% block title %}Account{% endblock %}
 
 {% block content %}
 <h2>Welcome {{ user }}</h2>
 
-{% if show_change_password %}
+{% if show_change_password and not backends.associated %}
     <a href="{% url 'users:password_change' %}">{% trans "Change password" %}</a>
 {% endif %}
+
+{% can_use_oauth as show_oauth_link %}
+{% if show_oauth_link %}
+    <a href="{% url 'users:oauth' %}">{% trans "Manage OAuth" %}</a>
+{% endif %}
 {% endblock %}
diff --git a/opentech/apply/users/templates/users/oauth.html b/opentech/apply/users/templates/users/oauth.html
new file mode 100644
index 0000000000000000000000000000000000000000..312003dddfdb5167e71383632961c8a39fb873dd
--- /dev/null
+++ b/opentech/apply/users/templates/users/oauth.html
@@ -0,0 +1,41 @@
+{% extends 'base.html' %}
+{% load users_tags %}
+
+{% block title %}OAuth{% endblock %}
+
+{% block content %}
+<div class="social">
+    {% if backends.associated %}
+        <h3>Providers</h3>
+        <ul>
+        {% for association in backends.associated %}
+            <li>
+                {% if user.password %}
+                    <form id="{{ association.provider|backend_name }}-disconnect" class="disconnect-form col-md-2" action="{% url 'social:disconnect_individual' backend=association.provider association_id=association.id %}?next={% url "users:account" %}"
+                        method="post">
+                        <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
+                        <button class="btn btn-danger" name="{{ association.provider|backend_class }}">
+                            Disconnect {{ association.provider|backend_name }}
+                        </button>
+                    </form>
+                {% else %}
+                    {{ association.provider|backend_name }}
+                {% endif %}
+            </li>
+        {% endfor %}
+        </ul>
+    {% endif %}
+    {% if backends.not_associated %}
+        <h3>Available OAuth providers</h3>
+        <ul>
+        {% for backend in backends.not_associated %}
+            <li>
+                <a id="{{ name }}-button" class="col-md-2 btn btn-default" name="{{ backend }}" href="{% url 'social:begin' backend=backend %}">
+                    Associate with {{ backend|backend_name }}
+                </a>
+            </li>
+        {% endfor %}
+        </ul>
+    {% endif %}
+</div>
+{% endblock %}
diff --git a/opentech/apply/users/templatetags/__init__.py b/opentech/apply/users/templatetags/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/opentech/apply/users/templatetags/users_tags.py b/opentech/apply/users/templatetags/users_tags.py
new file mode 100644
index 0000000000000000000000000000000000000000..0125e89bd66bd3c76620b3185290045ec3545d94
--- /dev/null
+++ b/opentech/apply/users/templatetags/users_tags.py
@@ -0,0 +1,40 @@
+from django import template
+from django.conf import settings
+
+register = template.Library()
+
+
+@register.filter
+def backend_name(name):
+    return {
+        'google-oauth': 'Google OAuth',
+        'google-oauth2': 'Google OAuth',
+        'google-openidconnect': 'Google OpenId',
+        'facebook-app': 'Facebook',
+        'stackoverflow': 'Stack Overflow',
+        'yahoo-oauth': 'Yahoo',
+        'vimeo': 'Vimeo',
+        'linkedin-oauth2': 'LinkedIn OAuth',
+        'vk-oauth2': 'VK OAuth',
+        'live': 'Windows Live',
+    }.get(name, name)
+
+
+@register.filter
+def backend_class(backend):
+    return backend.replace('-', ' ')
+
+
+@register.simple_tag(takes_context=True)
+def can_use_oauth(context):
+    user = context.get('user')
+
+    try:
+        if settings.SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS:
+            for domain in settings.SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS:
+                if user.email.endswith(f'@{domain}'):
+                    return True
+    except AttributeError:
+        return False
+
+    return False
diff --git a/opentech/apply/users/urls.py b/opentech/apply/users/urls.py
index 4942e2dada305c2d44cd8b4df19f80b9d882ab6b..1fc074d79c5e3e79e3cba737a10a1915552ce18c 100644
--- a/opentech/apply/users/urls.py
+++ b/opentech/apply/users/urls.py
@@ -2,7 +2,7 @@ from django.conf.urls import url
 from django.contrib.auth import views as auth_views
 from django.urls import reverse_lazy
 
-from opentech.apply.users.views import account
+from opentech.apply.users.views import account, oauth
 
 urlpatterns = [
     url(r'^$', account, name='account'),
@@ -53,4 +53,5 @@ urlpatterns = [
         auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset/complete.html'),
         name='password_reset_complete'
     ),
+    url(r'^oauth$', oauth, name='oauth'),
 ]
diff --git a/opentech/apply/users/views.py b/opentech/apply/users/views.py
index c531b183ae221c1441c401f0f17f36ff2fe32980..c9bad14dfb283aa4c1c8caa5f2e769cf20708025 100644
--- a/opentech/apply/users/views.py
+++ b/opentech/apply/users/views.py
@@ -1,9 +1,12 @@
 from django.contrib.auth.decorators import login_required
 from django.shortcuts import render
+from django.template.response import TemplateResponse
 from django.urls import reverse_lazy
 
 from wagtail.wagtailadmin.views.account import password_management_enabled
 
+from .decorators import require_oauth_whitelist
+
 
 @login_required(login_url=reverse_lazy('users:login'))
 def account(request):
@@ -12,3 +15,13 @@ def account(request):
     return render(request, 'users/account.html', {
         'show_change_password': password_management_enabled() and request.user.has_usable_password(),
     })
+
+
+@login_required(login_url=reverse_lazy('users:login'))
+@require_oauth_whitelist
+def oauth(request):
+    """
+    Generic, empty view for the OAuth associations.
+    """
+
+    return TemplateResponse(request, 'users/oauth.html', {})