Navigation

Email/Password Authentication

Overview

The Email/Password authentication provider allows users to register accounts and log in using their email address and a password. Stitch must confirm Email/Password users before it allows them to login to your application.

Note

User email addresses are case-sensitive. For example, a user with the email address TestAccount@example.com could not log in using the testaccount@example.com address.

Configuration

You can enable and configure the Email/Password authentication provider from the Stitch UI by selecting Email/Password from the Users > Providers page.

Users may choose one of three ways to handle user confirmation:

Users can choose one of two ways to handle password resets:

You can enable and configure the Email/Password authentication provider with stitch-cli by importing an application directory that contains a configuration file for the provider.

The configuration file must be named local-userpass.json and stored in the /auth_providers directory. Configuration files for the Email/Password authentication provider have the following form:

/auth_providers/local-userpass.json
{
  "name": "local-userpass",
  "type": "local-userpass",
  "config": {
    "autoConfirm": <boolean>,
    "emailConfirmationUrl": <string>,
    "confirmEmailSubject": <string>,
    "runConfirmationFunction": <boolean>,
    "confirmationFunctionName": <string>,
    "resetPasswordUrl": <string>,
    "resetPasswordSubject": <string>,
    "runResetFunction": <boolean>,
    "resetFunctionName": <string>,
  },
  "disabled": <boolean>
}

User Confirmation

MongoDB Stitch confirms Email/Password authentication provider users in one of three ways:

Send a Confirmation Email

If you configure the provider to Send a Confirmation Email, Stitch sends a confirmation email to the email address provided by new Email/Password users when they register an account. The email contains a link to a confirmation URL that the user must visit this URL within 30 minutes to confirm that they control the email address. For an example of how to confirm a new Email/Password identity using the Stitch SDK, see Confirm a New User’s Email Address.

Configure the following settings to have Stitch automatically send a confirmation email:

  • Email Confirmation URL: the base of the URL included in every confirmation email. Stitch appends a unique token and tokenId to this URL as query parameters to create a unique link for every confirmation. To confirm the user, extract these query parameters from the user’s unique URL and pass the token and tokenId to the Client SDK’s confirmUser function.
  • Email Confirmation Subject: the subject of the email sent to the user containing the confirmation URL. This value is optional: if omitted, Stich uses a default subject line instead. Custom email confirmation subjects can contain a maximum of 256 characters.

Use Deep Links in Mobile Apps

Mobile applications can handle email confirmation directly in the app by configuring deep linking in Android or universal links in iOS.

Run a Confirmation Function

If you configure the provider to Run a Confirmation Function, Stitch runs a Function whenever a new Email/Password user registers an account. Stitch passes this function unique confirmation tokens and data about the user which allows you to define custom logic to confirm users. The return value of this function determines whether Stitch immediately confirms the user or requires additional confirmation from the client application.

You can use a custom confirmation function to define your own confirmation flows, such as the following examples:

  • Send custom confirmation emails from a specific domain with a particular template using an external service.
  • Read user permissions from a collection in a MongoDB Atlas instance or an external REST service to confirm whether a user is authorized to use the application or not.
  • Send confirmation messages through a service other than email.

Configure the following settings to have Stitch automatically run a confirmation function:

  • Function: the function run when a user registers a new account with your Stitch application. This function must return an object containing a status key mapping to a string with one of the following values: success, pending, or fail.

The custom confirmation function signature has one parameter: an object containing user data and confirmation tokens. The following table describes the fields found in the object passed to the custom user confirmation function:

Field Description
username The email address of the user.
token A unique value that can be used to confirm the user’s identity using the SDK confirmUser function.
tokenId A unique value that can be used to confirm the user’s identity using the SDK confirmUser function.

The following table describes the potential values of the status field in the object returned by the custom user confirmation function:

