diff --git a/server/controllers/api/user/password/index.js b/server/controllers/api/user/password/index.js
new file mode 100644
index 00000000..e1e3cff3
--- /dev/null
+++ b/server/controllers/api/user/password/index.js
@@ -0,0 +1,69 @@
+const { handleErrorResponse } = require('../../../utils/errorHandlers.js');
+const logger = require('winston');
+const db = require('../../../../models');
+const { auth: { masterPassword } } = require('../../../../../config/siteConfig.js');
+
+/*
+
+  route to update a password
+
+*/
+
+const updateUserPassword = ({ ip, originalUrl, body }, res) => {
+  let userRecord;
+  const { userName, oldPassword, newPassword } = body;
+
+  if (!masterPassword) {
+    return res.status(400).json({
+      success: false,
+      message: 'no master password set in site config',
+    });
+  }
+
+  if (!userName || !oldPassword || !newPassword) {
+    return res.status(400).json({
+      success: false,
+      message: 'body should include userName (channel name without the @), oldPassword, & newPassword',
+    });
+  }
+
+  db.User.findOne({
+    where: {
+      userName,
+    },
+  })
+  .then(user => {
+    userRecord = user;
+    if (!userRecord) {
+      throw new Error('no user found');
+    }
+    if (oldPassword === masterPassword) {
+      logger.debug('master password provided');
+      return true;
+    } else {
+      logger.debug('old password provided');
+      return userRecord.comparePassword(oldPassword);
+    }
+  })
+  .then(isMatch => {
+    if (!isMatch) {
+      throw new Error('Incorrect old password.');
+    }
+    logger.debug('Password was a match, updating password');
+    return userRecord.changePassword(newPassword);
+  })
+  .then(() => {
+    logger.debug('Password successfully updated');
+    return res.status(200).json({
+      success: true,
+      message: 'Password successfully updated',
+      oldPassword,
+      newPassword,
+    });
+  })
+  .catch((error) => {
+    handleErrorResponse(originalUrl, ip, error, res);
+  });
+};
+
+module.exports = updateUserPassword;
diff --git a/server/routes/api/index.js b/server/routes/api/index.js
index 4eda3f2a..0aabd472 100644
--- a/server/routes/api/index.js
+++ b/server/routes/api/index.js
@@ -12,6 +12,7 @@ const claimPublish = require('../../controllers/api/claim/publish');
 const claimResolve = require('../../controllers/api/claim/resolve');
 const claimShortId = require('../../controllers/api/claim/shortId');
 const fileAvailability = require('../../controllers/api/file/availability');
+const userPassword = require('../../controllers/api/user/password');
 
 const multipartMiddleware = require('../utils/multipartMiddleware');
 
@@ -33,4 +34,6 @@ module.exports = (app) => {
   app.get('/api/claim/short-id/:longId/:name', claimShortId);
   // file routes
   app.get('/api/file/availability/:name/:claimId', fileAvailability);
+  // user routes
+  app.put('/api/user/password/', userPassword);
 };