diff --git a/CHANGELOG b/CHANGELOG
index 43a4f0f2798b242b7e6d352d4954b073f211689c..6ba09e952bf6e62b3aa7967813b785c40399cfab 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,7 @@ v 7.13.0 (unreleased)
   - Rename "Design" profile settings page to "Preferences".
   - Allow users to customize their default Dashboard page.
   - Update ssl_ciphers in Nginx example to remove DHE settings. This will deny forward secrecy for Android 2.3.7, Java 6 and OpenSSL 0.9.8
+  - Admin can edit and remove user identities
   - Convert CRLF newlines to LF when committing using the web editor.
   - API request /projects/:project_id/merge_requests?state=closed will return only closed merge requests without merged one. If you need ones that were merged - use state=merged.  
   - Allow Administrators to filter the user list by those with or without Two-factor Authentication enabled.
diff --git a/app/controllers/admin/identities_controller.rb b/app/controllers/admin/identities_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d28614731f9211cf66fb1ef3af5e76a2c3fe972d
--- /dev/null
+++ b/app/controllers/admin/identities_controller.rb
@@ -0,0 +1,41 @@
+class Admin::IdentitiesController < Admin::ApplicationController
+  before_action :user
+  before_action :identity, except: :index
+
+  def index
+    @identities = @user.identities
+  end
+
+  def edit
+  end
+
+  def update
+    if @identity.update_attributes(identity_params)
+      redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully updated.'
+    else
+      render :edit
+    end
+  end
+
+  def destroy
+    if @identity.destroy
+      redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully removed.'
+    else
+      redirect_to admin_user_identities_path(@user), alert: 'Failed to remove user identity.'
+    end
+  end
+
+  protected
+
+  def user
+    @user ||= User.find_by!(username: params[:user_id])
+  end
+
+  def identity
+    @identity ||= user.identities.find(params[:id])
+  end
+
+  def identity_params
+    params.require(:identity).permit(:provider, :extern_uid)
+  end
+end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 2bc236871b0c6482789beb9d21ea501acf6a7c08..ec29c32065423d819f0562f81677a9c8e39ba29a 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -1,5 +1,5 @@
 class Admin::UsersController < Admin::ApplicationController
-  before_action :user, only: [:show, :edit, :update, :destroy]
+  before_action :user, except: [:index, :new, :create]
 
   def index
     @users = User.order_name_asc.filter(params[:filter])
@@ -9,8 +9,17 @@ class Admin::UsersController < Admin::ApplicationController
   end
 
   def show
+  end
+
+  def projects
     @personal_projects = user.personal_projects
     @joined_projects = user.projects.joined(@user)
+  end
+
+  def groups
+  end
+
+  def keys
     @keys = user.keys
   end
 
