Change Password Script Templates
The Change Password script implements the defined function to change the specified user's password in the external database. We recommend naming this function changePassword
.
The script is used only in a legacy authentication scenario and is required if you want to change a user's password in the external database. It will execute when a user performs a password reset workflow, or when a password change workflow is started from the Auth0 Dashboard or the Auth0 Management API.
ChangePassword function
The changePassword
function should:
Update the user's password in the external database.
Return
true
(or an object containing thelast_password_reset
property) if the password change operation succeeded. If thelast_password_reset
property is present in the object, it will be updated on the user's profile.Return
false
if the password change operation failed.Return an error if the external database could not be reached.
Definition
The changePassword
function accepts three parameters and returns a callback
function:
changePassword(email, newPassword, callback): function
Was this helpful?
Parameter | Type | Description |
---|---|---|
email |
String | User's email address in Auth0 and external database. |
newPassword |
String | Value to be set as user's new password in the external database. This value is sent as plaintext to the function and should be encrypted before being sent to the external database. |
callback |
Function | Used to pass data or operation result data through the pipeline. |
Example
This is a pseudo-JavaScript example of how you could implement the changePassword
function. For language-specific examples, read Language-specific script examples.
function changePassword(email, newPassword, callback) {
// Hash the provided password
let hashedPassword = hash(newPassword);
// Prepare the API call
let options = {
url: "https://example.com/api/users",
body: {
email: email,
password: hashedPassword
}
};
// Call the API
send(options, err => {
if (err && err.id == "FAIL_CHANGE_PASSWORD") {
// Return false in callback if password change failed
return callback(null, false);
} else if (err) {
// Return error in callback if other error occurred
return callback(new Error("My custom error message.");
} else {
// Return true in callback if password change operation succeeded
return callback(null, true);
// Or return an object containing the `last_password_reset` property
// if the password change operation succeeded.
// If the `last_password_reset` property is present in the object,
// it will be updated on the user's profile.
return callback(null, { "last_password_reset": Date.now() });
}
});
}
Was this helpful?
Encryption
To prevent any potential data leak, encrypt the password value using a cryptographic hash encryption library such as bcrypt
.
Example
bcrypt.hash(password, 10, function (err, hash) {
if (err) {
return callback(err);
} else {
// Return hashed password
}
});
Was this helpful?
Callback function
The callback
function accepts two parameters and is used to pass error data or indicate the result of the operation.
Definition
callback(error, operationResult | resultObj): function
Was this helpful?
Parameter | Type | Required | Description |
---|---|---|---|
error |
Object | Required | Contains error data. |
operationResult |
Boolean | Optional | Indicates the result of the change password operation. |
resultObj |
Object | Optional | Indicates that the change password operation succeeded. If the last_password_reset property is present, it will be updated on the user's profile. |
Return a success
If the change password operation succeeded, return the callback
function, and pass a null
value as the error
parameter and a true
value as the operationResult
parameter.
Example
return callback(null, true);
Was this helpful?
Return a success and update last_password_reset attribute
If the change password operation succeeded, return the callback
function, and pass a null
value as the error
parameter and an object value as the profile
parameter. If last_password_reset
attribute is provided in the object, it will be updated on the user's profile.
Example
return callback(null, { "last_password_reset": Date.now() });
Was this helpful?
Return a failure
If the change password operation failed, return the callback
function, and pass a null
value as the error
parameter and a false
value as the operationResult
parameter.
Example
return callback(null, false);
Was this helpful?
Return an error
If an error occurs, return callback
function, and pass relevant error information as the error
parameter.
Example
return callback(new Error("My custom error message."));
Was this helpful?
Language-specific script examples
Auth0 provides sample scripts for use with the following languages/technologies:
JavaScript
function changePassword(email, newPassword, callback) {
// This script should change the password stored for the current user in your
// database. It is executed when the user clicks on the confirmation link
// after a reset password request.
// The content and behavior of password confirmation emails can be customized
// here: https://manage.auth0.com/#/emails
// The `newPassword` parameter of this function is in plain text. It must be
// hashed/salted to match whatever is stored in your database.
//
// There are three ways that this script can finish:
// 1. The user's password was updated successfully:
// callback(null, true);
// 2. The user's password was not updated:
// callback(null, false);
// 3. Something went wrong while trying to reach your database:
// callback(new Error("my error message"));
//
// If an error is returned, it will be passed to the query string of the page
// to which the user is being redirected after clicking the confirmation link.
// For example, returning `callback(new Error("error"))` and redirecting to
// https://example.com would redirect to the following URL:
// https://example.com?email=alice%40example.com&message=error&success=false
const msg = 'Please implement the Change Password script for this database ' +
'connection at https://manage.auth0.com/#/connections/database';
return callback(new Error(msg));
}
Was this helpful?
ASP.NET Membership Provider (MVC3 - Universal Providers)
function changePassword(email, newPassword, callback) {
var crypto = require('crypto');
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES
var connection = new Connection({
userName: 'the username',
password: 'the password',
server: 'the server',
options: {
database: 'the db name',
// encrypt: true for Windows Azure enable this
}
});
/**
* hashPassword
*
* This function creates a hashed version of the password to store in the database.
*
* @password {[string]} the password entered by the user
* @return {[string]} the hashed password
*/
function hashPassword(password, salt) {
// the default implementation uses HMACSHA256 and since Key length is 64
// and default salt is 16 bytes, Membership will fill the buffer repeating the salt
var key = Buffer.concat([salt, salt, salt, salt]);
var hmac = crypto.createHmac('sha256', key);
hmac.update(Buffer.from(password, 'ucs2'));
var hashed = hmac.digest('base64');
return hashed;
}
connection.on('debug', function(text) {
// if you have connection issues, uncomment this to get more detailed info
//console.log(text);
}).on('errorMessage', function(text) {
// this will show any errors when connecting to the SQL database or with the SQL statements
console.log(JSON.stringify(text));
});
connection.on('connect', function (err) {
if (err) {
return callback(err);
}
updateMembershipUser(email, newPassword, function(err, wasUpdated) {
if (err) {
return callback(err); // this will return a 500
}
callback(null, wasUpdated);
});
});
function updateMembershipUser(email, newPassword, callback) {
var salt = crypto.randomBytes(16);
var hashedPassword = hashPassword(newPassword, salt);
var updateMembership =
'UPDATE Memberships '+
'SET Password=@NewPassword, PasswordSalt=@NewSalt, LastPasswordChangedDate=GETDATE() '+
'WHERE Email=@Email';
var updateMembershipQuery = new Request(updateMembership, function (membershipErr, membershipCount) {
if (membershipErr) {
return callback(membershipErr);
}
callback(null, membershipCount > 0);
});
updateMembershipQuery.addParameter('NewPassword', TYPES.VarChar, hashedPassword);
updateMembershipQuery.addParameter('NewSalt', TYPES.VarChar, salt.toString('base64'));
updateMembershipQuery.addParameter('Email', TYPES.VarChar, email);
connection.execSql(updateMembershipQuery);
}
}
Was this helpful?
ASP.NET Membership Provider (MVC4 - Simple Membership)
function changePassword(email, newPassword, callback) {
var crypto = require('crypto');
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES
var connection = new Connection({
userName: 'the username',
password: 'the password',
server: 'the server',
options: {
database: 'the db name',
// encrypt: true for Windows Azure enable this
}
});
/**
* hashPassword
*
* This function hashes a password using HMAC SHA256 algorithm.
*
* @password {[string]} password to be hased
* @salt {[string]} salt to be used in the hashing process
* @callback {[function]} callback to be called after hashing the password
*/
function hashPassword(password, salt, callback) {
var iterations = 1000;
var passwordHashLength = 32;
crypto.pbkdf2(password, salt, iterations, passwordHashLength, function (err, hashed) {
if (err) {
return callback(err);
}
var result = Buffer.concat([Buffer.from([0], 1), salt, Buffer.from(hashed, 'binary')]);
var resultBase64 = result.toString('base64');
callback(null, resultBase64);
});
}
connection.on('debug', function(text) {
// if you have connection issues, uncomment this to get more detailed info
//console.log(text);
}).on('errorMessage', function(text) {
// this will show any errors when connecting to the SQL database or with the SQL statements
console.log(JSON.stringify(text));
});
connection.on('connect', function (err) {
if (err) {
return callback(err);
}
updateMembershipUser(email, newPassword, function(err, wasUpdated) {
if (err) {
return callback(err); // this will return a 500
}
callback(null, wasUpdated);
});
});
function findUserId(email, callback) {
var findUserIdFromEmail =
'SELECT UserProfile.UserId FROM ' +
'UserProfile INNER JOIN webpages_Membership ' +
'ON UserProfile.UserId = webpages_Membership.UserId ' +
'WHERE UserName = @Email';
var findUserIdFromEmailQuery = new Request(findUserIdFromEmail, function (err, rowCount, rows) {
if (err) {
return callback(err);
}
// No record found with that email
if (rowCount < 1) {
return callback(null, null);
}
var userId = rows[0][0].value;
callback(null, userId);
});
findUserIdFromEmailQuery.addParameter('Email', TYPES.VarChar, email);
connection.execSql(findUserIdFromEmailQuery);
}
function updateMembershipUser(email, newPassword, callback) {
findUserId(email, function (err, userId) {
if (err) {
return callback(err);
}
if (userId === null) {
return callback();
}
var salt = crypto.randomBytes(16);
var updateMembership =
'UPDATE webpages_Membership '+
'SET Password=@NewPassword, PasswordChangedDate=GETDATE() '+
'WHERE UserId=@UserId';
var updateMembershipQuery = new Request(updateMembership, function (err, rowCount) {
if (err) {
return callback(err);
}
if (rowCount < 1) {
return callback();
}
callback(null, rowCount > 0);
});
hashPassword(newPassword, salt, function (err, hashedPassword) {
if (err) {
return callback(err);
}
updateMembershipQuery.addParameter('NewPassword', TYPES.VarChar, hashedPassword);
updateMembershipQuery.addParameter('UserId', TYPES.VarChar, userId);
connection.execSql(updateMembershipQuery);
});
});
}
}
Was this helpful?
MongoDB
function changePassword(email, newPassword, callback) {
const bcrypt = require('bcrypt');
const MongoClient = require('mongodb@3.1.4').MongoClient;
const client = new MongoClient('mongodb://user:pass@mymongoserver.com');
client.connect(function (err) {
if (err) return callback(err);
const db = client.db('db-name');
const users = db.collection('users');
bcrypt.hash(newPassword, 10, function (err, hash) {
if (err) {
client.close();
return callback(err);
}
users.update({ email: email }, { $set: { password: hash } }, function (err, count) {
client.close();
if (err) return callback(err);
callback(null, count > 0);
});
});
});
}
Was this helpful?
MySQL
function changePassword(email, newPassword, callback) {
const mysql = require('mysql');
const bcrypt = require('bcrypt');
const connection = mysql({
host: 'localhost',
user: 'me',
password: 'secret',
database: 'mydb'
});
connection.connect();
const query = 'UPDATE users SET password = ? WHERE email = ?';
bcrypt.hash(newPassword, 10, function(err, hash) {
if (err) return callback(err);
connection.query(query, [ hash, email ], function(err, results) {
if (err) return callback(err);
callback(null, results.length > 0);
});
});
}
Was this helpful?
PostgreSQL
function changePassword (email, newPassword, callback) {
//this example uses the "pg" library
//more info here: https://github.com/brianc/node-postgres
const bcrypt = require('bcrypt');
const postgres = require('pg');
const conString = 'postgres://user:pass@localhost/mydb';
postgres.connect(conString, function (err, client, done) {
if (err) return callback(err);
bcrypt.hash(newPassword, 10, function (err, hash) {
if (err) return callback(err);
const query = 'UPDATE users SET password = $1 WHERE email = $2';
client.query(query, [hash, email], function (err, result) {
// NOTE: always call `done()` here to close
// the connection to the database
done();
return callback(err, result && result.rowCount > 0);
});
});
});
}
Was this helpful?
SQL Server
function changePassword (email, newPassword, callback) {
//this example uses the "tedious" library
//more info here: http://tediousjs.github.io/tedious/
const bcrypt = require('bcrypt');
const sqlserver = require('tedious@1.11.0');
const Connection = sqlserver.Connection;
const Request = sqlserver.Request;
const TYPES = sqlserver.TYPES;
const connection = new Connection({
userName: 'test',
password: 'test',
server: 'localhost',
options: {
database: 'mydb'
}
});
const query = 'UPDATE dbo.Users SET Password = @NewPassword WHERE Email = @Email';
connection.on('debug', function(text) {
console.log(text);
}).on('errorMessage', function(text) {
console.log(JSON.stringify(text, null, 2));
}).on('infoMessage', function(text) {
console.log(JSON.stringify(text, null, 2));
});
connection.on('connect', function (err) {
if (err) return callback(err);
const request = new Request(query, function (err, rows) {
if (err) return callback(err);
callback(null, rows > 0);
});
bcrypt.hash(newPassword, 10, function (err, hash) {
if (err) return callback(err);
request.addParameter('NewPassword', TYPES.VarChar, hash);
request.addParameter('Email', TYPES.VarChar, email);
connection.execSql(request);
});
});
}
Was this helpful?
Windows Azure SQL Database
function changePassword (email, newPassword, callback) {
//this example uses the "tedious" library
//more info here: http://pekim.github.io/tedious/index.html
var Connection = require('tedious@1.11.0').Connection;
var Request = require('tedious@1.11.0').Request;
var TYPES = require('tedious@1.11.0').TYPES;
var bcrypt = require('bcrypt');
var connection = new Connection({
userName: 'your-user@your-server-id.database.windows.net',
password: 'the-password',
server: 'your-server-id.database.windows.net',
options: {
database: 'mydb',
encrypt: true
}
});
var query = 'UPDATE dbo.Users SET Password = @NewPassword ' +
'WHERE Email = @Email';
connection.on('debug', function(text) {
// Uncomment next line in order to enable debugging messages
// console.log(text);
}).on('errorMessage', function(text) {
console.log(JSON.stringify(text, null, 2));
}).on('infoMessage', function(text) {
// Uncomment next line in order to enable information messages
// console.log(JSON.stringify(text, null, 2));
});
connection.on('connect', function (err) {
if (err) { return callback(err); }
var request = new Request(query, function (err, rows) {
if (err) { return callback(err); }
console.log('rows: ' + rows);
callback(null, rows > 0);
});
bcrypt.hash(newPassword, 10, function (err, hash) {
if (err) { return callback(err); }
request.addParameter('NewPassword', TYPES.VarChar, hash);
request.addParameter('Email', TYPES.VarChar, email);
connection.execSql(request);
});
});
}
Was this helpful?