diff --git a/fid/config/vufind/fid.ini b/fid/config/vufind/fid.ini
index 849eafe4edef9e5f6245714de74eb9e0ef4b4894..8ad0334e9c8acaec84a14e0737613ae485b37ba0 100644
--- a/fid/config/vufind/fid.ini
+++ b/fid/config/vufind/fid.ini
@@ -3,4 +3,23 @@ baseUrl = http://172.18.113.133/bbi-alpha.3
 
 [Security]
 access_levels[] = limited_access
-access_levels[] = full_access
\ No newline at end of file
+access_levels[] = full_access
+
+[Admin]
+; Whitelist of all fields that admins shall be able
+; to change for other users
+;editable_user_fields[] = 'HomeLibrary'
+editable_user_fields[] = 'Permissions'
+editable_user_fields[] = 'Salutation'
+
+;list of user fields to be shown in overview table
+overview_fields[] = 'UserName'
+overview_fields[] = 'Firstname'
+overview_fields[] = 'Lastname'
+overview_fields[] = 'Permissions'
+
+; List of all available user permissions
+permission_options[] = 'edit_user'
+permission_options[] = 'read_user_list'
+permission_options[] = 'limited_access'
+permission_options[] = 'full_access'
\ No newline at end of file
diff --git a/fid/config/vufind/permissionBehavior.ini b/fid/config/vufind/permissionBehavior.ini
new file mode 100644
index 0000000000000000000000000000000000000000..c5d8cf1661a251631d5801a512296cecfdd77821
--- /dev/null
+++ b/fid/config/vufind/permissionBehavior.ini
@@ -0,0 +1,22 @@
+;####################################################################
+;##################### DO NOT DELETE THIS HEADER ####################
+;################### Leipzig University Library © 2019 ##############
+;
+; This is the FID-master default INI-file and inherits
+; all the settings from the INI-file defined in [Parent_Config] which
+; points to the default INI-file located in the folder vufind2/local
+;
+
+[Parent_Config]
+relative_path = ../../../local/config/vufind/permissionBehavior.ini
+
+; A comma-separated list of config sections from the parent which should be
+; completely overwritten by the equivalent sections in this configuration;
+; any sections not listed here will be merged on a section-by-section basis.
+;override_full_sections = ""
+
+;
+;       Add instance-specific customization after this header.
+;
+;##################### DO NOT DELETE THIS HEADER ####################
+;####################################################################
\ No newline at end of file
diff --git a/fid/config/vufind/permissions.ini b/fid/config/vufind/permissions.ini
index 09473231d4d630422b1329ddfdffb83ce195e536..2269abcc3024634b7da35f0a085d1e47e75f8d88 100644
--- a/fid/config/vufind/permissions.ini
+++ b/fid/config/vufind/permissions.ini
@@ -19,4 +19,20 @@ relative_path = ../../../local/config/vufind/permissions.ini
 ;       Add instance-specific customization after this header.
 ;
 ;##################### DO NOT DELETE THIS HEADER ####################
-;####################################################################
\ No newline at end of file
+;####################################################################
+; Show staff view for all users by default
+[fid.ReadList]
+role[] = loggedin
+FidApiPermission = read_user_list
+
+[fid.EditUser]
+role[] = loggedin
+FidApiPermission = edit_user
+
+[fid.LimitedAccess]
+role[] = loggedin
+FidApiPermission = limited_access
+
+[fid.FullAccess]
+role[] = loggedin
+FidApiPermission = full_access
\ No newline at end of file
diff --git a/local/config/vufind/permissionBehavior.ini b/local/config/vufind/permissionBehavior.ini
new file mode 100644
index 0000000000000000000000000000000000000000..7297e4a66f87957bd24de31e21e4cab604d83c4f
--- /dev/null
+++ b/local/config/vufind/permissionBehavior.ini
@@ -0,0 +1,25 @@
+;####################################################################
+;##################### DO NOT DELETE THIS HEADER ####################
+;################### Leipzig University Library © 2019 ##############
+;
+; This is the ISIL-instance-specific default INI-file and inherits
+; all the settings from the INI-file defined in [Parent_Config] which
+; points to the default INI-file located in the folder vufind2/local
+;
+
+[Parent_Config]
+relative_path = ../../../config/vufind/permissionBehavior.ini
+
+; A comma-separated list of config sections from the parent which should be
+; completely overwritten by the equivalent sections in this configuration;
+; any sections not listed here will be merged on a section-by-section basis.
+;override_full_sections = ""
+
+;
+;       Add instance-specific customization after this header.
+;
+;##################### DO NOT DELETE THIS HEADER ####################
+;####################################################################
+
+[global]
+defaultDeniedTemplateBehavior = true
\ No newline at end of file
diff --git a/module/fid/config/module.config.php b/module/fid/config/module.config.php
index 075a68cf034e5af117a91b2e0bd67a270097368d..dfbbf46edc8e328761350308ab3df558c12a7209 100644
--- a/module/fid/config/module.config.php
+++ b/module/fid/config/module.config.php
@@ -21,6 +21,7 @@
 
 use fid\Controller\UserController;
 use fid\Controller\UserControllerFactory;
+use fid\FormModel\UsernameChangeModel;
 use fid\FormModel\PasswordChangeModel;
 use fid\FormModel\PasswordResetModel;
 use fid\FormModel\UserCreateModel;
@@ -55,6 +56,7 @@ return [
         UserUpdateModel::class     => require_once 'user-update-form.php',
         PasswordResetModel::class  => require_once 'password-reset-form.php',
         PasswordChangeModel::class => require_once 'password-change-form.php',
+        UsernameChangeModel::class => require_once 'username-change-form.php',
     ],
     'controllers'        => [
         'factories' => [
@@ -129,6 +131,18 @@ return [
             ],
         ],
     ],
+    // Authorization configuration:
+    'zfc_rbac' => [
+        'vufind_permission_provider_manager' => [
+            'factories' => [
+                'fid\Role\PermissionProvider\FidApiPermission' =>
+                    'fid\Role\PermissionProvider\Factory::getFidApiPermission'
+            ],
+            'aliases' => [
+                'FidApiPermission' => 'fid\Role\PermissionProvider\FidApiPermission'
+            ]
+        ]
+    ],
     'router'             => [
         'routes' => [
             'fid'                => [
@@ -215,9 +229,59 @@ return [
                                         'action'     => 'changePassword',
                                     ],
                                 ],
+                            ],
+                            'change-username' => [
+                                'type'    => 'literal',
+                                'options' => [
+                                    'route'    => '/change-username',
+                                    'defaults' => [
+                                        'controller' => UserController::class,
+                                        'action'     => 'changeUsername',
+                                    ],
+                                ],
+                            ],
+                            'update-username' => [
+                                'type'    => 'literal',
+                                'options' => [
+                                    'route'    => '/update-username',
+                                    'defaults' => [
+                                        'controller' => UserController::class,
+                                        'action'     => 'updateUsername',
+                                    ],
+                                ],
                             ]
                         ],
                     ],
+                    'admin'          => [
+                        'may_terminate' => false,
+                        'type'          => 'literal',
+                        'options'       => [
+                            'route' => '/admin'
+                        ],
+                        'child_routes'  => [
+                            'list'          => [
+                                'type'    => 'literal',
+                                'options' => [
+                                    'route'    => '/list',
+                                    'defaults' => [
+                                        'controller' => UserController::class,
+                                        'action'     => 'list',
+                                    ],
+                                ],
+                            ],
+                            'edit'          => [
+                                'type'    => 'Zend\Router\Http\Segment',
+                                'options' => [
+                                    'route'    => '/edit/[:userid]',
+                                    'defaults' => [
+                                        'controller' => UserController::class,
+                                        'action'     => 'edit',
+                                        'userid'     => null
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
                 ],
             ],
             'myresearch-account' => [
@@ -238,4 +302,4 @@ return [
             ]
         ],
     ],
-];
\ No newline at end of file
+];
diff --git a/module/fid/config/user-update-form.php b/module/fid/config/user-update-form.php
index 6ce6b77daffa9c7d07559526d87f66f45a2cb675..546c62246b35da8b6ac74bc6fdf18352b7561165 100644
--- a/module/fid/config/user-update-form.php
+++ b/module/fid/config/user-update-form.php
@@ -22,17 +22,28 @@
 use Zend\Filter\StringTrim;
 use Zend\Filter\ToInt;
 use Zend\Filter\ToNull;