Status Effect
success Stitch confirms the user’s identity, allowing the user to log into their new account.
pending Stitch changes the user’s confirmation status to pending but the client application must call the confirmUser SDK function to fully confirm the user’s identity and allow login. For an example of user confirmation, see Confirm a New User’s Email Address.
fail Stitch deletes the pending user. The user can only retry account confirmation by registering an entirely new account. Since the previous account no longer exists, the same username can be reused.

A user confirmation function is generally structured as follows:

exports = ({ token, tokenId, username }) => {
   // validate the username
   const isValidEmail = myFakeValidator.validate(username);

   // check if the user is privileged for this service
   const isPrivileged = myFakeAuth.hasAccess(username, 'myFakeService')

   // send a message to the user in some way so that the user can confirm themselves
   const msgSendSuccessful = isValidEmail && isPrivileged && myFakeMsgr.send(username, token, tokenId)

   if ( msgSendSuccessful ) {
      return { status: 'pending' };
   } else {
      return { status: 'fail' };
   }
}

Automatically Confirm Users

If you configure the provider to Automatically Confirm Users, Stitch immediately confirms new Email/Password users after registration. When selected, Stitch does not validate email addresses and does not send any email to the user.

Warning

Stitch does not validate automatically confirmed email addresses. As a result, there are a few reasons you may not be able to contact such users via email:

  • An automatically confirmed user’s email address might not actually belong to that user. (e.g. a user could sign up as steve.jobs@apple.com)
  • A user’s email address may not even be a valid email address. (e.g. a user could sign up as my.name@gmail or asdavaskljj)

Exercise caution with this option, as securely resetting the password of a user account with no valid contact information can be very difficult.

Password Resets

MongoDB Stitch resets Email/Password authentication provider user passwords in one of two ways:

Send a Password Reset Email

If you configure the provider to Send a Password Reset Email, Stitch sends a Password Reset URL to a user’s email address when a user requests a password reset. The user must visit this URL within 30 minutes to confirm their intent to change their password. For an example of how to reset the password of an Email/Password identity using the Stitch SDK, see Reset a User’s Password.

Configure the following settings to have Stitch automatically send a password reset email:

  • Password Reset URL: the base of the URL included in every password reset email. Stitch appends a unique token and tokenId to this URL as query parameters to create a unique link for every password reset. To reset the user’s password, extract these query parameters from the user’s unique URL and pass the token and tokenId to the Client SDK’s resetPassword function.
  • Reset Password Email Subject: the subject line of the email that Stitch sends to users when they request to reset their password. This value is optional: if omitted, Stich uses a default subject line instead. Custom password reset subjects can contain a maximum of 256 characters.

Use Deep Links in Mobile Apps

Mobile applications can handle password resets directly in the app by configuring deep linking in Android or universal links in iOS.

Run a Password Reset Function

If you configure the provider to Run a Password Reset Function, Stitch runs a function that you define whenever the client SDK callResetPasswordFunction() function is called. Stitch passes this function unique confirmation tokens and data about the user which allows you to define custom logic to reset a user’s password. The value that you return from the function determines whether Stitch immediately resets the user’s password or requires additional confirmation from the client application.

You can use a custom password reset function to define your own password reset flows, such as the following examples:

  • Send custom password reset emails from a specific domain with a particular template using an external service.
  • Interface with a MongoDB Atlas collection to implement a password reset “cooldown period” to prevent too many password reset attempts on a single account in a particular time range.
  • Send custom password reset messages through a service other than email.

Configure the following settings to have Stitch automatically run a password reset function:

  • Function: the function run when an instance of the client SDK calls the callResetPasswordFunction function. This function must return an object containing a status key mapping to a string with one of the following values: success, pending, or fail.

Note

If you configure the provider to use a password reset function then the client SDK sendResetPasswordEmail() function will return an error. You may still need to call resetPassword() if the password reset function returns a pending status.

