# Configurations

Your application configuration lives in the config folder. All the configuration files are loaded on startup and can be accessed through the configuration provider.

When you have a file ./config/server.js with the following config:

module.exports = {
  host: '0.0.0.0',
};

You can access it as

strapi.config.get('server.host', 'defaultValueIfUndefined');

Nested keys are accessible with dot-notation.

鉁忥笍 NOTE

Notice that the filename is used as a prefix to access the configurations.

# Required configurations

# Database

This file lets you define database connections that will be used to store your application content.

鉁忥笍 NOTE

You can find supported database and versions in the local installation process.

Path 鈥 ./config/database.js.

馃挕 TIP

Take a look at the database's guide for more details.

# Configuration in database

Configuration files are not multi server friendly. So we created a data store for config you will want to update in production.

# Get settings
  • environment (string): Sets the environment you want to store the data in. By default it's current environment (can be an empty string if your config is environment agnostic).
  • type (string): Sets if your config is for an api, plugin or core. By default it's core.
  • name (string): You have to set the plugin or api name if type is api or plugin.
  • key (string, required): The name of the key you want to store.
// strapi.store(object).get(object);

// create reusable plugin store variable
const pluginStore = strapi.store({
  environment: strapi.config.environment,
  type: 'plugin',
  name: 'users-permissions',
});

await pluginStore.get({ key: 'grant' });
# Set settings
  • value (any, required): The value you want to store.
// strapi.store(object).set(object);

// create reusable plugin store variable
const pluginStore = strapi.store({
  environment: strapi.config.environment,
  type: 'plugin',
  name: 'users-permissions'
});

await pluginStore.set({
  key: 'grant',
  value: {
    ...
  }
});

# Databases installation guides

Strapi gives you the option to choose the most appropriate database for your project. It currently supports PostgreSQL, MongoDB, SQLite, MySQL and MariaDB. The following documentation covers how to install these databases locally (for development purposes) and on various hosted or cloud server solutions (for staging or production purposes).

馃挕 TIP

Deploying Strapi itself is covered in the Deployment Guide.

# Server

# Available options
Property Description Type Default
host Host name string localhost
port Port on which the server should be running. integer 1337
socket Listens on a socket. Host and port are cosmetic when this option is provided and likewise use url to generate proper urls when using this option. This option is useful for running a server without exposing a port and using proxy servers on the same machine (e.g Heroku nginx buildpack (opens new window)) string | integer /tmp/nginx.socket
emitErrors Enable errors to be emitted to koa when they happen in order to attach custom logic or use error reporting services. boolean false
url Public url of the server. Required for many different features (ex: reset password, third login providers etc.). Also enables proxy support such as Apache or Nginx, example: https://mywebsite.com/api. The url can be relative, if so, it is used with http://${host}:${port} as the base url. An absolute url is however recommended. string ''
proxy Set the koa variable app.proxy. When true, proxy header fields will be trusted. boolean false
cron Cron configuration (powered by node-schedule (opens new window)) Object
cron.enabled Enable or disable CRON tasks to schedule jobs at specific dates. boolean false
admin Admin panel configuration Object
admin.auth Authentication configuration Object
admin.auth.secret Secret used to encode JWT tokens string undefined
admin.auth.events Record of all the events subscribers registered for the authentication object {}
admin.auth.events.onConnectionSuccess Function called when an admin user log in successfully to the administration panel function undefined
admin.auth.events.onConnectionError Function called when an admin user fails to log in to the administration panel function undefined
admin.url Url of your admin panel. Default value: /admin. Note: If the url is relative, it will be concatenated with url. string /admin
admin.autoOpen Enable or disabled administration opening on start. boolean true
admin.watchIgnoreFiles Add custom files that should not be watched during development. See more here (opens new window) (property ignored). Array(string) []
admin.host Use a different host for the admin panel. Only used along with strapi develop --watch-admin string localhost
admin.port Use a different port for the admin panel. Only used along with strapi develop --watch-admin string 8000
admin.serveAdminPanel If false, the admin panel won't be served. Note: the index.html will still be served, see defaultIndex option boolean true
admin.forgotPassword Settings to customize the forgot password email (see more here: Forgot Password Email) Object {}
admin.forgotPassword.emailTemplate Email template as defined in email plugin Object Default template (opens new window)
admin.forgotPassword.from Sender mail address string Default value defined in your provider configuration
admin.forgotPassword.replyTo Default address or addresses the receiver is asked to reply to string Default value defined in your provider configuration

