diff --git a/src/api/users.js b/src/api/users.js
index 8298eeca047c6b890bbe5f84061401adca901fca..642dd1a7d9bb888640f218d536f38cf74feb1f5b 100644
--- a/src/api/users.js
+++ b/src/api/users.js
@@ -71,6 +71,25 @@ export async function fetchUser(id, authHost, token) {
   })
 }
 
+export async function fetchUserCredentials(nickname, authHost, token) {
+  return await request({
+    baseURL: baseName(authHost),
+    url: `/api/pleroma/admin/users/${nickname}/credentials`,
+    method: 'get',
+    headers: authHeaders(token)
+  })
+}
+
+export async function updateUserCredentials(nickname, credentials, authHost, token) {
+  return await request({
+    baseURL: baseName(authHost),
+    url: `/api/pleroma/admin/users/${nickname}/credentials`,
+    method: 'patch',
+    headers: authHeaders(token),
+    data: credentials
+  })
+}
+
 export async function fetchUsers(filters, authHost, token, page = 1) {
   return await request({
     baseURL: baseName(authHost),
diff --git a/src/lang/en.js b/src/lang/en.js
index 8b8e9ff7a6ec7f740b78f1e06524a77058d9f677..5e98a3cbf164523675491d78d55b66185e2720c5 100644
--- a/src/lang/en.js
+++ b/src/lang/en.js
@@ -261,7 +261,22 @@ export default {
     activeUppercase: 'Active',
     active: 'active',
     deactivated: 'deactivated',
-    noStatuses: 'No statuses to show'
+    noStatuses: 'No statuses to show',
+    securitySettings: {
+      email: 'Email',
+      password: 'Password',
+      securitySettings: 'Security settings',
+      passwordChangeWarning1: 'Setting a new password will cause the user to be signed out from any client they have used before.',
+      passwordChangeWarning2: 'When the user signs in with this password, they will be asked to set a new one.',
+      passwordLengthNotice: 'Make sure it\'s at least {minLength} characters long.',
+      inputNewEmail: 'Input new email',
+      inputNewPassword: 'Input new password',
+      passwordUpdated: 'The password has been updated',
+      emailUpdated: 'The email has been updated',
+      success: 'Success',
+      submit: 'Submit',
+      close: 'Close'
+    }
   },
   usersFilter: {
     inputPlaceholder: 'Select filter',
diff --git a/src/store/modules/userProfile.js b/src/store/modules/userProfile.js
index 5a7e4394cd84e6019256c5b3b63ae38ad556c510..af54072c5205783fcb16a37ea55274665a98ff21 100644
--- a/src/store/modules/userProfile.js
+++ b/src/store/modules/userProfile.js
@@ -1,10 +1,11 @@
-import { fetchUser, fetchUserStatuses } from '@/api/users'
+import { fetchUser, fetchUserStatuses, fetchUserCredentials, updateUserCredentials } from '@/api/users'
 
 const userProfile = {
   state: {
     statuses: [],
     statusesLoading: true,
     user: {},
+    userCredentials: {},
     userProfileLoading: true
   },
   mutations: {
@@ -19,6 +20,9 @@ const userProfile = {
     },
     SET_USER_PROFILE_LOADING: (state, status) => {
       state.userProfileLoading = status
+    },
+    SET_USER_CREDENTIALS: (state, userCredentials) => {
+      state.userCredentials = userCredentials
     }
   },
   actions: {
@@ -38,6 +42,14 @@ const userProfile = {
 
       commit('SET_STATUSES', statuses.data)
       commit('SET_STATUSES_LOADING', false)
+    },
+    async FetchUserCredentials({ commit, getters }, { nickname }) {
+      const userResponse = await fetchUserCredentials(nickname, getters.authHost, getters.token)
+      commit('SET_USER_CREDENTIALS', userResponse.data)
+    },
+    async UpdateUserCredentials({ dispatch, getters }, { nickname, credentials }) {
+      await updateUserCredentials(nickname, credentials, getters.authHost, getters.token)
+      dispatch('FetchUserCredentials', { nickname })
     }
   }
 }
diff --git a/src/views/users/components/SecuritySettingsModal.vue b/src/views/users/components/SecuritySettingsModal.vue
new file mode 100644
index 0000000000000000000000000000000000000000..58c757b1bb24e82b5c9c3eacad327e6710da8218
--- /dev/null
+++ b/src/views/users/components/SecuritySettingsModal.vue
@@ -0,0 +1,155 @@
+<template>
+  <el-dialog
+    :before-close="close"
+    :title="$t('userProfile.securitySettings.securitySettings')"
+    :visible="visible"
+    class="security-settings-modal">
+    <el-row>
+      <p>
+        <label>
+          {{ $t('userProfile.securitySettings.email') }}
+        </label>
+      </p>
+    </el-row>
+    <el-row>
+      <el-input
+        :placeholder="$t('userProfile.securitySettings.inputNewEmail')"
+        v-model="emailForm.newEmail" />
+    </el-row>
+    <br>
+    <el-row type="flex" justify="end">
+      <el-button
+        :loading="emailForm.isLoading"
+        :disabled="!emailForm.newEmail || emailForm.newEmail === userCredentials.email"
+        type="primary"
+        @click="updateEmail()">
+        {{ $t('userProfile.securitySettings.submit') }}
+      </el-button>
+    </el-row>
+    <el-row>
+      <p>
+        <label>
+          {{ $t('userProfile.securitySettings.password') }}
+        </label>
+      </p>
+    </el-row>
+    <el-row>
+      <el-input
+        :placeholder="$t('userProfile.securitySettings.inputNewPassword')"
+        v-model="passwordForm.newPassword"
+        show-password />
+      <small class="form-text">
+        {{ $t('userProfile.securitySettings.passwordLengthNotice', { minLength: 8 }) }}
+      </small>
+      <br>
+      <el-alert
+        :closable="false"
+        type="warning"
+        show-icon>
+        <p>{{ $t('userProfile.securitySettings.passwordChangeWarning1') }}</p>
+        <p>{{ $t('userProfile.securitySettings.passwordChangeWarning2') }}</p>
+      </el-alert>
+    </el-row>
+    <br>
+    <el-row type="flex" justify="end">
+      <el-button
+        :loading="passwordForm.isLoading"
+        :disabled="passwordForm.newPassword.length < 8"
+        type="primary"
+        @click="updatePassword()">
+        {{ $t('userProfile.securitySettings.submit') }}
+      </el-button>
+    </el-row>
+  </el-dialog>
+</template>
+
+<script>
+
+export default {
+  name: 'SecuritySettingsModal',
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    user: {
+      type: Object,
+      default: function() {
+        return {}
+      }
+    }
+  },
+  data() {
+    return {
+      emailForm: {
+        newEmail: '',
+        isLoading: false
+      },
+      passwordForm: {
+        newPassword: '',
+        isLoading: false
+      }
+    }
+  },
+  computed: {
+    userCredentials() {
+      return this.$store.state.userProfile.userCredentials
+    }
+  },
+  mounted: async function() {
+    await this.$store.dispatch('FetchUserCredentials', { nickname: this.user.nickname })
+    this.emailForm.newEmail = this.userCredentials.email
+  },
+  methods: {
+    async updateEmail() {
+      const credentials = { email: this.emailForm.newEmail }
+      this.emailForm.isLoading = true
+      await this.$store.dispatch('UpdateUserCredentials', { nickname: this.user.nickname, credentials })
+      this.emailForm.isLoading = false
+      this.$notify.success({
+        title: this.$t('userProfile.securitySettings.success'),
+        message: this.$t('userProfile.securitySettings.emailUpdated'),
+        duration: 2000
+      })
+    },
+    async updatePassword() {
+      const credentials = { password: this.passwordForm.newPassword }
+      this.passwordForm.isLoading = true
+      await this.$store.dispatch('UpdateUserCredentials', { nickname: this.user.nickname, credentials })
+      this.passwordForm.isLoading = false
+      this.passwordForm.newPassword = ''
+      this.$notify.success({
+        title: this.$t('userProfile.securitySettings.success'),
+        message: this.$t('userProfile.securitySettings.passwordUpdated'),
+        duration: 2000
+      })
+    },
+    close() {
+      this.$emit('close', true)
+    }
+  }
+}
+</script>
+
+<style rel='stylesheet/scss' lang='scss'>
+@media all and (max-width: 800px) {
+  .security-settings-modal {
+    .el-dialog {
+      width: 90%;
+    }
+  }
+}
+
+.security-settings-modal {
+  .el-alert .el-alert__description {
+    word-break: break-word;
+    font-size: 1em;
+  }
+
+  .form-text {
+    display: block;
+    margin-top: .25rem;
+    color: #909399;
+  }
+}
+</style>
diff --git a/src/views/users/show.vue b/src/views/users/show.vue
index fd24486ddc1575bf11fbcde36ac6a6a28b6da3c8..84cfef323022fe30b37df302e70f3397f7b808ed 100644
--- a/src/views/users/show.vue
+++ b/src/views/users/show.vue
@@ -73,6 +73,18 @@
                   <el-tag v-if="user.deactivated" type="danger">{{ $t('userProfile.deactivated') }}</el-tag>
                 </td>
               </tr>
+              <tr class="el-table__row">
+                <td>
+                  <el-button icon="el-icon-lock" @click="securitySettingsModalVisible = true">
+                    {{ $t('userProfile.securitySettings.securitySettings') }}
+                  </el-button>
+                  <SecuritySettingsModal
+                    :user="user"
+                    :visible="securitySettingsModalVisible"
+                    @close="securitySettingsModalVisible = false" />
+                </td>
+                <td />
+              </tr>
             </tbody>
           </table>
         </div>
@@ -96,14 +108,16 @@
 <script>
 import Status from '@/components/Status'
 import ModerationDropdown from './components/ModerationDropdown'
+import SecuritySettingsModal from './components/SecuritySettingsModal'
 
 export default {
   name: 'UsersShow',
-  components: { ModerationDropdown, Status },
+  components: { ModerationDropdown, Status, SecuritySettingsModal },
   data() {
     return {
       showPrivate: false,
-      resetPasswordDialogOpen: false
+      resetPasswordDialogOpen: false,
+      securitySettingsModalVisible: false
     }
   },
   computed: {
@@ -127,6 +141,9 @@ export default {
     },
     userProfileLoading() {
       return this.$store.state.userProfile.userProfileLoading
+    },
+    userCredentials() {
+      return this.$store.state.userProfile.userCredentials
     }
   },
   mounted: function() {