Installation

$ npm install --save @propelauth/express

Initialize

initAuth performs a one-time initialization of the library. It will verify your apiKey is correct and fetch the metadata needed to verify access tokens in requireUser, optionalUser, or requireOrgMember.

const propelAuth = require("@propelauth/express");
const {
  requireUser,
  optionalUser,
  requireOrgMember,
  requireOrgMemberWithMinimumRole,
  requireOrgMemberWithExactRole,
  requireOrgMemberWithPermission,
  requireOrgMemberWithAllPermissions,
  fetchUserMetadataByUserId,
  fetchUserMetadataByEmail,
  fetchUserMetadataByUsername,
  fetchBatchUserMetadataByUserIds,
  fetchBatchUserMetadataByEmails,
  fetchBatchUserMetadataByUsernames,
  fetchOrg,
  fetchOrgByQuery,
  fetchUsersByQuery,
  fetchUsersInOrg,
  createUser,
  updateUserMetadata,
  updateUserEmail,
  createMagicLink,
  migrateUserFromExternalSource,
  createOrg,
  addUserToOrg,
  deleteUser,
  disableUser,
  enableUser,
  allowOrgToSetupSamlConnection,
  disallowOrgToSetupSamlConnection,
} = propelAuth.initAuth({
  // If true, error messages returned to the user will be detailed.
  // It's useful for debugging, but a good idea to turn off in production.
  debugMode: true,
  // You can find your Auth URL and API key under the Backend Integration
  //   section for your project at https://app.propelauth.com.
  authUrl: "https://auth.yourdomain.com",
  apiKey: "YOUR_API_KEY",
});

We recommend putting this in its own file and exporting it:

// propelauth.js
const propelAuth = require("@propelauth/express");
module.exports = propelAuth.initAuth({
  debugMode: true,
  authUrl: "https://auth.yourdomain.com",
  apiKey: "YOUR_API_KEY",
});

And then importing just what you need:

const { requireUser } = require("./propelauth");

Protect API routes

requireUser

An Express middleware that will verify the request was made by a valid user. Specifically, it will:

  1. Check that a valid access token was provided. If not, the request is rejected with a 401 status code.
  2. Set user on the Request with the user’s information.
app.get("/hello", requireUser, (req, res) => {
  res.text("Hello user with ID " + req.user.userId);
});

The user object looks like:

userId
string

The id of the user

orgIdToOrgMemberInfo
object

A dictionary of org ids to metadata about the org. Includes all orgs that the user is in

legacyUserId
string

The original ID of the user, if the user was migrated from an external source

impersonatorUserId
string

If someone on your team is impersonating another user, this will be set to the employee’s ID. By default, user impersonation is turned off and this will be undefined

properties
{ [key: string]: unknown }

A dictionary of custom properties for the user. See Custom Properties for more details.

The values of orgIdToOrgMemberInfo are OrgMemberInfo’s, with the following fields/functions:

orgId
string

The id of the org

orgName
string

The name of the org

urlSafeOrgName
string

A URL-safe version of the name of the org

assignedRole()
function

A function that returns the user’s role within the organization. See Roles and Permissions for more details.

permissions()
function

A function that returns the user’s permissions within the organization. See Roles and Permissions

isRole(role)
function

Returns True if the user’s role within the organization matches the role passed in

isAtLeastRole(role)
function

Returns True if the user’s role within the organization is at least the role passed in. If the hierarchy of roles is Owner => Admin => Member, specifying “Admin” will return True for Admins and Owners, but False for Members

hasPermission(permission)
function

Return True if the user has a specific permission. The users’ permissions are derived from their role within this organization.

hasAllPermissions(permissions)
function

Return True if the user has all the specified permissions. The users’ permissions are derived from their role within this organization.

optionalUser

Similar to requireUser, except if an access token is missing or invalid, the request is allowed to continue, but user on the Request will be undefined.

app.get("/hello", optionalUser, (req, res) => {
  if (req.user) {
    res.text("Hello user with ID " + req.user.userId);
  } else {
    res.text("Hello anonymous");
  }
});