+use Zend\Filter\Callback;
 use Zend\Form\Element\Number;
 use Zend\Form\Element\Select;
 use Zend\Form\Element\Submit;
 use Zend\Form\Element\Text;
+use Zend\Form\Element\Hidden;
+use Zend\Form\Element\MultiCheckbox;
 use Zend\Hydrator\ClassMethods;
 use Zend\Validator\Regex;
 use Zend\Validator\StringLength;
+use Zend\Validator\InArray;
+use Zend\Validator\Explode;
 
 return [
     'hydrator'     => ClassMethods::class,
     'elements'     => [
+        'userId'   => [
+            'spec' => [
+                'name'       => 'userId',
+                'type'       => Hidden::class,
+            ],
+        ],
         'salutation'    => [
             'spec' => [
                 'name'    => 'salutation',
@@ -130,6 +141,17 @@ return [
                 ]
             ],
         ],
+        'permissions'   => [
+            'spec' => [
+                'name'       => 'permissions',
+                'type'       => MultiCheckbox::class,
+                'options'    => [
+                    'label'        => 'label_permissions',
+                    'checked_value' => 'granted',
+                    'unchecked_value' => 'denied',
+                ],
+            ],
+        ],
         'submit'        => [
             'spec' => [
                 'name'       => 'submit',
@@ -244,6 +266,35 @@ return [
                 ],
             ],
         ],
+        'permissions'   => [
+            'name'      => 'permissions',
+            'required'  => false,
+            'validators' => [
+                Explode::class => [
+                    'name' => Explode::class,
+                    'options' => [
+                        'validator' => [
+                            'name'    => InArray::class,
+                            'options' => [
+                                'haystack' => [
+                                    'granted',
+                                    'denied',
+                                    'requested'
+                                ],
+                            ]
+                        ],
+                    ],
+                ],
+            ],
+            'filters'  => [
+                Callback::class => [
+                    'name' => Callback::class,
+                    'options' => [
+                        'callback' => '\fid\Controller\UserController::combinePermissionsArray'
+                    ]
+                ],
+            ],
+        ],
         'submit'               => [
             'name'       => 'submit',
             'required'   => true,
diff --git a/module/fid/config/username-change-form.php b/module/fid/config/username-change-form.php
new file mode 100644
index 0000000000000000000000000000000000000000..75ac717b6a862512ecfb7193f0c4ddb59fafc102
--- /dev/null
+++ b/module/fid/config/username-change-form.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use Zend\Filter\StringTrim;
+use Zend\Form\Element\Email;
+use Zend\Form\Element\Submit;
+use Zend\Form\Element\Text;
+use Zend\Hydrator\ClassMethods;
+use Zend\Validator\EmailAddress;
+use Zend\Validator\Identical;
+use Zend\Validator\StringLength;
+
+return [
+    'hydrator'     => ClassMethods::class,
+    'elements'     => [
+        'username'             => [
+            'spec' => [
+                'name'       => 'username',
+                'type'       => Email::class,
+                'options'    => [
+                    'label' => 'label_newusername',
+                ],
+                'attributes' => [
+                    'required' => 'required',
+                ],
+            ],
+        ],
+        'usernameConfirmation' => [
+            'spec' => [
+                'name'       => 'usernameConfirmation',
+                'type'       => Text::class,
+                'options'    => [
+                    'label' => 'label_newusername_confirmation',
+                ],
+                'attributes' => [
+                    'required' => 'required',
+                ],
+            ],
+        ],
+        'submit'               => [
+            'spec' => [
+                'name'       => 'submit',
+                'type'       => Submit::class,
+                'attributes' => [
+                    'value' => 'label_submit',
+                ],
+            ],
+        ],
+    ],
+    'input_filter' => [
+        'username'             => [
+            'name'       => 'username',
+            'required'   => true,
+            'filters'    => [
+                StringTrim::class => [
+                    'name' => StringTrim::class,
+                ],
+            ],
+            'validators' => [
+                StringLength::class => [
+                    'name'    => StringLength::class,
+                    'options' => [
+                        'max' => 255
+                    ],
+                ],
+                EmailAddress::class => [
+                    'name' => EmailAddress::class,
+                ],
+            ],
+        ],
+        'usernameConfirmation' => [
+            'name'       => 'usernameConfirmation',
+            'required'   => true,
+            'validators' => [
+                Identical::class => [
+                    'name'    => Identical::class,
+                    'options' => [
+                        'strict'   => false,
+                        'token'    => 'username',
+                        'messages' => [
+                            Identical::NOT_SAME => 'error_username_confirmation',
+                        ],
+                    ],
+                ],
+            ],
+        ],
+        'submit'               => [
+            'name'       => 'submit',
+            'required'   => true,
+        ],
+    ],
+];
diff --git a/module/fid/src/Controller/UserController.php b/module/fid/src/Controller/UserController.php
index 10deb2e9c83e9068af4458f9494b7f2c95e9879d..d101d2e4e1c066866b0125db422b46592e8b6506 100644
--- a/module/fid/src/Controller/UserController.php
+++ b/module/fid/src/Controller/UserController.php
@@ -27,14 +27,17 @@ use fid\FormModel\PasswordResetModel;
 use fid\FormModel\UserCreateModel;
 use fid\FormModel\UserInitModel;
 use fid\FormModel\UserUpdateModel;
+use fid\FormModel\UsernameChangeModel;
 use fid\Service\Client;
 use fid\Service\ClientException;
 use fid\Service\DataTransferObject\Library;
 use fid\Service\DataTransferObject\User;
+use fid\Service\UserNotAuthorizedException;
 use Symfony\Component\Serializer\SerializerAwareTrait;
 use VuFind\Auth\Manager as AuthManager;
 use VuFind\Controller\AbstractBase;
 use VuFind\Exception\Auth as AuthException;
+use Zend\Form\Element\MultiCheckbox;
 use Zend\Form\Element\Radio;
 use Zend\Form\Element\Select;
 use Zend\Form\Form;
@@ -84,6 +87,7 @@ class UserController extends AbstractBase
     }
 
     /**
+     * @noinspection PhpUnused
      * @return ViewModel
      */
     public function initAction()
@@ -108,6 +112,7 @@ class UserController extends AbstractBase
     }
 
     /**
+     * @noinspection PhpUnused
      * @return Response|ViewModel
      */
     public function createAction()
@@ -175,6 +180,11 @@ class UserController extends AbstractBase
         return $view;
     }
 
+
+    /**
+     * @noinspection PhpUnused
+     * @return Response|ViewModel
+     */
     public function updateAction()
     {
         /** @var Request $request */
@@ -215,6 +225,73 @@ class UserController extends AbstractBase
         return $viewModel;
     }
 