# Formats

You can either use .js or .json files to configure your application.

When using a .js you can either export an object:

module.exports = {
  mySecret: 'someValue',
};

or a function returning a configuration object (recommended usage). The function will get access to the env utility.

module.exports = ({ env }) => {
  return {
    mySecret: 'someValue',
  };
};

# Optional configurations

# Environment

In case you need specific static configurations for specific environments, and using environment variables becomes tedious, Strapi configurations can be created per environment in ./config/env/{env}/{filename}.

These configurations will be merged into the base configurations defined in the ./config folder. The environment is based on the NODE_ENV environment variable (defaults to development).

When starting Strapi with NODE_ENV=production it will load the configuration from ./config/* and ./config/env/production/*. Everything defined in the production config will override the default config.

In combination with environment variables this pattern becomes really powerful.

Examples:

./config/server.js

module.exports = {
  host: '127.0.0.1',
};

./config/env/production/server.js

module.exports = ({ env }) => ({
  host: env('HOST', '0.0.0.0'),
});

When starting your application:

yarn start
# uses host 127.0.0.1
NODE_ENV=production yarn start
# uses host 0.0.0.0
HOST=10.0.0.1 NODE_ENV=production yarn start
# uses host 10.0.0.1

# Environment variables

# List of Strapi's environment variables

Some settings can only be modified through environment variables. Here is a list of those settings are associated environment variable names:

name description type default
STRAPI_DISABLE_UPDATE_NOTIFICATION Don't show the notification message about updating strapi in the terminal boolean false
STRAPI_HIDE_STARTUP_MESSAGE Don't show the startup message in the terminal boolean false
STRAPI_TELEMETRY_DISABLED Don't send telemetry usage data to Strapi boolean false
STRAPI_LOG_TIMESTAMP Add the timestamp info in logs boolean false
STRAPI_LOG_LEVEL Select the level of logs among fatal, error, warn, info, debug, trace string 'info'
STRAPI_LOG_FORCE_COLOR Force colors to be displayed even in environments that are not supposed to have colors enabled (ex: outside of a TTY) boolean true
STRAPI_LOG_PRETTY_PRINT Log lines are displayed as text instead of as object boolean true
STRAPI_LICENSE The license key to activate the Enterprise Edition string undefined
NODE_ENV Type of environment where the app is running string 'development'
BROWSER Open the admin panel in the browser after startup boolean true
ENV_PATH Path to the file that contains your environment variables string './.env'
STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE Initialization locale for the app, if Internationalization (i18n) plugin is installed and enabled on your content types (see Configuration of i18n in production environments) string 'en'

# Configuration using environment variables

In most use cases you will have different configurations between your environments. For example: your database credentials.

Instead of writing those credentials into your configuration files, you can define those variables in a .env file at the root of your application.

Example:

Path 鈥 .env

DATABASE_PASSWORD=acme

If you want to customize the path of the .env file to load you can set an environment variable called ENV_PATH before starting your application:

$ ENV_PATH=/absolute/path/to/.env npm run start

Now you can access those variables in your configuration files and application. You can use process.env.{varName} to access those variables anywhere.

In your configuration files you will have access to a env utility that allows defining defaults and casting values.

Path 鈥 ./config/database.js

module.exports = ({ env }) => ({
  connections: {
    default: {
      settings: {
        password: env('DATABASE_PASSWORD'),
      },
    },
  },
});

# Casting environment variables

// Returns the env if defined without casting it
env('VAR', 'default');

// Cast to int (using parseInt)
env.int('VAR', 0);

// Cast to float (using parseFloat)
env.float('VAR', 3.14);

// Cast to boolean (check if the value is equal to 'true')
env.bool('VAR', true);

// Cast to js object (using JSON.parse)
env.json('VAR', { key: 'value' });

// Cast to an array (syntax: ENV_VAR=[value1, value2, value3] | ENV_VAR=["value1", "value2", "value3"])
env.array('VAR', [1, 2, 3]);

// Case to date (using new Date(value))
env.date('VAR', new Date());

# API

Path 鈥 ./config/api.js.

module.exports = ({ env }) => ({
  responses: {
    privateAttributes: ['_v', 'id', 'created_at'],
  },
  rest: {
    defaultLimit: 100,
    maxLimit: 250,
  },
});

# Available options

Property Description Type Default
responses Global API response configuration Object
responses.privateAttributes Set of globally defined attributes to be treated as private. E.g. _v when using MongoDb or timestamps like created_at, updated_at can be treated as private String array []
rest REST API configuration Object
rest.defaultLimit Specifies default _limit parameter used in API calls Integer 100
rest.maxLimit Specifies max allowed number that can be requested as _limit. Default to null which fetches all results Integer null

# Plugins

A plugin is like a small independent sub-application. It has its own business logic with dedicated models, controllers, services, middlewares or hooks. It can also have its own UI integrated in the admin panel.

馃挕 TIP

Please refer to the plugins documentation for more information.

# Hooks

The hooks are modules that add functionality to the core. They are loaded during the server boot.

# Structure

# File structure
module.exports = strapi => {
  const hook = {
    /**
     * Default options
     */

    defaults: {
      // config object
    },

    /**
     * Initialize the hook
     */

    async initialize() {
      // await someAsyncCode()
      // const settings = {...this.defaults, ...strapi.config.hook.settings.**};
    },
  };

  return hook;
};
  • defaults (object): Contains the default configurations.
  • initialize (function): Called during the server boot.