requireOrgMember

An Express middleware that will verify the request was made by a valid user that belongs to a specific organization.

If none is specified like in the Basic example below, the default function here will it will check for a path param orgId. Otherwise, you can provide a function here that returns an orgId in another way, as seen with the orgIdInQueryExtractor in the Advanced example.

// By default, requireOrgMember checks for orgId as a path parameter
app.get("/org/:orgId/hello", requireOrgMember(), (req, res) => {
    res.text("You are in " + req.org.orgName);
});

Specifically, it will:

  1. Check that a valid access token was provided. If not, the request is rejected with a 401 status code.
  2. Set user on the Request with the user’s information. See requireUser for what the user object looks like.
  3. Find an id for an organization within the request. By default, it will check Request.params.orgId (a path parameter named orgId).
  4. Check that the user is a member of that organization. If not, the request is rejected with a 403 status code.
  5. Set org on the Request with the organization’s information for this user.

Roles and Permissions

A user has a Role within an organization. By default, the available roles are Owner, Admin, or Member, but these can be configured. These roles are also hierarchical, so Owner > Admin > Member.

Roles allow you to control what different users can do within your product. If you want to check a user’s role, you can use requireOrgMemberWithExactRole or requireOrgMemberWithMinimumRole.

// Assuming a Role structure of Owner => Admin => Member

app.get(
  "/org/:orgId/admin",
  requireOrgMemberWithExactRole({ role: "Admin" }),
  (req, res) => {
    res.text("You are an Admin of " + req.org.orgName);
  }
);

app.get(
  "/org/:orgId/admin_or_owner",
  requireOrgMemberWithMinimumRole({ minimumRequiredRole: "Admin" }),
  (req, res) => {
    res.text("You are an Admin of " + req.org.orgName);
  }
);

Permissions are arbitrary strings associated with a role. For example, can_view_billing, ProductA::CanCreate, and ReadOnly are all valid permissions. The PropelAuth dashboard allows you to set up these permissions.

You can use requireOrgMemberWithPermission or requireOrgMemberWithAllPermissions to check for a given permission.

app.get(
  "/org/:orgId/billing",
  requireOrgMemberWithPermission({ permission: "can_view_billing" }),
  (req, res) => {
    // TODO: view billing
  }
);

All of these functions, just like requireOrgMember, can also take in orgIdExtractor, and will set both req.user and req.org on a valid request.

Fetching functions

Fetch user metadata by id

function fetchUserMetadataByUserId(userId, includeOrgs)

Parameters

userIdrequired
string

The id of the user

includeOrgs
boolean

Whether to return an orgIdToOrgInfo object, default value is false

Successful response (UserMetadata):

{
    userId:            "e9d3520f-836e-403c-82c2-09843517e1ce",
    email:             "user@example.com",
    emailConfirmed:    true,
    hasPassword:       true,

    username:          "example",
    firstName:         "first",
    lastName:          "last",
    pictureUrl:        "https://...",

    // True if the user's account is locked for security purposes.
    locked:            false,
    enabled:           true,
    mfaEnabled:        false,

    createdAt:         1645131680,
    lastActiveAt:      1650654711,

    // Only returned if includeOrgs = true
    orgIdToOrgInfo: {
        "2ef0e1fc-234f-4dc0-a50c-35adb1bbb7e4" : {
            orgId: "2ef0e1fc-234f-4dc0-a50c-35adb1bbb7e4",
            orgName: "ExampleOrganization",
            userAssignedRole: "Owner",
        }
    },

    // Only returned if user was migrated from an external system
    legacyUserId:    "507f191e810c19729de860ea"
}

Fetch user metadata by email

function fetchUserMetadataByEmail(email, includeOrgs)

Parameters

emailrequired
string

The email of the user

includeOrgs
boolean

Whether to return an orgIdToOrgInfo object, default value is false

Successful response is the same as Fetch user metadata by id.