+    /**
+     * @noinspection PhpUnused
+     * @return ViewModel
+     */
+    public function changeUsernameAction()
+    {
+        /** @var Request $request */
+        $request = $this->getRequest();
+        $form = $this->serviceLocator->get(UsernameChangeModel::class);
+        $forwarded = $this->params()->fromRoute('forwarded', false);
+
+        if ($submitted = $this->formWasSubmitted()) {
+            $form->setData($request->getPost());
+            if (!$forwarded && $form->isValid()) {
+                return $this->changeUsername($form);
+            }
+        }
+
+        $view = $this->createViewModel();
+        $view->setVariables(compact('form'));
+        $view->setTemplate('fid/user/username-change');
+
+        return $view;
+    }
+
+    /**
+     * @noinspection PhpUnused
+     * @return Response
+     */
+    public function updateUsernameAction()
+    {
+        /** @var Request $request */
+        $request = $this->getRequest();
+        $query = $request->getQuery();
+        $messenger = $this->getMessenger();
+
+        if ($credentials = $query->get('logon')) {
+            try {
+                $this->client->logon($credentials);
+            } catch (ClientException $exception) {
+                $message = $exception->getCode() === 401
+                    ? 'fid::username_update_error_expired'
+                    : 'fid::username_update_error';
+                $messenger->addErrorMessage($this->translate($message));
+                return $this->redirect()->toRoute('fid/user/change-username');
+            }
+
+            $query->offsetUnset('logon');
+            return $this->redirect()->toRoute('fid/user/update-username', [], [
+                'query' => $query->toArray()
+            ]);
+        }
+
+        try {
+            $user = $this->client->requestUserDetails();
+            $user->setUsername($query->get('username'));
+            $this->client->requestUserUsernameUpdate($user);
+            $message = $this->translate('fid::username_update_success');
+            $this->getMessenger()->addSuccessMessage($message);
+        } catch (ClientException $exception) {
+            $message = $this->translate('fid::username_update_error');
+            $this->getMessenger()->addErrorMessage($message);
+        }
+
+        return $this->redirect()->toRoute('myresearch-home');
+    }
+
     public function policyAction()
     {
         $viewModel = $this->createViewModel();
@@ -396,7 +473,7 @@ class UserController extends AbstractBase
      *
      * @return Response
      */
-    protected function update(Form $form)
+    protected function update(Form $form,string $redirect = 'myresearch-home')
     {
         $messenger = $this->getMessenger();
         /** @var UserUpdateModel $model */
@@ -404,7 +481,8 @@ class UserController extends AbstractBase
             new UserUpdateModel());
 
         try {
-            $user = $this->client->requestUserDetails();
+            $userId = $model->getUserId();
+            $user = $this->client->requestUserDetails($userId);
             $user->setHomeLibrary($model->getHomeLibrary());
             $user->setSalutation($model->getSalutation());
             $user->setAcademicTitle($model->getAcademicTitle());
@@ -413,6 +491,7 @@ class UserController extends AbstractBase
             $user->setYearOfBirth($model->getYearOfBirth());
             $user->setCollege($model->getCollege());
             $user->setJobTitle($model->getJobTitle());
+            $user->setPermissions($model->getPermissions());
             $this->client->requestUserUpdate($user);
             $message = $this->translate('fid::user_update_success');
             $messenger->addSuccessMessage($message);
@@ -427,7 +506,8 @@ class UserController extends AbstractBase
             $messenger->addErrorMessage($message);
         }
 
-        return $this->redirect()->toRoute('myresearch-home', [], [
+        $this->client->flushUserList();
+        return $this->redirect()->toRoute($redirect, [], [
             'query' => ['redirect' => false]
         ]);
     }
@@ -493,6 +573,35 @@ class UserController extends AbstractBase
         ]);
     }
 
+    protected function changeUsername(Form $form)
+    {
+        $messenger = $this->getMessenger();
+        $model = $form->getHydrator()->hydrate(
+            $form->getData(), new UsernameChangeModel());
+
+        /** @noinspection PhpUndefinedFieldInspection */
+        $query['lng'] = $this->layout()->userLang;
+        $username = $query['username'] = $model->getUsername();
+        $baseUrl = $this->url()->fromRoute('fid/user/update-username',
+            [], ['query' => $query, 'force_canonical' => true]);
+
+        try {
+            $this->client->requestUsernameLink($baseUrl, $username);
+        } catch (ClientException $exception) {
+            $message = $exception->getCode() === 400
+                ? 'fid::username_change_error_username'
+                : 'fid::username_change_error';
+            $messenger->addErrorMessage($this->translate($message));
+            return $this->forward()->dispatch(self::class, [
+                'action'    => 'changeUsername',
+                'forwarded' => true
+            ]);
+        }
+
+        $message = $this->translate('fid::username_change_success');
+        $messenger->addSuccessMessage(sprintf($message, $username));
+        return $this->redirect()->toRoute('myresearch-home');
+    }
 
     protected function getMessenger(): FlashMessenger
     {
@@ -500,4 +609,161 @@ class UserController extends AbstractBase
         /** @var FlashMessenger $messenger */
         return $this->flashMessenger();
     }