The configurations of the hook are accessible through strapi.config.hook.settings.**.

The hooks are accessible through the strapi.hook variable.

# Node modules

Every folder that follows this name pattern strapi-hook-* in your ./node_modules folder will be loaded as a hook.

A hook needs to follow the structure below:

/strapi-hook-[...]
鈹斺攢鈹鈹 lib
     - index.js
- LICENSE.md
- package.json
- README.md

The index.js is the entry point to your hook. It should look like the example above.

# Custom local hooks

The framework allows loading hooks from the project directly without having to install them from npm. It's a great way to take advantage of the features of the hooks system for code that doesn't need to be shared between apps. To achieve this, you have to create a ./hooks folder at the root of your project and put the hooks into it.

/project
鈹斺攢鈹鈹 admin
鈹斺攢鈹鈹 api
鈹斺攢鈹鈹 config
鈹    - hook.js
鈹斺攢鈹鈹 hooks
鈹   鈹斺攢鈹鈹 strapi-documentation
鈹        - index.js
鈹   鈹斺攢鈹鈹 strapi-server-side-rendering
鈹        - index.js
鈹斺攢鈹鈹 public
- favicon.ico
- package.json
- server.js

# Configuration and activation

To activate and configure hooks with custom options, you need to add/edit your ./config/hook.js file in your Strapi app. A hook specific timeout value will overwrite the global timeout value, the default timeout value is 1000 milliseconds.

module.exports = {
  timeout: 2000,
  settings: {
    'hook-name': {
      enabled: true,
      timeout: 3000,
    },
  },
};

# Middlewares

The middlewares are functions which are composed and executed in a stack-like manner upon request. If you are not familiar with the middleware stack in Koa, we highly recommend you to read the Koa's documentation introduction (opens new window).

# Structure

# File structure
module.exports = strapi => {
  return {
    // can also be async
    initialize() {
      strapi.app.use(async (ctx, next) => {
        // await someAsyncCode()

        await next();

        // await someAsyncCode()
      });
    },
  };
};
  • initialize (function): Called during the server boot.

The middlewares are accessible through the strapi.middleware variable.

# Node modules

Every folder that follows this name pattern strapi-middleware-* in your ./node_modules folder will be loaded as a middleware.

A middleware needs to follow the structure below:

/middleware
鈹斺攢鈹鈹 lib
     - index.js
- LICENSE.md
- package.json
- README.md