Fetch user metadata by username

function fetchUserMetadataByUsername(username, includeOrgs)

Parameters

usernamerequired
string

The username of the user

includeOrgs
boolean

Whether to return an orgIdToOrgInfo object, default value is false

Successful response is the same as Fetch user metadata by id.

Batch fetch users by ids

function fetchBatchUserMetadataByUserIds(userIds, includeOrgs)

Parameters

userIdsrequired
array

List of userIds

includeOrgs
boolean

Whether to return an orgIdToOrgInfo object, default value is false

Any IDs that don’t have a match are not returned. Duplicate users are only returned once.

A successful response will be a map of the user objects set to keys of the userIds you passed in. For example:

{
    "e9d3520f-836e-403c-82c2-09843517e1ce": {
        userId:            "e9d3520f-836e-403c-82c2-09843517e1ce",
        email:             "user@example.com",
        emailConfirmed:    true,
        hasPassword:       true,

        username:          "example",
        firstName:         "first",
        lastName:          "last",
        pictureUrl:        "https://...",

        // True if the user's account is locked for security purposes.
        locked:            false,
        enabled:           true,
        mfaEnabled:        false,

        createdAt:         1645131680,
        lastActiveAt:      1650654711,

        // Only returned if includeOrgs = true
        orgIdToOrgInfo: {
            "2ef0e1fc-234f-4dc0-a50c-35adb1bbb7e4" : {
                orgId: "2ef0e1fc-234f-4dc0-a50c-35adb1bbb7e4",
                orgName: "ExampleOrganization",
                userAssignedRole: "Owner",
            }
        },

        // Only returned if user was migrated from an external system
        legacyUserId:    "507f191e810c19729de860ea"
    },
    // other user_ids
}

Batch fetch users by emails

function fetchBatchUserMetadataByEmails(emails, includeOrgs)

Parameters

emailsrequired
array

List of user emails

includeOrgs
boolean

Whether to return an orgIdToOrgInfo object, default value is false

Successful response is the same as Batch fetch users by ids, but the keys are matching email addresses.

Batch fetch users by usernames

function fetchBatchUserMetadataByUsernames(usernames, includeOrgs)

Parameters

usernamesrequired
array

List of user usernames

includeOrgs
boolean

Whether to return an orgIdToOrgInfo object, default value is false

Successful response is the same as Batch fetch users by ids, but the keys are matching usernames.

Search for users

function fetchUsersByQuery(usersQuery)

Searches for users through a customizable query object, usersQuery. The possible parameters for this query are as follows.

usersQuery Parameters

pageSize
number

The number of results to return at a time. Must be between 1 and 100, default 10.

pageNumber
number

Used to page over results

orderBy
string

How to order the results. Must be one of: CREATED_AT_ASC, CREATED_AT_DESC, LAST_ACTIVE_AT_ASC, LAST_ACTIVE_AT_DESC, EMAIL, USERNAME

emailOrUsername
string

Searches for partial matches within email addresses or usernames. port would match a user with email address support@propelauth.com.

includeOrgs
boolean

Whether to return an orgIdToOrgInfo object, default value is false

Successful response:

{
    "totalUsers": 103,
    "currentPage": 0,
    "pageSize": 10,
    "hasMoreResults": true,
    "users": [{
        // See (1) for example users
    }, {
        // There will be 10 users in this response
    }]
}
  1. Example user in response

Fetch an organization

function fetchOrg(orgId)
orgId
string

Id for the organization

Successful response:

{
    "orgId": "d488996d-8ccc-4101-b5f2-131f5f09ddb6"
    "name": "OneOfYourCustomers"
}

Fetch all organizations

function fetchOrgsByQuery(orgQuery)

orgQuery Parameters

pageSize
number

The number of results to return at a time. Must be between 1 and 100, default 10.

pageNumber
number

Used to page over results

orderBy
string

How to order the results. Must be one of: CREATED_AT_ASC, CREATED_AT_DESC, NAME

