Navigation

Custom JWT Authentication

Overview

The Custom JWT authentication provider allows users to authenticate with an authentication system that is independent from Stitch. The external system must return a signed JSON Web Token that contains a unique ID value for the authenticated user.

Stitch uses the JWT to identify your application’s users and authenticate their requests but does not impose any restrictions on the external authentication system’s requirements or authentication methods. For example, the system could require the user to perform two factor authentication, provide specific credentials, or otherwise identify themself.

Diagram of Custom JWT authentication architecture.

Configuration

You can enable the JWT authentication provider from the Stitch UI by selecting Custom JWT Authentication from the Users > Providers page.

You can configure the following properties for the provider:

You can enable the Custom JWT authentication provider with stitch-cli by importing an application directory that contains a configuration file for the provider.

The configuration file must be named custom-token.json and stored in the /auth_providers directory. Configuration files for the Custom authentication provider have the following form:

/auth_providers/custom-token.json
{
  "name": "custom-token",
  "type": "custom-token",
  "config": {
    "audience": "<JWT Audience>",
    "signingAlgorithm": "<JWT Signing Algorithm>",
    "useJWKURI": <boolean>,
    "jwkURI": "<JWK or JWKS URL>",
  },
  "secret_config": {
    "signingKeys": [
      "<Signing Key Secret Name>",
      ...
    ]
  },
  "metadata_fields": [
    {
      "required": <boolean>,
      "name": "<JWT Field Path>",
      "field_name": "<Metadata Field Name>",
    },
    ...
  ],
  "disabled": <boolean>,
}

Audience

The Audience of a JWT specifies its intended recipient. JWTs describe their audience in the aud claim. By default, Stitch expects aud to contain the App ID of the Stitch app for which the provider is configured.

If the external authentication system JWT specifies a different aud value, then you can configure the provider to use that value instead.

To override the default audience, specify a new value in the Audience input:

The Custom JWT audience configuration input

To override the default audience, set the value of config.audience:

"config": {
  "audience": "<JWT Audience>",
}

Verification Method

The Verification Method configures how the provider determines which signing algorithm and signing keys the external authentication system must use to sign each JWT.

You can either manually specify signing keys or specify a JSON Web Key URI.

Manually Specify Signing Keys

You can manually configure the signing algorithm and specify one or more signing keys that the external authentication system may use to sign JWTs.

"config": {
  "signingAlgorithm": "<JWT Signing Algorithm>",
},
"secret_config": {
  "signingKeys": [
    "<Signing Key Secret Name>",
    ...
  ]
}
Field Description

Signing Algorithm

config.signingAlgorithm

The cryptographic method that the external system uses to sign the JWT. Custom authentication supports JWTs signed using any of the following algorithms:

  • HS256
  • RS256
The Signing Algorithm configuration dropdown

Signing Key

secret_config.signingKeys

A list of the names of up to three Secrets that each contain a signing key used by the external authentication system to sign JWTs. Each signing key Secret must be a string with length between 32 and 512 characters.

The Signing Keys configuration inputs

Warning

A Signing Key is a secret key and anyone with the key can issue valid user credentials for your app. Ensure that it’s never stored in a publicly accessible location, such as a git repository, message board, or in your code.

Use a JWK URI

Some external authentication systems provide a JSON Web Key Set that describes the signing algorithm and signing keys the system uses to sign JWTs. You can use the JWKS to configure the provider instead of manually specifying the signing algorithm and keys.

"config": {
  "useJWKURI": <boolean>,
  "jwkURI": "<JWK or JWKS URL>"
}
Field Description

Use JWK URI

config.useJWKURI
If true, configures Stitch to use a signing algorithm and signing keys defined in a JWK or JWKS. The JWKS must be accessible at a URL that you specify.

JWK URI

config.jwkURI

A URL that hosts a JWK or JWKS that describes the signing method and signing keys the JWTs should use. The JWKS may specify up to three signing keys and must use the RS256 algorithm.

The JWK URI input

Metadata Fields

Metadata Fields are additional data that describe each user. Stitch determines the value of each metadata field from the value of some field included in the JWT from the external authentication system. Stitch refreshes a user’s metadata whenever they log in and exposes the fields in the data object of the user object.

To define a metadata field, click Add Field and specify the mapping between the metadata field in the JWT and its corresponding field name in the user object.

The metadata fields configuration table

To define a metadata field in a Custom JWT authentication configuration file, add an entry for the field to the metadata_fields array. Each entry should be a document of the following form:

{
  required: <boolean>,
  name: "<field path>",
  field_name: "<metadata field name>"
}
Field Description

Required

required
If true , the metadata field is required for all users associated with the provider, i.e. the JWT returned by the external system must have a value assigned to the field designated by Path.

Path

name
The name of a field in the JWT that contains the value for the metadata field. To specify a field in an embedded object, use dot notation.

Field Name

field_name

Optional. A name for the field in the user object’s data document that exposes the metadata field value. If not specified, this defaults to the same name as the JWT field that contains the value. The metadata field name may not contain no more than 64 characters.