The index.js is the entry point to your middleware. It should look like the example above.

# Custom middlewares

The framework allows the application to override the default middlewares and add new ones. You have to create a ./middlewares folder at the root of your project and put the middlewares into it.

/project
鈹斺攢鈹鈹 api
鈹斺攢鈹鈹 config
鈹斺攢鈹鈹 middlewares
鈹   鈹斺攢鈹鈹 responseTime // It will override the core default responseTime middleware.
鈹        - index.js
鈹   鈹斺攢鈹鈹 views // It will be added into the stack of middleware.
鈹        - index.js
鈹斺攢鈹鈹 public
- favicon.ico
- package.json
- server.js

Every middleware will be injected into the Koa stack. To manage the load order, please refer to the Middleware order section.

# Configuration and activation

To configure the middlewares of your application, you need to create or edit the ./config/middleware.js file in your Strapi app.

By default this file doesn't exist, you will have to create it.

Available options

  • timeout (integer): Defines the maximum allowed milliseconds to load a middleware.
  • load (Object): Configuration middleware loading. See details here
  • settings (Object): Configuration of each middleware
    • {middlewareName} (Object): Configuration of one middleware
      • enabled (boolean): Tells Strapi to run the middleware or not
# Settings

Example:

Path 鈥 ./config/middleware.js.

module.exports = {
  //...
  settings: {
    cors: {
      origin: ['http://localhost', 'https://mysite.com', 'https://www.mysite.com'],
    },
  },
};
# Load order

The middlewares are injected into the Koa stack asynchronously. Sometimes it happens that some of these middlewares need to be loaded in a specific order. To define a load order, create or edit the file ./config/middleware.js.

Path 鈥 ./config/middleware.js.

module.exports = {
  load: {
    before: ['responseTime', 'logger', 'cors', 'responses'],
    order: [
      "Define the middlewares' load order by putting their name in this array in the right order",
    ],
    after: ['parser', 'router'],
  },
};
  • load:
    • before: Array of middlewares that need to be loaded in the first place. The order of this array matters.
    • order: Array of middlewares that need to be loaded in a specific order.
    • after: Array of middlewares that need to be loaded at the end of the stack. The order of this array matters.

# Core middleware configurations

The core of Strapi embraces a small list of middlewares for performances, security and great error handling.

  • boom
  • cors
  • cron
  • csp
  • favicon
  • gzip
  • hsts
  • ip
  • language
  • logger
  • p3p
  • parser
  • public
  • responses
  • responseTime
  • router
  • session
  • xframe
  • xss

馃挕 TIP

The following middlewares cannot be disabled: responses, router, logger and boom.

# Global middlewares
  • favicon
    • path (string): Path to the favicon file. Default value: favicon.ico.
    • maxAge (integer): Cache-control max-age directive in ms. Default value: 86400000.
  • public
    • path (string): Path to the public folder. Default value: ./public.
    • maxAge (integer): Cache-control max-age directive in ms. Default value: 60000.
    • defaultIndex (boolean): Display default index page at / and /index.html. Default value: true.
# Request middlewares
  • session
    • enabled (boolean): Enable or disable sessions. Default value: false.
  • logger
    • level (string): Default log level. Default value: debug.
    • exposeInContext (boolean): Expose logger in context so it can be used through strapi.log.info(鈥榤y log鈥). Default value: true.
    • requests (boolean): Enable or disable requests logs. Default value: false.
  • parser (See koa-body (opens new window) for more information)
    • enabled(boolean): Enable or disable parser. Default value: true.
    • multipart (boolean): Enable or disable multipart bodies parsing. Default value: true.
    • jsonLimit (string|integer): The byte (if integer) limit of the JSON body. Default value: 1mb.
    • formLimit (string|integer): The byte (if integer) limit of the form body. Default value: 56k.
    • queryStringParser (see qs (opens new window) for a full list of options).
      • arrayLimit (integer): the maximum length of an array in the query string. Any array members with an index of greater than the limit will instead be converted to an object with the index as the key. Default value: 100.
      • depth (integer): maximum parsing depth of nested query string objects. Default value: 20.

馃挕 TIP