-}
\ No newline at end of file
+
+    public function editAction()
+    {
+        // Not logged in?  Force user to log in:
+        if (!$this->getAuthManager()->isLoggedIn()) {
+            // Allow bypassing of post-login redirect
+            if ($this->params()->fromQuery('redirect', true)) {
+                $this->setFollowupUrlToReferer();
+            }
+            return $this->forwardTo('MyResearch', 'Login');
+        }
+
+        /** @var Request $request */
+        $request = $this->getRequest();
+        $userId = $this->params()->fromRoute('userid');
+        if (empty($userId)) {
+            // if no user ID is set the call is not valid
+            // unless we are in submission state
+            return $this->redirect()->toRoute('fid/admin/list');
+        }
+
+        $editableFields = $this->config['Admin']['editable_user_fields'] ?? [];
+
+        try {
+            try {
+                $user = $this->client->requestUserDetails($userId);
+            } catch (UserNotAuthorizedException $ex) {
+                // either user does not exist, or we are not allowed to edit it
+                $this->getMessenger()->addErrorMessage($this->translate('fid::user_edit_not_allowed', ['%%userid%%' => $userId]));
+                return $this->redirect()->toRoute('fid/admin/list');
+            } catch (\Exception $ex) {
+                $this->getMessenger()->addErrorMessage($this->translate('fid::user_read_error',['%%userid%%' => $userId]));
+                return $this->redirect()->toRoute('fid/admin/list');
+            }
+            $libraries = $this->client->requestLibraryList();
+        } catch (ClientException $exception) {
+            $this->setFollowupUrlToReferer();
+            $message = $exception->getCode() === 401
+                ? 'fid::user_update_error_expired'
+                : 'fid::user_update_error';
+            $this->getMessenger()->addErrorMessage($this->translate($message));
+            return $this->redirect()->toRoute('fid/admin/list');
+        }
+
+        /** @var Form $form */
+        $form = $this->serviceLocator->get(UserUpdateModel::class);
+
+        if (!empty($libraries)) {
+            $userLibrary = $user->getHomeLibrary();
+            $libraries = array_map(function (Library $libary) use ($editableFields,$userLibrary) {
+                $option = [
+                    'label' => $libary->getLabel(),
+                    'value' => $id = $libary->getId(),
+                    'selected' => $id == $userLibrary
+                ];
+                if ($id != $userLibrary && !in_array('HomeLibrary', $editableFields)) {
+                    $option['attributes']['disabled'] = 'disabled';
+                }
+                return $option;
+            }, $libraries);
+
+            /** @var Select $homeLibraryElement */
+            $homeLibraryElement = $form->get('homeLibrary');
+            $homeLibraryElement->setValueOptions($libraries);
+        }
+
+        if ($permissions = $this->config['Admin']['permission_options'] ?? []) {
+
+            $userPermissions = $user->getPermissions();
+            if (!isset(self::$currentPermissions)) {
+                $valid = [];
+                foreach ($permissions as $permission) {
+                    $valid[$permission] = $userPermissions[$permission] ?? 'denied';
+                }
+                self::$currentPermissions = $valid;
+            }
+            /** @var MultiCheckbox $permissionsElement */
+            $permissionsElement = $form->get('permissions');
+            $permissions = array_map(function ($permission) use ($editableFields,$userPermissions) {
+                $option = [
+                    'label' => $this->translate('fid::permission_' . $permission),
+                    'name' => $permission,
+                    'label_attributes' => ['class' => 'permission-label col-sm-11'],
+                    'attributes' => ['class' => 'permission-option col-sm-1'],
+                    'selected' => isset($userPermissions[$permission]) && $userPermissions[$permission] == 'granted',
+                    'value' => $permission . '::' . ($userPermissions[$permission] ?? 'denied'),
+                ];
+                if (!in_array('Permissions', $editableFields)) {
+                    $option['disabled'] = '1';
+                }
+                return $option;
+            }, $permissions);
+            $permissionsElement->setDisableInArrayValidator(true);
+            $permissionsElement->setValueOptions($permissions);
+        }
+
+        if ($this->formWasSubmitted()) {
+            $form->setData($request->getPost());
+            if ($form->isValid()) {
+                return $this->update($form,'fid/admin/list');
+            }
+        }
+
+        $viewModel = $this->createViewModel();
+        $viewModel->setVariables(compact('form', 'user','editableFields'));
+        $viewModel->setTemplate('fid/admin/edit');
+
+        return $viewModel;
+    }
+
+    public static $currentPermissions;
+
+    public static function combinePermissionsArray($input) {
+        $output = [];
+        foreach ($input as $line) {
+            list($key,) = explode('::',$line);
+            if (isset(self::$currentPermissions[$key])) {
+                $output[$key] = 'granted';
+            }
+        }
+        foreach (self::$currentPermissions as $key => $state) {
+            if ($state === 'granted' && !isset($output[$key])) {
+                $output[$key] = 'denied';
+            }
+        }
+        return array_intersect_key($output,['full_access'=>'0','limited_access'=>1]);
+    }
+
+    public function listAction() {
+
+        // Not logged in?  Force user to log in:
+        if (!$this->getAuthManager()->isLoggedIn()) {
+            // Allow bypassing of post-login redirect
+            if ($this->params()->fromQuery('redirect', true)) {
+                $this->setFollowupUrlToReferer();
+            }
+            return $this->forwardTo('MyResearch', 'Login');
+        }
+
+        $viewModel = $this->createViewModel();
+        try {
+            $list = $this->client->requestUserList();
+            $viewModel->setVariable('list',$list);
+        } catch (UserNotAuthorizedException $exception) {
+            $this->getMessenger()->addErrorMessage('fid::read_user_list_not_allowed');
+        } catch (ClientException $exception) {
+            $this->getMessenger()->addErrorMessage('fid::read_user_list_error');
+        }
+
+        if ($fields = $this->config['Admin']['overview_fields']) {
+            $viewModel->setVariable('fields',$fields);
+        }
+
+        $viewModel->setTemplate('fid/admin/list');
+        return $viewModel;
+    }
+
+}
diff --git a/module/fid/src/FormModel/UserUpdateModel.php b/module/fid/src/FormModel/UserUpdateModel.php
index e6bda2be41d7a7a684bd70f41a6db0e76dd9f0dd..fcf67c9a8649f4fdac3d3d4f748003c5e7689e42 100644
--- a/module/fid/src/FormModel/UserUpdateModel.php
+++ b/module/fid/src/FormModel/UserUpdateModel.php
@@ -24,6 +24,11 @@ namespace fid\FormModel;
 
 class UserUpdateModel
 {
+    /**
+     * @var string
+     */
+    protected $userId;
+
     /**
      * @var string
      */
@@ -64,11 +69,32 @@ class UserUpdateModel
      */
     protected $college;
 
+    /**
+     * @var array
+     */
+    protected $permissions;
+
     /**
      * @var string|null
      */
     protected $submit;
 
+    /**
+     * @return string|null
+     */
+    public function getUserId(): ?string
+    {
+        return $this->userId;
+    }
+
+    /**
+     * @param string $userId
+     */
+    public function setUserId(string $userId = null): void
+    {
+        $this->userId = $userId;
+    }
+
     /**
      * @return string
      */
@@ -197,6 +223,22 @@ class UserUpdateModel
         $this->college = $college;
     }
 
+    /**
+     * @param array $permissions
+     */
+    public function setPermissions(array $permissions): void
+    {
+        $this->permissions = $permissions;
+    }
+
+    /**
+     * @return array
+     */
+    public function getPermissions(): array
+    {
+        return $this->permissions;
+    }
+
     /**
      * @return string|null
      */
diff --git a/module/fid/src/FormModel/UsernameChangeModel.php b/module/fid/src/FormModel/UsernameChangeModel.php
new file mode 100644
index 0000000000000000000000000000000000000000..940e46d75d40e784b314e11adfc4b8ec361a383b
--- /dev/null
+++ b/module/fid/src/FormModel/UsernameChangeModel.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author   Gregor Gawol <gawol@ub.uni-leipzig.de>
+ * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+namespace fid\FormModel;
+
+class UsernameChangeModel
+{
+    /**
+     * @var string
+     */
+    protected $username;
+
+    /**
+     * @var string
+     */
+    protected $usernameConfirmation;
+
+    /**
+     * @var string
+     */
+    protected $submit;
+
+    /**
+     * @return string
+     */
+    public function getUsername(): string
+    {
+        return $this->username;
+    }
+
+    /**
+     * @param string $username
+     */
+    public function setUsername(string $username): void
+    {
+        $this->username = $username;
+    }
+
+    /**
+     * @return string
+     */
+    public function getUsernameConfirmation(): string
+    {
+        return $this->usernameConfirmation;
+    }
+
+    /**
+     * @param string $usernameConfirmation
+     */
+    public function setUsernameConfirmation(string $usernameConfirmation): void
+    {
+        $this->usernameConfirmation = $usernameConfirmation;
+    }
+
+    /**
+     * @return string
+     */
+    public function getSubmit(): string
+    {
+        return $this->submit;
+    }
+
+    /**
+     * @param string $submit
+     */
+    public function setSubmit(string $submit): void
+    {
+        $this->submit = $submit;
+    }
+}
diff --git a/module/fid/src/Role/PermissionProvider/Factory.php b/module/fid/src/Role/PermissionProvider/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..761c717d2192efd9c234729a148ba6e7f73308f2
--- /dev/null
+++ b/module/fid/src/Role/PermissionProvider/Factory.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Permission Provider Factory Class
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:hierarchy_components Wiki
+ */
+namespace fid\Role\PermissionProvider;
+
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Permission Provider Factory Class
+ *
+ * @category VuFind
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:hierarchy_components Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class Factory extends \VuFind\Role\PermissionProvider\Factory
+{
+    /**
+     * Factory for IpRangeFoFor
+     *
+     * @param ServiceManager $container Service manager.
+     *
+     * @return FidApiPermission
+     */
+    public static function getFidApiPermission(ServiceManager $container)
+    {
+        return new FidApiPermission(
+            $container->get('fid\Service\Client')
+        );
+    }
+}
diff --git a/module/fid/src/Role/PermissionProvider/FidApiPermission.php b/module/fid/src/Role/PermissionProvider/FidApiPermission.php
new file mode 100644
index 0000000000000000000000000000000000000000..51fa15ef4574b6b2edcd89d4613c2a668a2538fd
--- /dev/null
+++ b/module/fid/src/Role/PermissionProvider/FidApiPermission.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * IpRange permission provider for VuFind.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2007.
+ * Copyright (C) The National Library of Finland 2015.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @author   Gregor Gawol <gawol@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace fid\Role\PermissionProvider;
+
+use VuFind\Role\PermissionProvider\PermissionProviderInterface;
+use fid\Service\Client as FidApiClient;
+/**
+ * Permission provider authorizing FID API roles
+ *
+ * @category VuFind
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @author   Dorian Merz <merz@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class FidApiPermission implements PermissionProviderInterface
+{
+    /**
+     * @var FidApiClient
+     */
+    private $client;
+
+    public function __construct(FidApiClient $client)
+    {
+        $this->client = $client;
+    }
+
+    /**
+     * Return an array of roles which may be granted the permission based on
+     * the options.
+     *
+     * @param mixed $options Options provided from configuration.
+     *
+     * @return array
+     */
+    public function getPermissions($options)
+    {
+        if ($this->client->isAuthorized($options)) {
+            return ['loggedin'];
+        }
+        //  No match? No permissions.
+        return [];
+    }
+}
diff --git a/module/fid/src/Service/Client.php b/module/fid/src/Service/Client.php
index 32eb30ff41e86f0b9044905a69bce1dcac942c66..bda65b19de033fd438ade5e3250307a7e1224b37 100644
--- a/module/fid/src/Service/Client.php
+++ b/module/fid/src/Service/Client.php
@@ -241,21 +241,45 @@ class Client
         }
     }
 