For example, if you specify a name of location.primary.city, the default value for field_name is city.

For example, if you specify a Path of location.primary.city, the default value for Field Name is city.

Example

An external authentication system returns JWTs that include additional information about each user in the user_data field:

{
  "aud": "myapp-abcde",
  "exp": 1516239022,
  "sub": "24601",
  "user_data": {
    "name": "Jean Valjean",
    "aliases": [
      "Monsieur Madeleine",
      "Ultime Fauchelevent",
      "Urbain Fabre"
    ]
  }
}

To include the values from the user_data field in each user’s user object, you could specify the following metadata fields:

Path Field Name
user_data.name name
user_data.aliases aliases

We can now access the mapped values directly from the user object, which would resemble the following for the given JWT:

{
  "id": "59fdd02846244cdse5369ebf",
  "type": "normal",
  "data": {
    "name": "Jean Valjean",
    "aliases": [
      "Monsieur Madeleine",
      "Ultime Fauchelevent",
      "Urbain Fabre"
    ]
  },
  identities: [
    {
      "id": "24601",
      "provider_type": "custom-token",
      "data": {
        "name": "Jean Valjean",
        "aliases": [
          "Monsieur Madeleine",
          "Ultime Fauchelevent",
          "Urbain Fabre"
        ]
      },
    }
  ]
}

Usage

Authenticate a User

To log a user in to your app with the Custom JWT authentication provider, call StitchAuth.loginWithCredential() with an instance of CustomCredential created with a signed JWT from the external authentication system.

const jwtString = getTokenFromCustomBuiltAuthSystem();
const credential = new CustomCredential(jwtString);

Stitch.defaultAppClient.auth.loginWithCredential(credential)
  .then(authedUser => console.log(`logged in with custom auth as user ${authedUser.id}`))
  .catch( err => console.error(`failed to log in with custom auth: ${err}`))

To log a user in to your app with the Custom JWT authentication provider, instantiate a CustomCredential instance with a signed JWT from the external authentication system and pass it as the argument to StitchAppClient.loginWithCredential().

String _jwtString = getTokenFromCustomBuiltAuthSystem();
CustomCredential credential = CustomCredential(_jwtString);

Stitch.getDefaultAppClient().getAuth().loginWithCredential(credential)
    .addOnCompleteListener(new OnCompleteListener<StitchUser>() {
        @Override
        public void onComplete(@NonNull final Task<StitchUser> task) {
            if (task.isSuccessful()) {
                Log.d("stitch", "logged in with custom auth as user " + task.getResult().id);
            } else {
                Log.e("stitch", "failed to log in with custom auth:", task.getException());
            }
        }
    });

To log a user in to your app with the Custom JWT authentication provider, instantiate a CustomCredential instance with a signed JWT from the external authentication system and pass it to the StitchAuth.login(withCredential:_:) method as the withCredential argument.

let jwtString = getTokenFromCustomBuiltAuthSystem()
let credential = CustomCredential.init(withToken: jwtString)

Stitch.defaultAppClient!.auth.login(withCredential: credential) { result in
  switch result {
  case .success(let user):
    print("logged in with custom auth as user \(user.id)")
  case .failure(let error):
    print("failed to log in with custom auth: \(error)")
}

JSON Web Tokens

The external authentication system must return a JSON web token that uniquely identifies the authenticated user. JSON web tokens are an industry standard (RFC 7519) for securely representing claims between two parties. A JWT is a string that consists of three parts: a header, a payload and a signature and has the following form:

<header>.<payload>.<signature>

Payload

The payload portion of the JWT consists of a Base64UrlEncoded document of the following form:

{
  "aud": "<stitch app id>"
  "sub": "<unique user id>",
  "exp": <NumericDate>,
  "iat": <NumericDate>,
  "nbf": <NumericDate>,
  ...
}
Field Description
aud
Required. The audience of the token. By default, Stitch expects this value to be the App ID of your Stitch application. If your external authentication service returns a different aud value, you should specify that value instead.
sub
Required. The subject of the token. The value should be a unique ID for the authenticated user from your custom-built authentication system.
exp

Required. The Expiration date of the token. The value should be a NumericDate number indicating the time at which the token expires.

Note

MongoDB Stitch will not accept expired authentication tokens.

iat
Optional. The “issued at” date of the token . The value should be a NumericDate number that indicates the time after which the token is considered valid. This field is functionally identical to nbf.
nbf
Optional. The “not before” date of the token. The value should be a NumericDate number that indicates the time before which the token is considered invalid. This field is functionally identical to iat.

Note

Stitch ignores any additional fields in the JWT payload unless you have mapped them to metadata fields in the provider configuration. Stitch includes the values of mapped fields in the data document of the authenticated user’s user object.

Signature

The signature portion of the JWT is a hash of the encoded token header and payload. To form the signature, concatentate the encoded header and payload with a period and sign the result with the Signing Key specified in the authentication provider configuration using the hashing algorithm specified in the "alg" field of the header.

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  signingKey
)