The custom password reset function signature is variadic: it accepts any number of parameters. The first of these parameters is always an object containing user data and confirmation tokens. All parameters after the first are custom parameters passed into the Client SDK as an argument collection. For instance, the Client SDK call:

callResetPasswordFunction("myUsername", "newPassword", ["Security Question Answer 1", "Security Question Answer 2", "securityCode:0510"])

Would be translated into the following custom password reset function signature:

resetFunc({username, password, token, tokenId}, securityAnswer1, securityAnswer2, securitySMSCode)

Each element of the custom argument array is spread into a parameter for the custom password reset function, starting with the second parameter.

The following table describes the fields found in the object passed to the custom password reset function as the first parameter:

Field Description
username The email address of the user.
password A new proposed password for the user. If this function returns the successful status, the user’s password will be updated to this value.
token A unique value that can be used to update the user’s password.
tokenId A unique value that can be used to confirm the user’s identity using the SDK confirmUser function.

The following table describes the potential values of the status field in the object returned by the custom password reset function:

Status Effect
success Stitch changes the user’s password to the provided password parameter immediately. Only recommended if your application can authenticate the user in the custom function itself through some secure means, such as a security question.
pending Stitch waits for client application to reset the user’s password using the Client SDK resetPassword function. For an example of how to reset the password of an Email/Password identity using the Stitch SDK, see Reset a User’s Password. The user’s password is not affected unless the client application calls the resetPassword function.
fail Nothing happens.

A custom password reset function is generally structured as follows:

exports = ({ token, tokenId, username, password }) => {
   // check if the username corresponds to a real user
   const isUser = myFakeValidator.validate(username);

   // check if the user has requested a password reset too often recently
   const isNotCoolingDown = myFakeCooldownService.canReset(username, 'myFakeService')

   // send a message to the user in some way so that the user can confirm themselves
   const msgSendSuccessful = isUser && isNotCoolingDown && myFakeMsgr.send(username, token, tokenId)

   if ( msgSendSuccessful ) {
      return { status: 'pending' };
   } else {
      return { status: 'fail' };
   }
}

Warning

The Stitch client SDK function callResetPasswordFunction is not authenticated because it is intended for password recovery for users who cannot log into their account otherwise. As a result, you cannot associate any call to this function with a specific Stitch user. Returning a success status from your custom password reset function permanently changes the password to the new value in the password parameter of the function, so returning success can result in any user resetting the password of any other application user. Because of this, it is recommended to always return a pending status after sending the actual account owner a message via a trusted mode of communication.

Usage

Authenticate a User

To log an existing user in to your application, create a UserPasswordCredential instance with the user’s email address and password, and provide that credential instance to the StitchAuth.loginWithCredential() method.

const app = Stitch.defaultAppClient
const credential = new UserPasswordCredential("<email>", "<password>")
app.auth.loginWithCredential(credential)
  // Returns a promise that resolves to the authenticated user
  .then(authedUser => console.log(`successfully logged in with id: ${authedUser.id}`))
  .catch(err => console.error(`login failed with error: ${err}`))

To log an existing user in to your application, instantiate UserPasswordCredential with the user’s email address and password, and provide that credential instance to the StitchAuth.loginWithCredential() method.

UserPasswordCredential credential = new UserPasswordCredential("<email>", "<password>")
Stitch.getDefaultAppClient().getAuth().loginWithCredential(credential)
  .addOnCompleteListener(new OnCompleteListener<StitchUser>() {
    @Override
    public void onComplete(@NonNull final Task<StitchUser> task) {
      if (task.isSuccessful()) {
        Log.d("stitch", "Successfully logged in as user " + task.getResult().getId());
      } else {
        Log.e("stitch", "Error logging in with email/password auth:", task.getException());
      }
    }
  }
);

To log an existing user into your application, instantiate UserPasswordCredential with the user’s email address and password, and provide that credential instance to the StitchAuth.loginWithCredential() method:

let credential = UserPasswordCredential.init()
Stitch.defaultAppClient!.auth.login(withCredential: credential) { result in
  switch result {
  case .success:
      print("Successfully logged in")
  case .failure(let error):
      print("Error logging in with email/password auth: \(error)")
  }
}

Create a New User Account

To register a new user account, obtain a UserPasswordAuthProviderClient instance, and pass the user’s email address and password to the registerWithEmail() method.

const emailPasswordClient = Stitch.defaultAppClient.auth
  .getProviderClient(UserPasswordAuthProviderClient.factory);

emailPasswordClient.registerWithEmail("<user-email>", "<user-password>")
  .then(() => console.log("Successfully sent account confirmation email!"))
  .catch(err => console.error("Error registering new user:", err));

Note

Stitch does not create a user object for a particular user until their account is confirmed and they log in for the first time.

To register a new user account, obtain a UserPasswordAuthProviderClient instance, and pass the user’s email address and password to the registerWithEmail() method.

UserPasswordAuthProviderClient emailPassClient = Stitch.getDefaultAppClient().getAuth().getProviderClient(
   UserPasswordAuthProviderClient.factory
);

emailPassClient.registerWithEmail("<user-email>", "<user-password>")
  .addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull final Task<Void> task) {
      if (task.isSuccessful()) {
        Log.d("stitch", "Successfully sent account confirmation email");
      } else {
        Log.e("stitch", "Error registering new user:", task.getException());
      }
    }
  }
);

Note

Stitch does not create a user object for a particular user until their account is confirmed and they log in for the first time.

To register a new user account, obtain a UserPasswordAuthProviderClient instance, and pass the user’s email address and password to the register() method.

let emailPassClient = Stitch.defaultAppClient!.auth.providerClient(
  fromFactory: userPasswordClientFactory
)

emailPassClient.register(email: "<user-email>", password: "<user-password>") { result in
  switch result {
  case .success:
      print("Registration email sent")
  case .failure(let error):
      print("Error sending registration email")
  }
}

Note

Stitch does not create a user object for a particular user until their account is confirmed and they log in for the first time.

Confirm a New User’s Email Address

If the provider’s User Confirmation Method is set to Send a confirmation email then Stitch sends an email with a confirmation link to each new user after they register. The link opens the Email Confirmation URL that you specified in the provider configuration and includes unique token and tokenId query parameters.

To confirm the user’s email address, you need to host a page at the confirmation URL that parses the user’s valid token and tokenId values and passes them to Stitch through the confirmUser() method.

Stitch.initializeDefaultAppClient("<your app id>");
// Parse the URL query parameters
const url = window.location.search;
const params = new URLSearchParams(url);
const token = params.get('token');
const tokenId = params.get('tokenId');

// Confirm the user's email/password account
const emailPassClient = Stitch.defaultAppClient.auth
  .getProviderClient(UserPasswordAuthProviderClient.factory);

return emailPassClient.confirmUser(token, tokenId);

Resend Confirmation Email

After Stitch sends a confirmation email, the confirmation token and tokenId are valid for two hours. If a user’s confirmation link expires before they confirm their email, then you can send them another confirmation email with a new, valid token by passing their email address to the resendConfirmationEmail() method.

If the provider’s User Confirmation Method is set to Send a confirmation email then Stitch sends an email with a confirmation link to each new user after they register. The link opens the Email Confirmation URL that you specified in the provider configuration and includes unique token and tokenId query parameters.

To confirm the user’s email address, you need to write logic that parses the user’s valid token and tokenId values and passes them to Stitch. You can confirm Android application users in two ways:

  1. Host a web page at the Email Confirmation URL that contains an email confirmation script. See the JavaScript tab of this section for an example of confirming user emails in the browser.
  2. Map the Email Confirmation URL to an activity in your app with a deep link. The activity should parse the token and tokenId from the deep link intent and pass them to the confirmUser() function.