+    /**
+     * @param string $baseUrl
+     * @param string $username
+     *
+     * @throws ClientException
+     */
+    public function requestUsernameLink(string $baseUrl, string $username): void
+    {
+        $body = json_encode(compact('baseUrl', 'username'));
+        $request = $this->buildRequest('post', 'mail/username', $body);
+        $response = $this->sendAuthenticatedRequest($request);
+
+        if ($response->getStatusCode() !== 204) {
+            $this->throwException($response);
+        }
+    }
 
     /**
      * @return User|null
      * @throws ClientException
+     * @throws UserNotAuthorizedException
      */
-    public function requestUserDetails(): ?User
+    public function requestUserDetails($userId = null): ?User
     {
         $logon = $this->restoreLogon();
 
         /** @var User $user */
-        if ($user = $this->session['user'] ?? null) {
-            return $user;
+        $user = $this->session['user'] ?? null;
+        $ownId = $logon->getOwnerId();
+
+        if (is_null($userId) || $userId === $ownId) {
+            // user asks for own profile data
+            if (!empty($user)) return $user;
+            $userId = $ownId;
+        } else {
+            // user asks for another user's profile
+            // this shall only be possible for authorized admins
+            $this->authorize('edit_user');
         }
-
-        $userId = $logon->getOwnerId();
         $request = $this->buildRequest('get', "users/$userId");
         $response = $this->sendAuthenticatedRequest($request);
 
@@ -267,7 +291,8 @@ class Client
         $user = $this->serializer->deserialize((string)$response->getBody(),
             User::class, 'json', ['groups' => ['user:details:response']]);
 
-        return $this->session['user'] = $user;
+         if ($ownId === $userId) $this->session['user'] = $user;
+         return $user;
     }
 
     /**
@@ -318,6 +343,81 @@ class Client
             ['user:update-password:request']);
     }
 
+    /**
+     * @param User $user
+     *
+     * @return User
+     * @throws ClientException
+     */
+    public function requestUserUsernameUpdate(User $user): User
+    {
+        return $this->doRequestUserUpdate($user, [
+            'user:update-username:request'
+        ]);
+    }
+
+    /**
+     * @return User[]
+     * @throws ClientException
+     * @throws UserNotAuthorizedException
+     */
+    public function requestUserList(): array
+    {
+        // user asks for another users' profiles
+        // this shall only be possible for authorized admins
+        $this->authorize('read_user_list');
+
+        if ($list = $this->session['users'] ?? null) {
+            return $list;
+        }
+
+        $request = $this->buildRequest('get', 'users');
+        $response = $this->sendAuthenticatedRequest($request);
+
+        if ($response->getStatusCode() !== 200) {
+            $this->throwException($response);
+        }
+        /** @var Library[] $list */
+        $list = $this->serializer->deserialize(
+            (string)$response->getBody(), User::class . '[]', 'json');
+
+        $keys = array_map(function (User $libary) {
+            return $libary->getId();
+        }, $list);
+
+        return $this->session['users'] = array_combine($keys, $list);
+    }
+
+    public function flushUserList() {
+        unset($this->session['users']);
+    }
+
+    /**
+     * throws an Exception in case the user does not have the requested permission
+     * or the permission cannot be verified
+     * @param String $permission Name of the permission
+     * @param User|null $user user object or null if we want to validate the currently logged in user
+     * @throws ClientException
+     * @throws UserNotAuthorizedException
+     */
+    protected function authorize(String $permission,User $user = null) {
+
+        $user = $this->requestUserDetails();
+        if (!$user->hasPermission($permission)) {
+            throw new UserNotAuthorizedException();
+        }
+    }
+
+    public function isAuthorized(String $permission) {
+
+        try {
+            $this->authorize($permission);
+        } catch (\Exception $ex) {
+            return FALSE;
+        }
+        return TRUE;
+    }
+
     /**
      * @return Library[]
      * @throws ClientException
@@ -365,7 +465,12 @@ class Client
         $result = $this->serializer->deserialize((string)$response->getBody(),
             User::class, 'json', ['groups' => ['user:update:response']]);
 
-        return $this->session['user'] = $result;
+        $logon = $this->restoreLogon();
+        if ($logon->getOwnerId() === $user->getId()) {
+            // refresh user data
+            $this->session['user'] = $result;
+        }
+        return $result;
     }
 
 
diff --git a/module/fid/src/Service/DataTransferObject/User.php b/module/fid/src/Service/DataTransferObject/User.php
index fc5695d8aa542af7ed7874b8b09b146e13eb4f7d..e7cc1bfc025370279a619e67d4bc94217c89b3d8 100644
--- a/module/fid/src/Service/DataTransferObject/User.php
+++ b/module/fid/src/Service/DataTransferObject/User.php
@@ -41,7 +41,8 @@ class User
      *     "user:details:response",
      *     "user:creation:request",
      *     "user:creation:response",
-     *     "user:update:response"
+     *     "user:update:response",
+     *     "user:update-username:request"
      * })
      */
     protected $username;
@@ -176,6 +177,21 @@ class User
      */
     protected $permissions = [];
 
+    /**
+     * Magic function as shortcut for all getters
+     * TODO ensure public visibility of all called getters
+     * @param $name
+     * @return |null
+     */
+    public function __get($name)
+    {
+        $methodName = 'get'.ucfirst($name);
+        if (method_exists($this,$methodName)) {
+            return $this->$methodName();
+        }
+        else return null;
+    }
+
     /**
      * @return string|null
      */
@@ -387,4 +403,16 @@ class User
     {
         $this->permissions = $permissions;
     }
+
+    public function hasPermission($permission): bool
+    {
+        if (
+            isset($this->permissions[$permission])
+        &&
+            $this->permissions[$permission] === 'granted'
+        ) {
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/module/fid/src/Service/UserNotAuthorizedException.php b/module/fid/src/Service/UserNotAuthorizedException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a802c48c66a9517551223bea7644e50c2fe066f1
--- /dev/null
+++ b/module/fid/src/Service/UserNotAuthorizedException.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author  Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+namespace fid\Service;
+
+class UserNotAuthorizedException extends \Exception
+{
+}
diff --git a/themes/fid/languages/fid/de.ini b/themes/fid/languages/fid/de.ini
index 44d6622ce9a6478dcdb4a927028788b100685753..9cb1972b05b1c4e947d196b9d0fd024ed5722781 100644
--- a/themes/fid/languages/fid/de.ini
+++ b/themes/fid/languages/fid/de.ini
@@ -6,9 +6,12 @@ user_create_form_title = "Registrierung abschließen"
 user_update_form_title = "Profildaten editieren."
 password_reset_form_title = "Passwort zurücksetzen"
 password_change_form_title = "Neues Passwort speichern"
+username_change_form_title = "E-Mail-Adresse ändern"
 
 label_username = "E-Mail-Adresse"
+label_newusername = "Neue E-Mail-Adresse"
 label_username_confirmation = "E-Mail-Adresse wiederholen"
+label_newusername_confirmation = "Neue E-Mail-Adresse wiederholen"
 label_firstname = "Vorname"
 label_lastname = "Nachname"
 label_salutation = "Anrede"
@@ -25,6 +28,7 @@ label_access_level = "Ich gehöre folgender Nutzergruppe an"
 label_access_level_full_access = "HochschullehrerInnen, wissenschaftliche MitarbeiterInnen, Mitglied einer Fachgesellschaft, DoktorandInnen, StipendiatInnen oder externe WissenschaftlerInnen (z. B. Lehrbeauftragte)"
 label_access_level_limited_access = "Studierende, Sonstige"
 label_access_level_unknown = "Unbekannte oder unbestätigte Gruppe(n)."
+label_permissions = "autorisiert für"
 
 label_delivery_address = "Privatadresse als Lieferadresse verwenden"
 Business = "Dienstadresse"
@@ -70,6 +74,31 @@ password_change_error_expired = "Der Link ist abgelaufen."
 password_change_error_autologon = "Ihr Passwort wurde gespeichert. Jedoch ist ein unerwarteteter Fehler bei der automatischen Anmeldung aufgetreten."
 password_change_success = "Passwort erfolgreich gespeichert."
 
+username_change_link = "E-Mail-Adresse ändern"
+username_change_error = "Es ist ein unerwarteter Fehler aufgetreten."
+username_change_error_username = "Die von Ihnen gewählte E-Mail-Adresse ist schon vergeben."
+username_change_success = "Ein Verifikationslink wurde soeben an Ihre neue E-Mail-Addresse %s gesendet. Die Zustellung kann einige Minuten in Anspruch nehmen. Bitte schauen Sie ggf. auch in Ihren Spamordner."
+
+username_update_error = "Es ist ein unerwarteter Fehler beim Aktualisieren Ihrer E-Mail-Adresse aufgetreten."
+username_update_error_expired = "Ihr Verifikationslink ist bereits abgelaufen. Bitte starten Sie den Vorgang erneut."
+username_update_success = "Ihre E-Mail-Addresse wurde erfolgreich aktualisiert."
+
 Edit Account = "Profildaten ändern"
 
-access_level_requested = "Ihre Zugehörigkeit zur unten stehenden Gruppe wird derzeit noch überprüft."
\ No newline at end of file
+
+access_level_requested = "Ihre Zugehörigkeit zur unten stehenden Gruppe wird derzeit noch überprüft."
+
+; Admin section
+user_edit_not_allowed = "Sie haben keine Berechtigung Nutzer %%userid%% zu editieren"
+user_read_error = "Fehler beim Lesen der Daten von Nutzer %%userid%%"
+read_user_list_not_allowed = "Sie haben keine Berechtigung die Nutzerliste einzusehen"
+read_user_list_error = "Fehler beim Lesen der Nutzerliste"
+
+user_edit_form_title = "Nutzerdaten ändern für <em>%%username%%</em> (ID %%userid%%)"
+
+user_edit = "Nutzer %%userid%% bearbeiten"
+
+permission_read_user_list = "Liste aller Nutzer einsehen"
+permission_edit_user = "Daten anderer Nutzer bearbeiten"
+permission_full_access = "Zugriff auf FID-Lizenzen"
+permission_limited_access = "Einfacher Zugriff"
\ No newline at end of file
diff --git a/themes/fid/languages/fid/en.ini b/themes/fid/languages/fid/en.ini
index 5f4b131105dd8331b10d4924b419f345667e9fa5..9ef8f48fe05fb1f5fdf550cb7f404143b23cbecf 100644
--- a/themes/fid/languages/fid/en.ini
+++ b/themes/fid/languages/fid/en.ini
@@ -6,9 +6,12 @@ user_create_form_title = "Complete registration"
 user_update_form_title = "Profile data"
 password_reset_form_title = "Reset password"
 password_change_form_title = "Save new password"
+username_change_form_title = "Update email address"
 
 label_username = "Email address"
+label_newusername = "New email address"
 label_username_confirmation = "Retype email address"
+label_newusername_confirmation = "Retype new email address"
 label_password = "Password"
 label_password_confirmation = "Retype Password"
 label_salutation = "Salutation"
@@ -25,6 +28,7 @@ label_access_level = "Please select your membership level"
 label_access_level_full_access = "Professor, Research Associate/Assistant, Member of an Academic Association, PhD Student (also Scholarships), (Visiting) Lecturer"
 label_access_level_limited_access = "Student, Other"
 label_access_level_unknown = "Unknown or ungranted user group(s)."
+label_permissions = "authorized for"
 
 label_delivery_address = "Use the following address for deliveries"
 Business = "Office Address"
@@ -70,6 +74,30 @@ password_change_error = "An unexpected error has occurred."
 password_change_error_expired = "The link has already expired."
 password_change_error_autologon = "You password has been update. However, an unexpected error has occurred during the process of logging on."
 
+username_change_link = "Update email address"
+username_change_error = "An unexpected error has occurred."
+username_change_error_username = "The specified email address is already taken."
+username_change_success = "A confirmation link has just been sent to your new email address %s. This may take several minutes. Please check also the junk folder of your mailbox."
+
+username_update_error = "An unexpected error has occurred when updating your email address."
+username_update_error_expired = "Your configmration link has already expired."
+username_update_success = "Your email address has successfully been updated."
+
 Edit Account = "Edit Account"
 
-access_level_requested = "Your membership status regarding the group below is currently being verified."
\ No newline at end of file
+access_level_requested = "Your membership status regarding the group below is currently being verified."
+
+; Admin section
+user_edit_not_allowed = "You are not entitled to edit user %%userid%%"
+user_read_error = "Error reading data of user %%userid%%"
+read_user_list_not_allowed = "You are not entitled to read the user list"
+read_user_list_error = "Error reading user list"
+
+user_edit_form_title = "Edit user data of <em>%%username%%</em> (ID %%userid%%)"
+
+user_edit = "Edit user %%userid%%"
+
+permission_read_user_list = "Read list of all users"
+permission_edit_user = "Edit other user's data"
+permission_full_access = "privileged access"
+permission_limited_access = "basic access"
\ No newline at end of file
diff --git a/themes/fid/scss/compiled.scss b/themes/fid/scss/compiled.scss
index 9f6357ce4c11d67119bd3ac177b7eb6bdfcb0a12..d87a310aaeb1fb19a179c705cdbb65b5c7704f78 100644
--- a/themes/fid/scss/compiled.scss
+++ b/themes/fid/scss/compiled.scss
@@ -66,4 +66,12 @@
     margin-right: $margin-right-width;
     padding-left: $margin-right-width;
   }
+}
+
+.permission-options {
+  margin-left: -$grid-gutter-width;
+}
+
+.template-dir-fid #content {
+  padding-top: 20px;
 }