The session doesn't work with mongo as a client. The package that we should use is broken for now.

# Response middlewares
  • gzip (opens new window)
  • responseTime
    • enabled (boolean): Enable or not X-Response-Time header to response. Default value: false.
  • poweredBy
    • enabled (boolean): Enable or not X-Powered-By header to response. Default value: true.
    • value (string): The value of the header. Default value: Strapi <strapi.io>

馃挕 TIP

gzip compression via koa-compress uses Brotli (opens new window) by default, but is not configured with sensible defaults for most cases. If you experience slow response times with gzip enabled, consider disabling Brotli by passing {br: false} as an option. You may also pass more sensible params with {br: { params: { // YOUR PARAMS HERE } }}

# Security middlewares
  • csp (opens new window)
    • enabled (boolean): Enable or disable CSP to avoid Cross Site Scripting (XSS) and data injection attacks.
    • policy (string): Configures the Content-Security-Policy header. If not specified uses default value. Default value: undefined.
  • p3p (opens new window)
    • enabled (boolean): Enable or disable p3p.
  • hsts (opens new window)
    • enabled (boolean): Enable or disable HSTS.
    • maxAge (integer): Number of seconds HSTS is in effect. Default value: 31536000.
    • includeSubDomains (boolean): Applies HSTS to all subdomains of the host. Default value: true.
  • xframe (opens new window)
    • enabled (boolean): Enable or disable X-FRAME-OPTIONS headers in response.
    • value (string): The value for the header, e.g. DENY, SAMEORIGIN or ALLOW-FROM uri. Default value: SAMEORIGIN.
  • xss (opens new window)
    • enabled (boolean): Enable or disable XSS to prevent Cross Site Scripting (XSS) attacks in older IE browsers (IE8).
  • cors (opens new window)
    • enabled (boolean): Enable or disable CORS to prevent your server to be requested from another domain.
    • origin (string or array): Allowed URLs (http://example1.com, http://example2.com, ['http://www.example1.com', 'http://example1.com'] or allows everyone *). Default value: *.
    • expose (array): Configures the Access-Control-Expose-Headers CORS header. If not specified, no custom headers are exposed. Default value: ["WWW-Authenticate", "Server-Authorization"].
    • maxAge (integer): Configures the Access-Control-Max-Age CORS header. Default value: 31536000.
    • credentials (boolean): Configures the Access-Control-Allow-Credentials CORS header. Default value: true.
    • methods (array)|String - Configures the Access-Control-Allow-Methods CORS header. Default value: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"].
    • headers (array): Configures the Access-Control-Allow-Headers CORS header. If not specified, defaults to reflecting the headers specified in the request's Access-Control-Request-Headers header. Default value: ["Content-Type", "Authorization", "X-Frame-Options"].
  • ip
    • enabled (boolean): Enable or disable IP blocker. Default value: false.
    • whiteList (array): Whitelisted IPs. Default value: [].
    • blackList (array): Blacklisted IPs. Default value: [].

# Example

Create your custom middleware.

Path 鈥 ./middlewares/timer/index.js

module.exports = strapi => {
  return {
    initialize() {
      strapi.app.use(async (ctx, next) => {
        const start = Date.now();

        await next();

        const delta = Math.ceil(Date.now() - start);

        ctx.set('X-Response-Time', delta + 'ms');
      });
    },
  };
};

Enable the middleware in environments settings.

Load a middleware at the very first place

Path 鈥 ./config/middleware.js

module.exports = {
  load: {
    before: ['timer', 'responseTime', 'logger', 'cors', 'responses', 'gzip'],
    order: [
      "Define the middlewares' load order by putting their name in this array is the right order",
    ],
    after: ['parser', 'router'],
  },
  settings: {
    timer: {
      enabled: true,
    },
  },
};

# Functions

The ./config/functions/ folder contains a set of JavaScript files in order to add dynamic and logic based configurations.

All functions that are exposed in this folder are accessible via strapi.config.functions['fileName']();

# Bootstrap

Path 鈥 ./config/functions/bootstrap.js.

The bootstrap function is called at every server start. You can use it to add a specific logic at this moment of your server's lifecycle.

Here are some use cases:

  • Create an admin user if there isn't one.
  • Fill the database with some necessary data.
  • Load some environment variables.

The bootstrap function can be synchronous or asynchronous.

Synchronous

module.exports = () => {
  // some sync code
};

Return a promise

module.exports = () => {
  return new Promise(/* some code */);
};

Asynchronous

module.exports = async () => {
  await someSetup();
};

# CRON tasks

CRON tasks allow you to schedule jobs (arbitrary functions) for execution at specific dates, with optional recurrence rules. It only uses a single timer at any given time (rather than reevaluating upcoming jobs every second/minute).

This feature is powered by node-schedule (opens new window) node modules. Check it for more information.

鉁 CAUTION

Make sure the enabled cron config is set to true in ./config/server.js file.

The cron format consists of:

*    *    *    *    *    *
鈹    鈹    鈹    鈹    鈹    鈹
鈹    鈹    鈹    鈹    鈹    |
鈹    鈹    鈹    鈹    鈹    鈹 day of week (0 - 7) (0 or 7 is Sun)
鈹    鈹    鈹    鈹    鈹斺攢鈹鈹鈹鈹 month (1 - 12)
鈹    鈹    鈹    鈹斺攢鈹鈹鈹鈹鈹鈹鈹鈹鈹 day of month (1 - 31)
鈹    鈹    鈹斺攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 hour (0 - 23)
鈹    鈹斺攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 minute (0 - 59)
鈹斺攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 second (0 - 59, OPTIONAL)

To define a CRON job, add your logic like below:

Path 鈥 ./config/functions/cron.js.

module.exports = {
  /**
   * Simple example.
   * Every monday at 1am.
   */

  '0 0 1 * * 1': () => {
    // Add your own logic here (e.g. send a queue of email, create a database backup, etc.).
  },
};

If your CRON task is required to run based on a specific timezone then you can configure the task like below:

module.exports = {
  /**
   * CRON task with timezone example.
   * Every monday at 1am for Asia/Dhaka timezone.
   * List of valid timezones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
   */

  '0 0 1 * * 1': {
    task: () => {
      // Add your own logic here (e.g. send a queue of email, create a database backup, etc.).
    },
    options: {
      tz: 'Asia/Dhaka',
    },
  },
};

# Database ORM customization

When present, they are loaded to let you customize your database connection instance, for example for adding some plugin, customizing parameters, etc.

You will need to install the plugin using the normal npm install the-plugin-name or any of the other supported package tools such as yarn then follow the below examples to load them.

# Public assets

Public assets are static files such as images, video, css, etc. that you want to make accessible to the outside world.

Because an API may need to serve static assets, every new Strapi project includes by default, a folder named /public. Any file located in this directory is accessible if the request's path doesn't match any other defined route and if it matches a public file name.

Example:

An image named company-logo.png in ./public/ is accessible through /company-logo.png URL.

馃挕 TIP

index.html files are served if the request corresponds to a folder name (/pictures url will try to serve public/pictures/index.html file).

鉁 CAUTION

The dotfiles are not exposed. It means that every file name that starts with ., such as .htaccess or .gitignore, are not served.

# Single Sign On Gold (opens new window)


Single-Sign-On on Strapi allows you to configure additional sign-in and sign-up methods for your administration panel.

PREREQUISITES

  • A Strapi application running on version 3.5.0 or higher is required.
  • To configure SSO on your application, you will need an EE license with a Gold plan.
  • Make sure Strapi is part of the applications you can access with your provider. For example, with Microsoft (Azure) Active Directory, you must first ask someone with the right permissions to add Strapi to the list of allowed applications. Please refer to your provider(s) documentation to learn more about that.

鉁 CAUTION

It is currently not possible to associate a unique SSO provider to an email address used for a Strapi account, meaning that the access to a Strapi account cannot be restricted to only one SSO provider. For more information and workarounds to solve this issue, please refer to the dedicated GitHub issue (opens new window).

# Usage

SSO configuration lives in the server configuration of your application found within /config/server.js.

# Accessing the configuration

The providers' configuration should be written within the admin.auth.providers path of the server configuration.

admin.auth.providers is an array of provider configuration.

module.exports = ({ env }) => ({
  // ...
  admin: {
    // ...
    auth: {
      providers: [], // The providers' configuration lives there
    },
  },
});
# Provider Configuration

A provider's configuration is a Javascript object built with the following properties:

Name Required Type Description
uid true string The UID of the strategy. It must match the strategy's name
displayName true string The name that will be used on the login page to reference the provider
icon false string An image URL. If specified, it will replace the displayName on the login page
createStrategy true function A factory that will build and return a new passport strategy for your provider. Takes the strapi instance as parameter

馃挕 TIP

The uid property is the unique identifier of each strategy and is generally found in the strategy's package. If you are not sure of what it refers to, please contact the maintainer of the strategy.

# The createStrategy Factory

A passport strategy is usually built by instantiating it using 2 parameters: the configuration object, and the verify function.

Configuration Object

The configuration object depends on the strategy needs, but often asks for a callback URL to be redirected to once the connection has been made on the provider side.

You can generate a specific callback URL for your provider using the getStrategyCallbackURL method. This URL also needs to be written on the provider side in order to allow redirection from it.

The format of the callback URL is the following: /admin/connect/<provider_uid>.

馃挕 TIP

strapi.admin.services.passport.getStrategyCallbackURL is a Strapi helper you can use to get a callback URL for a specific provider. It takes a provider name as a parameter and returns a URL.

If needed, this is also where you will put your client ID and secret key for your OAuth2 application.

Verify Function

The verify function is used here as a middleware allowing the user to transform and make extra processing on the data returned from the provider API.

This function always takes a done method as last parameter which is used to transfer needed data to the Strapi layer of SSO.

Its signature is the following: void done(error: any, data: object); and it follows the following rules:

  • If error is not set to null, then the data sent is ignored, and the controller will throw an error.
  • If the SSO's auto-registration feature is disabled, then the data object only need to be composed of an email property.
  • If the SSO's auto-registration feature is enabled, then you will need to define (in addition to the email) either a username property or both firstname and lastname within the data oject.
# Adding a provider

Adding a new provider means adding a new way for your administrators to log-in.

To achieve a great flexibility and a large choice of provider, Strapi uses Passport.js (opens new window). Any valid passport strategy that doesn't need additional custom data should therefore work with Strapi.

鉁 CAUTION

Strategies such as ldapauth (opens new window) don't work out of the box since they require extra data to be sent from the admin panel. If you want to add an LDAP provider to your application, you will need to write a custom strategy (opens new window). You can also use services such as Okta and Auth0 as bridge services.

# Configuring the provider

To configure a provider, follow the procedure below:

  1. Make sure to import your strategy in your server configuration file, either from an installed package or a local file.
  2. You'll need to add a new item to the admin.auth.providers array in your server configuration that will match the format given above
  3. Restart your application, the provider should appear on your admin login page.
# Examples
# Advanced Customization
# Admin Panel URL

If your administration panel lives on a different host/port than your Strapi server, you will need to modify the admin URL. To do so, head to your /config/server.js configuration file and tweak the admin.url field.

For example, if your admin application has been started on https://api.example.com, your configuration will look like the following:

/config/server.js

module.exports = () => ({
  // ...
  admin: {
    // ...
    url: 'https://api.example.com/admin',
  },
});
# Custom Logic

In some scenarios, you will want to write additional logic for your connection workflow such as:

  • Restricting connection and registration for a specific domain
  • Triggering actions on connection attempt
  • Analytics

The easiest way to do so is to plug into the verify function of your strategy and write some code.

For example, if you want to allow only people with an official strapi.io email address, you can instantiate your strategy like this:

const strategyInstance = new Strategy(configuration, ({ email, username }, done) => {
  // If the email ends with @strapi.io
  if (email.endsWith('@strapi.io')) {
    // Then we continue with the data given by the provider
    return done(null, { email, username });
  }

  // Otherwise, we continue by sending an error to the done function
  done(new Error('Forbidden email address'));
});
# Authentication Events

The SSO feature adds a new authentication event: onSSOAutoRegistration.

This event is triggered whenever a user is created using the auto-register feature added by SSO. It contains the created user (event.user), and the provider used to make the registration (event.provider).

Example:

/config/server.js

module.exports = () => ({
  // ...
  admin: {
    // ...
    auth: {
      // ...
      events: {
        onConnectionSuccess(e) {},
        onConnectionError(e) {},
        // ...
        onSSOAutoRegistration(e) {
          const { user, provider } = e;

          console.log(
            `A new user (${user.id}) has been automatically registered using ${provider}`
          );
        },
      },
    },
  },
});

# Role-Based Access Control Bronze Silver Gold (opens new window)

鉁 馃毀 This API is considered unstable for now.


Role-Based Access Control (RBAC) is an approach to restricting access to some users. In a Strapi application, users of the admin panel are administrators. Their roles and permissions are configured in the admin panel. The Community Edition of Strapi offers 3 default roles (Author, Editor, and Super Admin). To go further, creating custom conditions for any type of permission is also possible. This requires an Enterprise Edition with at minimum a Bronze licence plan.

# Declaring new conditions

Declare a single condition as an object, and multiple conditions as an array of objects. Each condition object can have 5 possible properties:

  • displayName (string): the condition name as shown in the admin panel,
  • name (string): the condition name, kebab-cased,
  • category (string, optional): conditions can be grouped into categories available in the admin panel; if undefined, the condition will appear under the "Default" category,
  • plugin (string, optional): if the condition is created by a plugin, should be the plugin's name, kebab-cased (e.g content-manager),
  • handler: a function used to verify the condition (see using the condition handler)

Declare and register conditions in your ./config/functions/bootstrap.js file (see Registering conditions).

鉁忥笍 NOTE

The condition name property acts as a unique id (opens new window) within its namespace, that is either the plugin if the plugin property is defined, or the root namespace.

# Using the condition handler

A condition can be applied to any permission, and the condition handler is used to verify the condition. The handler is a function returning a query object or a boolean value.

Query objects are useful to verify conditions on the entities you read, create, update, delete or publish. They use the sift.js (opens new window) library, but only with the following supported operators:

  • $or
  • $and
  • $eq
  • $ne
  • $in
  • $nin
  • $lt
  • $lte
  • $gt
  • $gte
  • $exists
  • $elemMatch

The condition handler can be a synchronous or asynchronous function that:

  • receives the authenticated user making the request,
  • and returns true, false, or a query object.

Returning true or false is useful to verify an external condition or a condition on the authenticated user. For instance, a condition that allows access to a page in the admin panel only if server time is 5pm could use this handler:

  handler: () => new Date().getHours() === 17

The handler function receives the authenticated user, so it can verify conditions on the user:

const condition = {
  displayName: "Email address from strapi.io",
  name: "email-strapi-dot-io",
  async handler(user) {
    return user.email.includes('@strapi.io');
  },
};

For more granular control, the handler function can also return a query object:

  const condition = {
    displayName: "price greater than 50",
    name: "price-gt-50",
    async handler(user) {
      return { price: { $gt: 50 } };
    },
 };

# Registering conditions

To be available in the admin panel, conditions should be declared and registered in the ./config/functions/bootstrap.js file. Register a single condition with the conditionProvider.register() method:

module.exports = async () => {
  await strapi.admin.services.permission.conditionProvider.register({
    displayName: 'Billing amount under 10K',
    name: 'billing-amount-under-10k',
    plugin: 'admin',
    handler: { amount: { $lt: 10000 }},
  });
};

To register multiple conditions, defined as an array of condition objects, use conditionProvider.registerMany():

const conditions = [
  {
    displayName: "Entity has same name as user",
    name: "same-name-as-user",
    plugin: "name of a plugin if created in a plugin"
    handler: (user) => {
      return { name: user.name };
    },
  },
  {
    displayName: "Email address from strapi.io",
    name: "email-strapi-dot-io",
    async handler(user) {
      return user.email.includes('@strapi.io');
    },
  }
];

module.exports = async () => {
  // do your boostrap

  await strapi.admin.services.permission.conditionProvider.registerMany(conditions);
};