public void handlePasswordReset() {
  Uri uri = intent.getIntent().getData();

  String token = uri.getQueryParameter("token");
  String tokenId = uri.getQueryParameter("tokenId");

  UserPasswordAuthProviderClient emailPassClient = Stitch
   .getDefaultAppClient()
   .getAuth()
   .getProviderClient(UserPasswordAuthProviderClient.factory);

  emailPassClient.confirmUser(token, tokenId)
    .addOnCompleteListener(new OnCompleteListener<Void>() {
      @Override
      public void onComplete(@NonNull final Task<Void> task) {
        if (task.isSuccessful()) {
          Log.d("stitch", "Successfully reset user's password");
        } else {
          Log.e("stitch", "Error resetting user's password:", task.getException());
        }
      }
    }
}

Resend Confirmation Email

After Stitch sends a confirmation email, the confirmation token and tokenId are valid for two hours. If a user’s confirmation link expires before they confirm their email, then you can send them another confirmation email with a new, valid token by passing their email address to the resendConfirmationEmail() method.

If the provider’s User Confirmation Method is set to Send a confirmation email then Stitch sends an email with a confirmation link to each new user after they register. The link opens the Email Confirmation URL that you specified in the provider configuration and includes unique token and tokenId query parameters.

To confirm the user’s email address, you need to write logic that parses the user’s valid token and tokenId values and passes them to Stitch. You can confirm iOS application users in two ways:

  1. Host a web page at the Email Confirmation URL that contains an email confirmation script. See the JavaScript tab of this section for an example of confirming user emails in the browser.
  2. Configure a universal link that redirects from the Email Confirmation URL to a confirmation handler in your app.

Alternatively, you can use an iOS universal link to open the URL directly in your app and handle the confirmation process natively. The application delegate should parse the token and tokenId query parameters from the universal link’s NSUserActivity object and pass them to the confirmUser() method.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
        let url = userActivity.webpageURL!
        let urlString = url.absoluteString

        let queryParams = URLComponents(string: url).queryItems?
        let token = queryParams.first(where: { $0.name == "token" })?.value
        let tokenId = queryParams.first(where: { $0.name == "tokenId" })?.value

        let emailPassClient = Stitch.defaultAppClient!.auth.providerClient(
          fromFactory: userPasswordClientFactory
        )

        emailPassClient.confirmUser(token: token, tokenId: tokenId) { result in
          switch result {
          case .success:
              print("User confirmed")
          case .failure(let error):
              print("Error confirming user: \(error)")
          }
        }
    }
    return true
}

Resend Confirmation Email

After Stitch sends a confirmation email, the confirmation token and tokenId are valid for two hours. If a user’s confirmation link expires before they confirm their email, then you can send them another confirmation email with a new, valid token by passing their email address to the resendConfirmation() method as the toEmail argument.

Reset a User’s Password

To reset a user’s password, obtain a UserPasswordAuthProviderClient instance, and call the sendResetPasswordEmail() method with their email address. Stitch will send the user an email containing a password reset link. The link points to the Password Reset URL specified in the provider configuration and includes unique token and tokenId query parameters.

const emailPassClient = Stitch.defaultAppClient.auth
  .getProviderClient(UserPasswordAuthProviderClient.factory);

emailPassClient.sendResetPasswordEmail('<email>').then(() => {
  console.log("Successfully sent password reset email!");
}).catch(err => {
  console.log("Error sending password reset email:", err);
});

The Password Reset URL should point to a page that allows users to, at minimum, input a new a password for their account. When a user submits their new password, pass it to the resetPassword() method along with the token and tokenId values.

// Parse the URL query parameters
const url = window.location.search;
const params = new URLSearchParams(url);

const token = params.get('token');
const tokenId = params.get('tokenId');
const newPassword = getUserInputFromPage();

// Confirm the user's email/password account
const emailPassClient = Stitch.defaultAppClient.auth
  .getProviderClient(UserPasswordAuthProviderClient.factory);