\ No newline at end of file
diff --git a/themes/fid/templates/fid/admin/edit.phtml b/themes/fid/templates/fid/admin/edit.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..ef46743db675a7b319d20895342e2c86223a6260
--- /dev/null
+++ b/themes/fid/templates/fid/admin/edit.phtml
@@ -0,0 +1,249 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author   Gregor Gawol <gawol@ub.uni-leipzig.de>
+ * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use fid\Service\DataTransferObject\User;
+use Zend\Form\Element as Element;
+use Zend\Form\Element\Submit;
+use Zend\Form\Form;
+use Zend\Form\View\Helper\FormElementErrors;
+use Zend\Form\View\Helper\FormLabel;
+use Zend\Form\View\Helper\FormRadio;
+use Zend\Form\View\Helper\FormSelect;
+use Zend\Form\View\Helper\FormSubmit;
+use Zend\I18n\Translator\TranslatorInterface;
+
+/** @var FormLabel $formLabel */
+$formLabel = $this->formLabel();
+/**@var FormRadio $formRadio */
+$formRadio = $this->formRadio();
+/**@var FormSelect $formSelect */
+$formSelect = $this->formSelect();
+/**@var FormSubmit $formSubmit */
+$formSubmit = $this->formSubmit();
+/** @var FormElementErrors $formElementErrors */
+$formElementErrors = $this->formElementErrors();
+$formLabel->setTranslatorTextDomain('fid');
+$formSelect->setTranslatorTextDomain('fid');
+$formRadio->setTranslatorTextDomain('fid');
+$formSubmit->setTranslatorTextDomain('fid');
+$formElementErrors->setTranslatorTextDomain('fid');
+/** @var TranslatorInterface $translator */
+$translator = $this->getHelperPluginManager()->get('translate')
+    ->getTranslator();
+
+$formLabel->setTranslator($translator);
+$formElementErrors->setTranslator($translator);
+
+/** @var Form $form */
+/** @var User $user */
+$user = $this->user;
+$userId = $user->getId();
+$form = $this->form;
+$form->setAttribute('method', 'post');
+$form->setAttribute('action', $this->url('fid/admin/edit',['userid' => $userId]));
+$form->setAttribute('class', 'form-horizontal');
+$form->prepare();
+
+$this->headTitle($this->translate('Profile Form'));
+$this->headTitle($this->translate("fid::user_update_form_title"));
+?>
+<!-- fid: admin - edit -->
+    <h2><?= $this->translate("fid::user_edit_form_title",['%%userid%%' => $userId, '%%username%%' => $user->getUsername()]) ?></h2>
+<?= $this->flashmessages() ?>
+<?= $this->form()->openTag($form) ?>
+<?php
+/** @var Element\Hidden $elemUserId */
+$elemUserId = $form->get('userId');
+$elemUserId->setValue($userId);
+?>
+    <div class="form-group"><?=$this->formHidden($elemUserId)?></div>
+
+<? /* home library */ ?>
+<?php
+/** @var Element\Select $elemHomeLibrary */
+$elemHomeLibrary = $form->get('homeLibrary');
+$elemHomeLibrary->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+$elemHomeLibrary->setAttributes(['class' => 'form-control inline col-sm-6']);
+$elemHomeLibrary->setValue($user->getHomeLibrary());
+if (!in_array('HomeLibrary',$editableFields)) {
+    $elemHomeLibrary->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemHomeLibrary) ?>
+        <?= $this->formSelect($elemHomeLibrary) ?>
+        <?= $this->formElementErrors($elemHomeLibrary) ?>
+    </div>
+
+<? /* salutation */ ?>
+<?php
+/** @var Element\Select $elemSalutation */
+$elemSalutation = $form->get('salutation');
+$elemSalutation->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+$elemSalutation->setAttributes(['class' => 'form-control inline col-sm-2']);
+$elemSalutation->setValue($user->getSalutation());
+if (!in_array('Salutation',$editableFields)) {
+    $elemSalutation->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemSalutation) ?>
+        <?= $this->formSelect($elemSalutation) ?>
+
+    </div>
+
+<? /* academic title */ ?>
+<?php
+/** @var Element\Text $elemAcademicTitle */
+$elemAcademicTitle = $form->get('academicTitle');
+$elemAcademicTitle->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+$elemAcademicTitle->setAttributes(['class' => 'form-control']);
+$elemAcademicTitle->setValue($user->getAcademicTitle());
+if (!in_array('AcademicTitle',$editableFields)) {
+    $elemAcademicTitle->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemAcademicTitle) ?>
+        <?= $this->formElement($elemAcademicTitle) ?>
+    </div>
+
+<? /* firstname */ ?>
+<?php
+/** @var Element\Text $elemFirstname */
+$elemFirstname = $form->get('firstname');
+$elemFirstname->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+$elemFirstname->setAttributes(['class' => 'form-control']);
+$elemFirstname->setValue($user->getFirstname());
+if (!in_array('Firstname',$editableFields)) {
+    $elemFirstname->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemFirstname) ?>
+        <?= $this->formElement($elemFirstname) ?>
+        <?= $this->formElementErrors($elemFirstname) ?>
+    </div>
+
+<? /* lastname */ ?>
+<?php
+/** @var Element\Text $elemLastname */
+$elemLastname = $form->get('lastname');
+$elemLastname->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+$elemLastname->setAttributes(['class' => 'form-control']);
+$elemLastname->setValue($user->getLastname());
+if (!in_array('Lastname',$editableFields)) {
+    $elemLastname->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemLastname) ?>
+        <?= $this->formElement($elemLastname) ?>
+        <?= $this->formElementErrors($elemLastname) ?>
+    </div>
+
+<? /* year of birth */ ?>
+<?php
+/** @var Element\Text $elemYearOfBirth */
+$elemYearOfBirth = $form->get('yearOfBirth');
+$elemYearOfBirth->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+$elemYearOfBirth->setAttributes(['class' => 'form-control']);
+$elemYearOfBirth->setValue($user->getYearOfBirth());
+if (!in_array('YearOfBirth',$editableFields)) {
+    $elemYearOfBirth->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemYearOfBirth) ?>
+        <?= $this->formElement($elemYearOfBirth) ?>
+        <?= $this->formElementErrors($elemYearOfBirth) ?>
+    </div>
+
+<? /* college */ ?>
+<?php
+/** @var Element\Text $elemCollege */
+$elemCollege = $form->get('college');
+$elemCollege->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+$elemCollege->setAttributes(['class' => 'form-control']);
+$elemCollege->setValue($user->getCollege());
+if (!in_array('College',$editableFields)) {
+    $elemCollege->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemCollege) ?>
+        <?= $this->formElement($elemCollege) ?>
+        <?= $this->formElementErrors($elemCollege) ?>
+    </div>
+
+<? /* job title */ ?>
+<?php
+/** @var Element\Text $elemJobTitle */
+$elemJobTitle = $form->get('jobTitle');
+$elemJobTitle->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+$elemJobTitle->setAttributes(['class' => 'form-control']);
+$elemJobTitle->setValue($user->getJobTitle());
+if (!in_array('JobTitle',$editableFields)) {
+    $elemJobTitle->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemJobTitle) ?>
+        <?= $this->formElement($elemJobTitle) ?>
+        <?= $this->formElementErrors($elemJobTitle) ?>
+    </div>
+
+<? /* Permissions */ ?>
+<?php
+/** @var Element\MultiCheckbox $elemPermissions */
+$elemPermissions = $form->get('permissions');
+$elemPermissions->setLabelAttributes(['class' => 'inline col-md-4 col-sm-10']);
+if (!in_array('Permissions',$editableFields)) {
+    $elemPermissions->setAttribute('readonly', '1');
+}
+?>
+    <div class="form-group">
+        <?= $this->formLabel($elemPermissions) ?>
+        <div class="permission-options col-sm-7">
+            <?= $this->formMultiCheckbox($elemPermissions) ?>
+        </div>
+        <?= $this->formElementErrors($elemPermissions) ?>
+    </div>
+
+<? /* submit button */ ?>
+<?php
+/** @var Submit $elemSubmit */
+$elemSubmit = $form->get('submit');
+$elemSubmit->setAttributes(['class' => 'btn btn-primary']);
+?>
+    <div class="form-group">
+        <div class="col-lg-11 col-md-9 col-sm-11 col-xs-12">
+            <?= $this->formSubmit($elemSubmit) ?>
+            <a href="<?= $this->url('fid/admin/list') ?>"
+               class="btn btn-primary">
+                <?= $this->transEsc('Cancel') ?>
+            </a>
+        </div>
+    </div>
+
+<?= $this->form()->closeTag($form) ?>
+<!-- fid: admin - edit - END -->
\ No newline at end of file
diff --git a/themes/fid/templates/fid/admin/list-entry.phtml b/themes/fid/templates/fid/admin/list-entry.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..758790b43d39c1df1c9ad2ff3ee9d62db0b45931
--- /dev/null
+++ b/themes/fid/templates/fid/admin/list-entry.phtml
@@ -0,0 +1,17 @@
+<!-- fid: user - admin - list-entry -->
+<?php
+$permissions  = [];
+if (!empty($permissions = $user->getPermissions())) {
+    foreach ($permissions as $key => &$perm) {
+        $perm = $this->escapeHtml($key).' ('.$this->escapeHtml($perm).')';
+    }
+}
+foreach ($this->fields as $field):
+?>
+<?php if ($field === 'Permissions'): ?>
+    <td><?=implode(', ',$permissions)?></td>
+<?php else: ?>
+    <td><?=$this->escapeHtml($user->$field)?></td>
+<?php endif; ?>
+<?php endforeach; ?>
+<!-- fid: user - admin - list-entry - END -->
\ No newline at end of file
diff --git a/themes/fid/templates/fid/admin/list.phtml b/themes/fid/templates/fid/admin/list.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..a5c81b74f18d84ec99feefed4fec3d6b9dbd1965
--- /dev/null
+++ b/themes/fid/templates/fid/admin/list.phtml
@@ -0,0 +1,21 @@
+<!-- fid - user - admin - list -->
+<?=$this->translate('Users')?>
+<?= $this->flashmessages() ?>
+<?php if (!empty($this->list)): ?>
+    <table class="fid fid-admin table user-table table-striped">
+    <tr>
+    <td><!-- empty cell --></td>
+    <th>#</th>
+    <?php foreach ($fields as $fieldname): ?>
+        <th><?=$this->translate('fid::'.$fieldname)?></th>
+    <?php endforeach; ?>
+    </tr>
+    <?php foreach ($list as $id => $user):?>
+        <?php $tooltip = $this->translate('fid::user_edit',['%%userid%%' => $id]); ?>
+        <tr><td><a href="<?=$this->url('fid/admin/edit',['userid' => $id])?>" title="<?=$tooltip?>"><i class="fa fa-pencil-square-o"></i><span class="sr-only"><?=$tooltip?></span></a></td><th><?=$id?></th><?= $this->render('fid/admin/list-entry',['user' => $user,'fields'=>$fields]) ?></tr>
+    <?php endforeach; ?>
+    </table>
+<?php else: ?>
+    <?= $this->translate('fid::user_list_empty') ?>
+<?php endif; ?>
+<!-- fid - user - admin - list - END -->
\ No newline at end of file
diff --git a/themes/fid/templates/fid/user/username-change.phtml b/themes/fid/templates/fid/user/username-change.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..4d9f6945dfcb05cf80734001916971165d550969
--- /dev/null
+++ b/themes/fid/templates/fid/user/username-change.phtml
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright (C) 2019 Leipzig University Library
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * @author   Gregor Gawol <gawol@ub.uni-leipzig.de>
+ * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU GPLv2
+ */
+
+use Zend\Form\Element;
+use Zend\Form\Form;
+use Zend\Form\View\Helper\FormElementErrors;
+use Zend\Form\View\Helper\FormLabel;
+use Zend\Form\View\Helper\FormSubmit;
+use Zend\I18n\Translator\TranslatorInterface;
+
+/** @var FormLabel $formLabel */
+$formLabel = $this->formLabel();
+/**@var FormSubmit $formSubmit */
+$formSubmit = $this->formSubmit();
+/** @var FormElementErrors $formElementErrors */
+$formElementErrors = $this->formElementErrors();
+
+$formLabel->setTranslatorTextDomain('fid');
+$formSubmit->setTranslatorTextDomain('fid');
+$formElementErrors->setTranslatorTextDomain('fid');
+/** @var TranslatorInterface $translator */
+$translator = $this->getHelperPluginManager()->get('translate')
+    ->getTranslator();
+$formLabel->setTranslator($translator);
+$formElementErrors->setTranslator($translator);
+
+/** @var Form $form */
+$form = $this->form;
+$form->setAttribute('method', 'post');
+$form->setAttribute('action', $this->url('fid/user/change-username'));
+$form->setAttribute('class', 'registration');
+$form->prepare();
+
+$this->headTitle($this->translate("fid::username_change_form_title"));
+?>
+
+<h2><?= $this->translate("fid::username_change_form_title") ?></h2>
+
+<div class="subito-pg">
+    * <?=$this->transEsc("This field is required")?>
+</div>
+
+<?= $this->flashmessages() ?>
+<?= $this->form()->openTag($form) ?>
+<br/>
+<? /* username */ ?>
+<?php
+/** @var Element\Text $elemUsername */
+$elemUsername = $form->get('username');
+$elemUsername->setLabelAttributes(['class' => 'control-label']);
+$elemUsername->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemUsername) ?>
+    <?= $this->formElement($elemUsername) ?>
+    <?= $this->formElementErrors($elemUsername) ?>
+</div>
+
+<? /* username confirmation */ ?>
+<?php
+/** @var Element\Text $elemUsernameConfirmation */
+$elemUsernameConfirmation = $form->get('usernameConfirmation');
+$elemUsernameConfirmation->setLabelAttributes(['class' => 'control-label']);
+$elemUsernameConfirmation->setAttributes(['class' => 'form-control']);
+?>
+<div class="form-group">
+    <?= $this->formLabel($elemUsernameConfirmation) ?>
+    <?= $this->formElement($elemUsernameConfirmation) ?>
+    <?= $this->formElementErrors($elemUsernameConfirmation) ?>
+</div>
+
+<? /* submit button */ ?>
+<?php
+/** @var Element\Submit $elemSubmit */
+$elemSubmit = $form->get('submit');
+$elemSubmit->setAttributes(['class' => 'btn btn-primary']);
+?>
+<div class="form-group">
+    <a class="back-to-login btn btn-link" href="<?=$this->url('myresearch-userlogin') ?>">
+        <i class="fa fa-chevron-left" aria-hidden="true"></i>
+        <?=$this->transEsc('Back')?>
+    </a>
+    <?= $this->formElement($elemSubmit) ?>
+</div>
+<?= $this->form()->closeTag($form) ?>
diff --git a/themes/fid/templates/myresearch/menu.phtml b/themes/fid/templates/myresearch/menu.phtml
index c4691604ba8802848fb6fd96aef1ae2bcf946a91..3813038b0a516fb8724acfcd35ca32013bbbedc2 100644
--- a/themes/fid/templates/myresearch/menu.phtml
+++ b/themes/fid/templates/myresearch/menu.phtml
@@ -69,6 +69,15 @@
       </a>
     <? endif; ?>
 
+    <?php if ($this->auth()->isLoggedIn()): ?>
+      <a href="<?=$this->url('fid/user/change-username')?>" data-lightbox>
+        <span class="no-padding">
+          <i class="fa fa-fw fa-envelope" aria-hidden="true"></i>
+        </span>
+        <?=$this->transEsc('fid::username_change_link')?>
+      </a>
+    <? endif; ?>
+
     <?php if ($user = $this->auth()->isLoggedIn()): ?>
       <span class="logout-button">
         <a href="<?=$this->url('myresearch-logout')?>">