Navigation

Custom Authentication

On this page

Overview

In many applications, simple email/password authentication or OAuth2 authentication with Google/Facebook is not sufficient. An application may require more user metadata, two-factor authentication, or other strict security requirements. With MongoDB Stitch custom authentication, you can build out an authentication system separate from Stitch that issues credentials that users can use to authenticate with your Stitch app.

Diagram of custom authentication architecture.

The credentials that are generated by your system must be JSON Web Tokens (described in the next section), and the token must contain a string ID that uniquely identifies that user within your authentication system. This ID is separate from the id of the MongoDB Stitch user. The tokens may optionally contain additional metadata that will be exposed in the data field of the MongoDB Stitch user.

To get started with custom authentication for your app:

  1. Select Users from the left-side navigation.

  2. Select the Providers tab.

  3. Click the Edit button in the Custom Authentication row.

  4. Switch the Provider Status toggle to enabled.

  5. Select the metadata fields you’d like to expose in the data field of Stitch users created with custom authentication. You may also specify that certain fields are required to exist in the tokens.

  6. The Signing Key is what your authentication service will use to sign the JSON Web Tokens that are issued to users as credentials.

    Warning

    Keep your signing key a secret, and never place it in a publicly accessible location. For example, avoid storing your key in source code repositories, never reveal it on online code-sharing platforms such as StackOverflow, and never expose or even use the key in your client applications.

    If an attacker obtains this key, they can theoretically issue genuine credentials and sign into your app as any user if they know that user’s ID in your authentication system.

Elements

Custom authentication uses JSON Web Tokens (JWT), an open, industry standard RFC 7519 method for representing claims securely between two parties. A JWT consists of three parts: a header, a payload and a signature.

The header looks like this:

{
  "alg": "HS256",
  "typ": "JWT"
}

The payload is an object with some fields common to all JWTs and some which are particular to MongoDB Stitch. A JWT for use with MongoDB Stitch custom authentication uses have the following fields:

{
  "aud": "clientAppID",   //required
  "sub": "uniqueUserID",  //required
  "exp": 1495578429,      //required
  "iat": 1495574829,      //optional
  "nbf": 1495578429,      //optional
  "stitch_meta": {        //optional
    "email": "name@example.com",
    "name": "Joe Bloggs",
    "picture": "http://example.com/joe_bloggs.jpg"
  }
}

The payload fields are populated as follows:

Field Required/Optional Description
aud
Required Audience. Populate with the App ID for your client application.
exp
Required Expires. Number containing a NumericDate value indicating the time at which the token expires. MongoDB Stitch will not accept expired tokens for authentication.
sub
Required Subject. A unique user ID in your custom-built authentication system.
iat
Optional Issued at. Number containing a NumericDate value indicating the time at which the token should become valid.
nbf
Optional Not before. Functionally identical to iat.
stitch_meta
Optional Document that contains the metadata that will be exposed in the data field of that MongoDB Stitch user. Note that for the fields to be properly exposed, they must be specified in the authentication provider settings. See the previous section.

The token’s signature is generated by taking a hash of the header, the payload, and your signing token.

Usage

When using custom authentication, your app must first communicate with your authentication system that is separate from MongoDB Stitch. The protocol for how this is done is entirely up to you. All Stitch needs is the JWT.

Once you have a signed JWT from your authentication system, you can use the SDKs to authenticate with MongoDB Stitch. In your client application, the following SDK sample code be used to authenticate the Stitch client. The sample assumes you have an inititalized StitchClient in your application.

See Initialize StitchClient for more details on initializing a StitchClient in your application.

let jwtString = getTokenFromCustomBuiltAuthSystem();

yourStitchClient.authenticate("custom", jwtString)
  .then( authedUserId => {
      console.log("logged in with custom auth as user", authedUserId);
  })
  .catch( err => {
      console.error("failed to log in with custom auth:", err);
  });
String _jwtString = getTokenFromCustomBuiltAuthSystem();

yourStitchClient.getAuthProviders().addOnSuccessListener(new OnSuccessListener<AvailableAuthProviders>() {
    @Override
    public void onSuccess(final AvailableAuthProviders auth) {
        if (auth.getCustomAuth() != null) {
            Log.d("stitch", "logging in with custom auth");
            yourStitchClient.logInWithProvider(new CustomAuthProvider(_jwtString)).addOnCompleteListener(new OnCompleteListener<String>() {
                @Override
                public void onComplete(@NonNull final Task<String> task) {
                    if (task.isSuccessful()) {
                        Log.d("stitch", "logged in with custom auth as user " + task.getResult());
                    } else {
                        Log.e("stitch", "failed to log in with custom auth:", task.getException());
                    }
                }
            });
        } else {
            Log.e("stitch", "no custom auth provider");
        }
    }
});
let jwtString = getTokenFromCustomBuiltAuthSystem()

yourStitchClient.fetchAuthProviders().then { (authProviderInfo: AuthProviderInfo) -> Promise<String> in
    if (authProviderInfo.customAuthProviderInfos.count != 0) {
        return yourStitchClient.login(withProvider: CustomAuthProvider(jwt: jwtString))
    } else {
        throw StitchError.illegalAction(message: "no custom auth provider")
    }
}.done { (userId: String) in
    print("logged in with custom auth as user \(userId)")
}.catch { error in
    print("failed to log in with custom auth: \(error)")
}