diff --git a/app/views/admin/identities/_form.html.haml b/app/views/admin/identities/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b405aa6e8e3fbd0d9b5ff571343e80890b303000
--- /dev/null
+++ b/app/views/admin/identities/_form.html.haml
@@ -0,0 +1,19 @@
+= form_for [:admin, @user, @identity], html: { class: 'form-horizontal fieldset-form' } do |f|
+  - if @identity.errors.any?
+    #error_explanation
+      .alert.alert-danger
+        - @identity.errors.full_messages.each do |msg|
+          %p= msg
+
+  .form-group
+    = f.label :provider, class: 'control-label'
+    .col-sm-10
+      = f.select :provider, Gitlab::OAuth::Provider.names, { allow_blank: false }, class: 'form-control'
+  .form-group
+    = f.label :extern_uid, "Identifier", class: 'control-label'
+    .col-sm-10
+      = f.text_field :extern_uid, required: true, class: 'form-control', required: true
+
+  .form-actions
+    = f.submit 'Save changes', class: "btn btn-save"
+
diff --git a/app/views/admin/identities/_identity.html.haml b/app/views/admin/identities/_identity.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..671c4fbc6774ab85500d231889fb441a74b6c4bf
--- /dev/null
+++ b/app/views/admin/identities/_identity.html.haml
@@ -0,0 +1,12 @@
+%tr
+  %td
+    = identity.provider
+  %td
+    = identity.extern_uid
+  %td
+    = link_to edit_admin_user_identity_path(@user, identity), class: 'btn btn-xs btn-grouped' do
+      Edit
+    = link_to [:admin, @user, identity], method: :delete,
+      class: 'btn btn-xs btn-danger',
+      data: { confirm: "Are you sure you want to remove this identity?" } do
+      Delete
diff --git a/app/views/admin/identities/edit.html.haml b/app/views/admin/identities/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..515d46b0f291cd9db5195e4c789beb466e8193e1
--- /dev/null
+++ b/app/views/admin/identities/edit.html.haml
@@ -0,0 +1,6 @@
+- page_title "Edit", @identity.provider, "Identities", @user.name, "Users"
+%h3.page-title
+  Edit identity for #{@user.name}
+%hr
+
+= render 'form'
diff --git a/app/views/admin/identities/index.html.haml b/app/views/admin/identities/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..ae57e3adc4d412271f1ac33b2abfc7f7b359035d
--- /dev/null
+++ b/app/views/admin/identities/index.html.haml
@@ -0,0 +1,13 @@
+- page_title "Identities", @user.name, "Users"
+= render 'admin/users/head'
+
+- if @identities.present?
+  %table.table
+    %thead
+      %tr
+        %th Provider
+        %th Identifier
+        %th
+    = render @identities
+- else
+  %h4 This user has no identities
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..9d5e934c8bafc622d43df9cb0b34f436975930f6
--- /dev/null
+++ b/app/views/admin/users/_head.html.haml
@@ -0,0 +1,23 @@
+%h3.page-title
+  = @user.name
+  - if @user.blocked?
+    %span.cred (Blocked)
+  - if @user.admin
+    %span.cred (Admin)
+
+  .pull-right
+    = link_to edit_admin_user_path(@user), class: "btn btn-grouped" do
+      %i.fa.fa-pencil-square-o
+      Edit
+%hr
+%ul.nav.nav-tabs
+  = nav_link(path: 'users#show') do
+    = link_to "Account", admin_user_path(@user)
+  = nav_link(path: 'users#groups') do
+    = link_to "Groups", groups_admin_user_path(@user)
+  = nav_link(path: 'users#projects') do
+    = link_to "Projects", projects_admin_user_path(@user)
+  = nav_link(path: 'users#keys') do
+    = link_to "SSH keys", keys_admin_user_path(@user)
+  = nav_link(controller: :identities) do
+    = link_to "Identities", admin_user_identities_path(@user)
diff --git a/app/views/admin/users/groups.html.haml b/app/views/admin/users/groups.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..dbecb7bbfd641578894ed8a33f6a1927e0c3e7c2
--- /dev/null
+++ b/app/views/admin/users/groups.html.haml
@@ -0,0 +1,19 @@
+- page_title "Groups", @user.name, "Users"
+= render 'admin/users/head'
+
+- if @user.group_members.present?
+  .panel.panel-default
+    .panel-heading Groups:
+    %ul.well-list
+      - @user.group_members.each do |group_member|
+        - group = group_member.group
+        %li.group_member
+          %span{class: ("list-item-name" unless group_member.owner?)}
+            %strong= link_to group.name, admin_group_path(group)
+          .pull-right
+            %span.light= group_member.human_access
+            - unless group_member.owner?
+              = link_to group_group_member_path(group, group_member), data: { confirm: remove_user_from_group_message(group, group_member) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
+                %i.fa.fa-times.fa-inverse
+- else
+  .nothing-here-block This user has no groups.
diff --git a/app/views/admin/users/keys.html.haml b/app/views/admin/users/keys.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..071107170825e0cae30a3d2983663b25e1a50cd0
--- /dev/null
+++ b/app/views/admin/users/keys.html.haml
@@ -0,0 +1,3 @@
+- page_title "Keys", @user.name, "Users"
+= render 'admin/users/head'
+= render 'profiles/keys/key_table', admin: true
diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..0d7a1a25a8043bef5bb20c2a06ce338c19c5ab46
--- /dev/null
+++ b/app/views/admin/users/projects.html.haml
@@ -0,0 +1,43 @@
+- page_title "Projects", @user.name, "Users"
+= render 'admin/users/head'
+
+- if @user.groups.any?
+  .panel.panel-default
+    .panel-heading Group projects
+    %ul.well-list
+      - @user.groups.each do |group|
+        %li
+          %strong= group.name
+          &ndash; access to
+          #{pluralize(group.projects.count, 'project')}
+
+.row
+  .col-md-6
+    - if @personal_projects.present?
+      = render 'users/projects', projects: @personal_projects
+    - else
+      .nothing-here-block This user has no personal projects.
+
+
+  .col-md-6
+    .panel.panel-default
+      .panel-heading Joined projects (#{@joined_projects.count})
+      %ul.well-list
+        - @joined_projects.sort_by(&:name_with_namespace).each do |project|
+          - member = project.team.find_member(@user.id)
+          %li.project_member
+            .list-item-name
+              = link_to admin_namespace_project_path(project.namespace, project), class: dom_class(project) do
+                = project.name_with_namespace
+
+            - if member
+              .pull-right
+                - if member.owner?
+                  %span.light Owner
+                - else
+                  %span.light= member.human_access
+
+                  - if member.respond_to? :project
+                    = link_to namespace_project_project_member_path(project.namespace, project, member), data: { confirm: remove_from_project_team_message(project, member) }, remote: true, method: :delete, class: "btn-xs btn btn-remove", title: 'Remove user from project' do
+                      %i.fa.fa-times
+
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 48cd22fc34b327626782fa19749fe26c238f8d44..2662b3569ec22fa3181aef61554a56939d166065 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -1,240 +1,154 @@
 - page_title @user.name, "Users"
-%h3.page-title
-  User:
-  = @user.name
-  - if @user.blocked?
-    %span.cred (Blocked)
-  - if @user.admin
-    %span.cred (Admin)
-
-  .pull-right
-    = link_to edit_admin_user_path(@user), class: "btn btn-grouped" do
-      %i.fa.fa-pencil-square-o
-      Edit
-%hr
-%ul.nav.nav-tabs
-  %li.active
-    %a{"data-toggle" => "tab", href: "#account"} Account
-  %li
-    %a{"data-toggle" => "tab", href: "#profile"} Profile
-  %li
-    %a{"data-toggle" => "tab", href: "#groups"} Groups
-  %li
-    %a{"data-toggle" => "tab", href: "#projects"} Projects
-  %li
-    %a{"data-toggle" => "tab", href: "#ssh-keys"} SSH keys
-
-.tab-content
-  #account.tab-pane.active
-    .row
-      .col-md-6
-        .panel.panel-default
-          .panel-heading
-            Account:
-          %ul.well-list
-            %li
-              %span.light Name:
-              %strong= @user.name
-            %li
-              %span.light Username:
-              %strong
-                = @user.username
-            %li
-              %span.light Email:
-              %strong
-                = mail_to @user.email
-            - @user.emails.each do |email|
-              %li
-                %span.light Secondary email:
-                %strong= email.email
-                = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-xs btn btn-remove pull-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
-                  %i.fa.fa-times
-
-            %li.two-factor-status
-              %span.light Two-factor Authentication:
-              %strong{class: @user.two_factor_enabled? ? 'cgreen' : 'cred'}
-                - if @user.two_factor_enabled?
-                  Enabled
-                - else
-                  Disabled
-
-            %li
-              %span.light Can create groups:
-              %strong
-                = @user.can_create_group ? "Yes" : "No"
-            %li
-              %span.light Personal projects limit:
-              %strong
-                = @user.projects_limit
-            %li
-              %span.light Member since:
-              %strong
-                = @user.created_at.stamp("Nov 12, 2031")
-            - if @user.confirmed_at
-              %li
-                %span.light Confirmed at:
-                %strong
-                  = @user.confirmed_at.stamp("Nov 12, 2031")
+= render 'admin/users/head'
+
+.row
+  .col-md-6
+    .panel.panel-default
+      .panel-heading
+        = @user.name
+      %ul.well-list
+        %li
+          = image_tag avatar_icon(@user.email, 60), class: "avatar s60"
+        %li
+          %span.light Profile page:
+          %strong
+            = link_to user_path(@user) do
+              = @user.username
+    = render 'users/profile', user: @user
+
+    .panel.panel-default
+      .panel-heading
+        Account:
+      %ul.well-list
+        %li
+          %span.light Name:
+          %strong= @user.name
+        %li
+          %span.light Username:
+          %strong
+            = @user.username
+        %li
+          %span.light Email:
+          %strong
+            = mail_to @user.email
+        - @user.emails.each do |email|
+          %li
+            %span.light Secondary email:
+            %strong= email.email
+            = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-xs btn btn-remove pull-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
+              %i.fa.fa-times
+
+        %li.two-factor-status
+          %span.light Two-factor Authentication:
+          %strong{class: @user.two_factor_enabled? ? 'cgreen' : 'cred'}
+            - if @user.two_factor_enabled?
+              Enabled
             - else
-              %li
-                %span.light Confirmed:
-                %strong.cred
-                  No
-
-            %li
-              %span.light Current sign-in at:
-              %strong
-                - if @user.current_sign_in_at
-                  = @user.current_sign_in_at.stamp("Nov 12, 2031")
-                - else
-                  never
-
-            %li
-              %span.light Last sign-in at:
-              %strong
-                - if @user.last_sign_in_at
-                  = @user.last_sign_in_at.stamp("Nov 12, 2031")
-                - else
-                  never
-
-            %li
-              %span.light Sign-in count:
-              %strong
-                = @user.sign_in_count
-
-            - if @user.ldap_user?
-              %li
-                %span.light LDAP uid:
-                %strong
-                  = @user.ldap_identity.extern_uid
-
-            - if @user.created_by
-              %li
-                %span.light Created by:
-                %strong
-                  = link_to @user.created_by.name, [:admin, @user.created_by]
-
-      .col-md-6
-        - unless @user == current_user
-          - if @user.blocked?
-            .panel.panel-info
-              .panel-heading
-                This user is blocked
-              .panel-body
-                %p Blocking user has the following effects:
-                %ul
-                  %li User will not be able to login
-                  %li User will not be able to access git repositories
-                  %li Personal projects will be left
-                  %li Owned groups will be left
-                %br
-                = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
-          - else
-            .panel.panel-warning
-              .panel-heading
-                Block this user
-              .panel-body
-                %p Blocking user has the following effects:
-                %ul
-                  %li User will not be able to login
-                  %li User will not be able to access git repositories
-                  %li User will be removed from joined projects and groups
-                  %li Personal projects will be left
-                  %li Owned groups will be left
-                %br
-                = link_to 'Block user', block_admin_user_path(@user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put, class: "btn btn-warning"
-
-          .panel.panel-danger
-            .panel-heading
-              Remove user
-            .panel-body
-              - if @user.can_be_removed?
-                %p Deleting a user has the following effects:
-                %ul
-                  %li All user content like authored issues, snippets, comments will be removed
-                  - rp = @user.personal_projects.count
-                  - unless rp.zero?
-                    %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
-                %br
-                = link_to 'Remove user', [:admin, @user], data: { confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-remove"
-              - else
-                - if @user.solo_owned_groups.present?
-                  %p
-                    This user is currently an owner in these groups:
-                    %strong #{@user.solo_owned_groups.map(&:name).join(', ')}
-                  %p
-                    You must transfer ownership or delete these groups before you can delete this user.
+              Disabled
+
+        %li
+          %span.light Can create groups:
+          %strong
+            = @user.can_create_group ? "Yes" : "No"
+        %li
+          %span.light Personal projects limit:
+          %strong
+            = @user.projects_limit
+        %li
+          %span.light Member since:
+          %strong
+            = @user.created_at.stamp("Nov 12, 2031")
+        - if @user.confirmed_at
+          %li
+            %span.light Confirmed at:
+            %strong
+              = @user.confirmed_at.stamp("Nov 12, 2031")
+        - else
+          %li
+            %span.light Confirmed:
+            %strong.cred
+              No
+
+        %li
+          %span.light Current sign-in at:
+          %strong
+            - if @user.current_sign_in_at
+              = @user.current_sign_in_at.stamp("Nov 12, 2031")
+            - else
+              never
 
-  #profile.tab-pane
-    .row
-      .col-md-6
-        .panel.panel-default
+        %li
+          %span.light Last sign-in at:
+          %strong
+            - if @user.last_sign_in_at
+              = @user.last_sign_in_at.stamp("Nov 12, 2031")
+            - else
+              never
+
+        %li
+          %span.light Sign-in count:
+          %strong
+            = @user.sign_in_count
+
+        - if @user.ldap_user?
+          %li
+            %span.light LDAP uid:
+            %strong
+              = @user.ldap_identity.extern_uid
+
+        - if @user.created_by
+          %li
+            %span.light Created by:
+            %strong
+              = link_to @user.created_by.name, [:admin, @user.created_by]
+
+  .col-md-6
+    - unless @user == current_user
+      - if @user.blocked?
+        .panel.panel-info
           .panel-heading
-            = @user.name
-          %ul.well-list
-            %li
-              = image_tag avatar_icon(@user.email, 60), class: "avatar s60"
-            %li
-              %span.light Profile page:
-              %strong
-                = link_to user_path(@user) do
-                  = @user.username
-      .col-md-6
-        = render 'users/profile', user: @user
-
-  #groups.tab-pane
-    - if @user.group_members.present?
-      .panel.panel-default
-        .panel-heading Groups:
-        %ul.well-list
-          - @user.group_members.each do |group_member|
-            - group = group_member.group
-            %li.group_member
-              %span{class: ("list-item-name" unless group_member.owner?)}
-                %strong= link_to group.name, admin_group_path(group)
-              .pull-right
-                %span.light= group_member.human_access
-                - unless group_member.owner?
-                  = link_to group_group_member_path(group, group_member), data: { confirm: remove_user_from_group_message(group, group_member) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
-                    %i.fa.fa-times.fa-inverse
-    - else
-      .nothing-here-block This user has no groups.
-
-  #projects.tab-pane
-    - if @user.groups.any?
-      .panel.panel-default
-        .panel-heading Group projects
-        %ul.well-list
-          - @user.groups.each do |group|
-            %li
-              %strong= group.name
-              &ndash; access to
-              #{pluralize(group.projects.count, 'project')}
-
-    .row
-      .col-md-6
-        = render 'users/projects', projects: @personal_projects
-
-      .col-md-6
-        .panel.panel-default
-          .panel-heading Joined projects (#{@joined_projects.count})
-          %ul.well-list
-            - @joined_projects.sort_by(&:name_with_namespace).each do |project|
-              - member = project.team.find_member(@user.id)
-              %li.project_member
-                .list-item-name
-                  = link_to admin_namespace_project_path(project.namespace, project), class: dom_class(project) do
-                    = project.name_with_namespace
-
-                - if member
-                  .pull-right
-                    - if member.owner?
-                      %span.light Owner
-                    - else
-                      %span.light= member.human_access
-
-                      - if member.respond_to? :project
-                        = link_to namespace_project_project_member_path(project.namespace, project, member), data: { confirm: remove_from_project_team_message(project, member) }, remote: true, method: :delete, class: "btn-xs btn btn-remove", title: 'Remove user from project' do
-                          %i.fa.fa-times
-  #ssh-keys.tab-pane
-    = render 'profiles/keys/key_table', admin: true
+            This user is blocked
+          .panel-body
+            %p Blocking user has the following effects:
+            %ul
+              %li User will not be able to login
+              %li User will not be able to access git repositories
+              %li Personal projects will be left
+              %li Owned groups will be left
+            %br
+            = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
+      - else
+        .panel.panel-warning
+          .panel-heading
+            Block this user
+          .panel-body
+            %p Blocking user has the following effects:
+            %ul
+              %li User will not be able to login
+              %li User will not be able to access git repositories
+              %li User will be removed from joined projects and groups
+              %li Personal projects will be left
+              %li Owned groups will be left
+            %br
+            = link_to 'Block user', block_admin_user_path(@user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put, class: "btn btn-warning"
+
+      .panel.panel-danger
+        .panel-heading
+          Remove user
+        .panel-body
+          - if @user.can_be_removed?
+            %p Deleting a user has the following effects:
+            %ul
+              %li All user content like authored issues, snippets, comments will be removed
+              - rp = @user.personal_projects.count
+              - unless rp.zero?
+                %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
+            %br
+            = link_to 'Remove user', [:admin, @user], data: { confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-remove"
+          - else
+            - if @user.solo_owned_groups.present?
+              %p
+                This user is currently an owner in these groups:
+                %strong #{@user.solo_owned_groups.map(&:name).join(', ')}
+              %p
+                You must transfer ownership or delete these groups before you can delete this user.
diff --git a/config/routes.rb b/config/routes.rb
index d60bc796fdb4537d6c389cb16c8863d89db1cce7..33f55dde476f5953138b7679219bbeacffb44e60 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -149,7 +149,12 @@ Gitlab::Application.routes.draw do
   namespace :admin do
     resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
       resources :keys, only: [:show, :destroy]
+      resources :identities, only: [:index, :edit, :update, :destroy]
+
       member do
+        get :projects
+        get :keys
+        get :groups
         put :team_update
         put :block
         put :unblock
diff --git a/features/admin/users.feature b/features/admin/users.feature
index 1a8720dd77edfb081a99badfc4b3e047e6baa19e..6755645778a1be679c78807be211d39acd442ce5 100644
--- a/features/admin/users.feature
+++ b/features/admin/users.feature
@@ -28,7 +28,7 @@ Feature: Admin Users
     When I submit modified user
     Then I see user attributes changed
 
-@javascript
+  @javascript
   Scenario: Remove users secondary email
     Given I visit admin users page
     And I view the user with secondary email
@@ -40,8 +40,26 @@ Feature: Admin Users
     Given user "Pete" with ssh keys
     And I visit admin users page
     And click on user "Pete"
+    And click on ssh keys tab
     Then I should see key list
     And I click on the key title
     Then I should see key details
     And I click on remove key
     Then I should see the key removed
+
+  Scenario: Show user identities
+    Given user "Pete" with twitter account
+    And I visit "Pete" identities page in admin
+    Then I should see twitter details
+
+  Scenario: Update user identities
+    Given user "Pete" with twitter account
+    And I visit "Pete" identities page in admin
+    And I modify twitter identity
+    Then I should see twitter details updated
+
+  Scenario: Remove user identities
+    Given user "Pete" with twitter account
+    And I visit "Pete" identities page in admin
+    And I remove twitter identity
+    Then I should not see twitter details
diff --git a/features/steps/admin/users.rb b/features/steps/admin/users.rb
index 34a3ed9f615ae3635f1fc17f0077f21df0ddfaad..6c4b91586d65720e1e91a6df8feae00380835788 100644
--- a/features/steps/admin/users.rb
+++ b/features/steps/admin/users.rb
@@ -114,4 +114,45 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps
   step 'I should see the key removed' do
     expect(page).not_to have_content 'ssh-rsa Key2'
   end
+
+  step 'user "Pete" with twitter account' do
+    @user = create(:user, name: 'Pete')
+    @user.identities.create!(extern_uid: '123456', provider: 'twitter')
+  end
+
+  step 'I visit "Pete" identities page in admin' do
+    allow(Gitlab::OAuth::Provider).to receive(:names).and_return(%w(twitter twitter_updated))
+    visit admin_user_identities_path(@user)
+  end
+
+  step 'I should see twitter details' do
+    expect(page).to have_content 'Pete'
+    expect(page).to have_content 'twitter'
+  end
+
+  step 'I modify twitter identity' do
+    find('.table').find(:link, 'Edit').click
+    fill_in 'identity_extern_uid', with: '654321'
+    select 'twitter_updated', from: 'identity_provider'
+    click_button 'Save changes'
+  end
+
+  step 'I should see twitter details updated' do
+    expect(page).to have_content 'Pete'
+    expect(page).to have_content 'twitter_updated'
+    expect(page).to have_content '654321'
+  end
+
+  step 'I remove twitter identity' do
+    click_link 'Delete'
+  end
+
+  step 'I should not see twitter details' do
+    expect(page).to have_content 'Pete'
+    expect(page).to_not have_content 'twitter'
+  end
+
+  step 'click on ssh keys tab' do
+    click_link 'SSH keys'
+  end
 end
diff --git a/lib/gitlab/o_auth/provider.rb b/lib/gitlab/o_auth/provider.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f986499a27cc62e61151da0f8bd6c2b2a72b404f
--- /dev/null
+++ b/lib/gitlab/o_auth/provider.rb
@@ -0,0 +1,19 @@
+module Gitlab
+  module OAuth
+    class Provider
+      def self.names
+        providers = []
+
+        Gitlab.config.ldap.servers.values.each do |server|
+          providers << server['provider_name']
+        end
+
+        Gitlab.config.omniauth.providers.each do |provider|
+          providers << provider['name']
+        end
+
+        providers
+      end
+    end
+  end
+end