emailPassClient.resetPassword(token, tokenId, newPassword).then(() => {
  console.log("Successfully reset password!");
}).catch(err => {
  console.log("Error resetting password:", err);
});

To reset a user’s password, obtain a UserPasswordAuthProviderClient instance, and call the sendResetPasswordEmail() method with their email address. Stitch will send the user an email that contains a password reset link. The link points to the Password Reset URL specified in the provider configuration and includes unique token and tokenId query parameters.

UserPasswordAuthProviderClient emailPassClient = Stitch.getDefaultAppClient().getAuth().getProviderClient(
   UserPasswordAuthProviderClient.factory
);

emailPassClient.sendResetPasswordEmail("<email>")
  .addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull final Task<Void> task) {
      if (task.isSuccessful()) {
        Log.d("stitch", "Successfully sent password reset email");
      } else {
        Log.e("stitch", "Error sending password reset email:", task.getException());
      }
    }
  }
);

The Password Reset URL should point to a page that, at minimum, allows users to input a new a password for their account. By default the link will open in the user’s web browser. See the JavaScript tab of this section for an example of handling password reset emails in the browser.

Alternatively, you can use an Android deep link to open the URL directly in an activity in your app that handles password resets. When a user submits their new password, pass it to the resetPassword() function along with the token and tokenId values.

public void handlePasswordReset() {
  Uri uri = intent.getIntent().getData();
  EditText newPasswordInput = (EditText) findViewById(R.id.newPasswordInput);

  String token = uri.getQueryParameter("token");
  String tokenId = uri.getQueryParameter("tokenId");
  String newPassword = newPasswordInput.getText().toString();

  UserPasswordAuthProviderClient emailPassClient = Stitch.getDefaultAppClient().getAuth().getProviderClient(
     UserPasswordAuthProviderClient.factory
  );

  emailPassClient
      .resetPassword(token, tokenId, newPassword)
      .addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull final Task<Void> task) {
          if (task.isSuccessful()) {
            Log.d("stitch", "Successfully reset user's password");
          } else {
            Log.e("stitch", "Error resetting user's password:", task.getException());
          }
        }
      }
}

To reset a user’s password, obtain a UserPasswordAuthProviderClient instance, and call the sendResetPasswordEmail() method with their email address. Stitch will send the user an email that contains a password reset link. The link points to the Password Reset URL specified in the provider configuration and includes unique token and tokenId query parameters.

let emailPassClient = Stitch.defaultAppClient!.auth.providerClient(
  fromFactory: userPasswordClientFactory
)

emailPassClient.sendResetPassword(toEmail: "<email>")
    .done { (userId: String) in
        print("Successfully sent password reset email")
    }.catch { error in
        print("Error logging in with email/password auth: \(error)")
    }

The Password Reset URL should point to a page that, at minimum, allows users to input a new a password for their account. By default the link will open in the user’s web browser. See the JavaScript tab of this section for an example of handling password reset emails in the browser.

Alternatively, you can use an iOS universal link to open the URL directly in your app and handle the password reset process natively. When a user submits their new password, pass it to the reset() function along with the token and tokenId values.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
        let url = userActivity.webpageURL!
        let urlString = url.absoluteString

        let queryParams = URLComponents(string: url).queryItems?
        let token = queryParams.first(where: { $0.name == "token" })?.value
        let tokenId = queryParams.first(where: { $0.name == "tokenId" })?.value

        // Instantiate and load the password reset view controller here
    }
    return true
}

func handlePasswordReset(newPassword: String) {
  let emailPassClient = Stitch.defaultAppClient!.auth.providerClient(
    fromFactory: userPasswordClientFactory
  )

  emailPassClient.reset(token: token, tokenId: tokenId, password: newPassword) { result in
    switch result {
    case .success:
        print("User password reset")
    case .failure(let error):
        print("Error resetting password: \(error)")
    }
  }
}