Successful response:

{
    "totalOrgs": 21,
    "currentPage": 0,
    "pageSize": 10,
    "hasMoreResults": true,
    "orgs": [{
        "orgId": "d488996d-8ccc-4101-b5f2-131f5f09ddb6",
        "name": "OneOfYourCustomers"
    }, {
        // There will be 10 orgs in this response
    }]
}

Fetch users in organization

function fetchUsersInOrg(usersInOrgQuery)

Searches for users in a specified organization through a customizable query object. The possible parameters for this query are as follows.

Parameters

orgIdrequired
number

The organization to fetch users for

pageSize
number

The number of results to return at a time. Must be between 1 and 100, default 10.

pageNumber
number

Used to page over results

includeOrgs
boolean

Whether to return an orgIdToOrgInfo object, default value is false

Successful response:

{
    "totalUsers": 43,
    "currentPage": 0,
    "pageSize": 10,
    "hasMoreResults": true,
    "users": [{
        // See (1) for example users
    }, {
        // There will be 10 users in this response, all in the specified organization
    }]
}
  1. Example user in response

User Management

Create User

function createUser(createUserRequest)

createUserRequest Parameters

emailrequired
string

The user’s email address

emailConfirmed
boolean

Whether the email address should start off as already confirmed. If false, the user is required to confirm the email address before they sign in.

sendEmailToConfirmEmailAddress
boolean

Whether we should send an email immediately to confirm the user’s email address. If false, the user will get a confirmation email when they first sign in.

askUserToUpdatePasswordOnLogin
boolean

Whether we should require the user to set or update their password on initial login. Default false

password
string

Optional password. If unset, the user can set it themselves via their account page

username
string

Optional username. Can only be used if username is enabled in your user schema

firstName
string

Optional first name. Can only be used if name is enabled in your user schema

lastName
string

Optional last name. Can only be used if name is enabled in your user schema

properties
{ [key: string]: any }

A dictionary of custom properties for the user. See Custom Properties for more details.

Successful response:

{
    "userId": "b5f667fb-e51a-49c6-a396-711e62948689"
}

Update User Email

// Returns true if it was successful, false if the user was not found
function updateUserEmailWrapper(userId, updateUserEmailRequest)
userId
string

Id for the user

updateUserEmailRequest
request object

Update User Metadata

// Returns true if it was successful, false if the user was not found
function updateUserMetadata(userId, updateUserMetadataRequest)
userId
string

Id for the user

updateUserMetadataRequest
request object

Update Password

// Returns true if it was successful, false if the user was not found
function updateUserPassword(userId, updateUserPasswordRequest)
userId
string

Id for the user

updateUserPasswordRequest
request object

Returns true if the user’s password was updated.

Delete user

function deleteUser(userId)
userId
string

Id for the user

Returns true if the user was deleted.

Disable user

function disableUser(userId)
userId
string

Id for the user

Returns true if the user was disabled. Afterwards, the user is logged out and unable to log back in.

Enable user

function enableUser(userId)
userId
string

Id for the user

Returns true if the user was enabled, allowing them to log in again.

Migrate User from External Source

Similar to Create User, but for cases where you already have a user stored in an external system. You can, for example, pass in a password hash for an existing user, and they will be able to login with their same password. It is also possible to provide an existing identifier, and we will store and return it along with our future identifiers, allowing you to link them.

function migrateUserFromExternalSource(migrateUserFromExternalSourceRequest)
migrateUserFromExternalSourceRequest
request object

Successful response:

{
    "userId": "b5f667fb-e51a-49c6-a396-711e62948689"
}

Creates a magic link that a user can use to log in. Use this API if you’d prefer to send the magic link to the customer yourself, otherwise, we have createUser which will email them directly.

function createMagicLink(createUserRequest)
createUserRequest
request object

Successful response:

{
    "url": "https://auth.yourdomain.com/..."
}

Create Access Token

Our frontend libraries allow you to get access tokens that can be sent to the backend. The backend is then responsible for verifying these tokens.

For testing purposes, you may want to create access tokens separately from the frontend and set a custom expiration time. With this API, you can create access tokens for users programmatically and set a custom expiration.

function createAccessToken(createAccessTokenRequest)
createAccessTokenRequest
request object

Successful response:

{
    "access_token": "..."
}

Enable Org Creation

function enableUserCanCreateOrgs(userId)
userId
string

Id for the user

Returns true if the user was enabled, allowing them to create organizations.

Disable Org Creation

function disableUserCanCreateOrgs(userId)
userId
string

Id for the user

Returns true if the user was disabled, removing their ability to create organizations.

Org Management

Create Organization

function createOrg(createOrgRequest)
createOrgRequest
request object

Successful response:

{
    "orgId": "d488996d-8ccc-4101-b5f2-131f5f09ddb6"
}

Add user to organization

function addUserToOrg(addUserToOrgRequest)
addUserToOrgRequest
request object

Returns true if the user was successfully added to the organization.

Allow organization to set up SAML connection

function allowOrgToSetupSamlConnection(orgId)
orgId
string

The org’s ID

Returns true if successful, meaning the organization can now set up SAML connections.

Disallow organization to set up SAML connection

function disallowOrgToSetupSamlConnection(orgId: string): Promise<boolean>
orgId
string

The org’s ID

Returns true if successful, meaning the organization can no longer set up SAML connections.

Update Organization Metadata

// Returns true if it was successful, false if the user was not found
function updateOrg(updateOrgRequest)
updateOrgRequest
request object

API Key Authentication

For more information on API Key Authentication, please refer to our Quickstart Guide on the topic.

Validate Personal API Key

function validatePersonalApiKey(apiKeyToken)
apiKeyToken
string

The API Key token that was issued to the user, or generated by the Create API Key endpoint.

If the token provided is not valid, an error is returned. If the token is valid, a user object that is associated with the token is returned.

In addition to validating the API Key, this also makes sure it’s specifically a personal API key.

Successful response user property contains the same fields as Fetch user metadata by id.

{

   "user":{
      "userId":"98cef184-7c15-45c5-8918-8c2295aa7ffe",
      "email":"test@propelauth.com",
      //...
   },
    "metadata":{},
}

Validate Organization API Key

function validateOrgApiKey(apiKeyToken)
apiKeyToken
string

The API Key token that was issued to the organization, or generated by the Create API Key endpoint.

If the token provided is not valid, an error is returned. If the token is valid, an organization object that is associated with the token is returned.

In addition to validating the API Key, this also makes sure it’s specifically an organization API key.

Successful response contains the same fields as Fetch user metadata by id.

Validate API Key

function validateApiKey(apiKeyToken)
apiKeyToken
string

The API Key token that was issued to the user or organization, or generated by the Create API Key endpoint.

Returns a full user or organization object, depending on where the API Token was issued.

Successful response contains the same fields as Fetch user metadata by id.

Fetch API Key

function fetchApiKey(apiKeyId)
apiKeyId
string

The ID associated with the API Key Token that was issued.

Returns the full API Key

Fetch Current API Keys

function fetchCurrentApiKeys(apiKeyRequest)
apiKeyRequest
request object

Returns a list of current API Keys

Fetch Archived API Keys

function fetchArchivedApiKeys(apiKeyRequest)
apiKeyRequest
request object

Returns a list of archived API Keys

Create API Key

Note: We have hosted pages for users to create API Keys. However, if you would like to do this programmatically, we have provided this endpoint to create keys via your backend.

function createApiKey(createApiKeyRequest)
createApiKeyRequest
request object

Creates a new API Key.

Update API Key

function updateApiKey(apiKeyId, updateApiKeyRequest)
apiKeyId
string

The API Key ID

updateApiKeyRequest
request object

Updates an API Key’s expiration and/or metadata.

Delete API Key

function deleteApiKey(apiKeyId)
apiKeyId
string

The API Key ID

Deletes an API Key.