Skip to content

Access-controlled files

The Access-controlled files feature restricts access to files and media uploaded to the WordPress Media Library. Two modes of Access-controlled files are supported: Restrict access to unpublished files or Restrict access to all files.

Limitations

  • Only one mode can be enabled on a single WordPress site at a single time.
  • The Access-controlled files feature has no effect on static files (e.g., CSS, JS) committed to an application’s GitHub repository.
  • The Access-controlled files feature is incompatible with Basic Authentication.
  • A VIP Local Development Environment will be unable to proxy media files from a WordPress multisite environment that has the Access-controlled files feature activated.

Prerequisites

Enable “Restrict access to unpublished files” mode

When the Restrict access to unpublished files mode is enabled, files attached to draft content can only be downloaded or viewed if the request comes from a logged-in WordPress user who is authorized to view the content the file is attached to.

Restrict access to unpublished files mode is useful if sensitive content is regularly posted and limited access to the media attached to that content is desired.

  • This mode will only apply to files uploaded directly via the post editor. That creates a parent-child relationship between the post and file, which is then used to determine access and permissions.
  • This mode will not apply to files uploaded directly to the WordPress Media Library, even if the file is later inserted into the post from the Media Library or a link to the file is copy-pasted directly into the post.

To code enable Restrict access to unpublished files mode on a WordPress single site—or for all sites on a WordPress multisite—add the code shown in the example below to a file in the /client-mu-plugins directory.

To code enable Restrict access to unpublished files mode per-network site on a WordPress multisite:

  • Add the code example below to a file in /client-mu-plugins. Include conditional logic in the code to selectively enable the mode for one or more specific sites using get_current_blog_id().
  • Or, add the code example below to functions.php of a network site’s theme, or any other loaded path in the theme or a plugin enabled for a specific site.
// Restrict access to unpublished files mode
add_filter( 'pre_option_vip_files_acl_restrict_unpublished_enabled', function( $value ) {
    return 1;
} );

To enable Restrict access to unpublished files mode with VIP-CLI, the vip_files_acl_restrict_unpublished_enabled option must be added and set to a value of 1. For example:

vip @<app-name>.<env> -- wp option add vip_files_acl_restrict_unpublished_enabled 1

Once the vip_files_acl_restrict_unpublished_enabled option exists, Restrict access to unpublished files mode can be disabled by updating the value to 0 and re-enabled by updating the value to 1. For example, to disable:

vip @<app-name>.<env> -- wp option update vip_files_acl_restrict_unpublished_enabled 0

Enable for a network site

Selectively enable Restrict access to unpublished files mode for a network site on a WordPress multisite by running the command with the --url=<url> flag and replacing <url> with the site’s URL.

vip @<app-name>.<env> -- wp option add vip_files_acl_restrict_unpublished_enabled 1 --url=<url>

Enable “Restrict access to all files” mode

When Restrict access to all files mode is enabled, all files in the site can only be downloaded or viewed by logged-in WordPress users with capability to “read” the published content on the site. This mode is useful for intranets and private sites.

To code enable Restrict access to all files mode on a WordPress single site—or for all sites on a WordPress multisite—add the code shown in the example below to a file in the /client-mu-plugins directory.

To code enable Restrict access to all files mode per-network site on a WordPress multisite:

  • Add the code example below to a file in /client-mu-plugins. Include conditional logic in the code to selectively enable the mode for one or more specific sites using get_current_blog_id().
  • Or, add the code example below to functions.php of a network site’s theme, or any other loaded path in the theme or a plugin enabled for a specific site.
// Restrict access to all files mode
add_filter( 'pre_option_vip_files_acl_restrict_all_enabled', function( $value ) {
    return 1;
} );

To enable Restrict access to all files mode with VIP-CLI, the vip_files_acl_restrict_all_enabled option must be added and set to a value of 1. For example:

vip @<app-name>.<env> -- wp option update vip_files_acl_restrict_all_enabled 1

Once the vip_files_acl_restrict_all_enabled option exists, Restrict access to all files mode can be disabled by updating the value to 0 and re-enabled by updating the value to 1. For example, to disable:

vip @<app-name>.<env> -- wp option update vip_files_acl_restrict_all_enabled 0

Enable for a network site

Selectively enable Restrict access to all files mode for a network site on a WordPress multisite by running the command with the --url=<url> flag and replacing <url> with the site’s URL.

vip @<app-name>.<env> -- wp option add vip_files_acl_restrict_all_enabled 1 --url=<url>

Allow access to Access-controlled files for specific requests

The vip_files_acl_file_visibility filter is useful for mobile applications or plugins that require access to Access-controlled files.

The vip_files_acl_file_visibility filter validates if a request for an Access-controlled file is legitimate. The filter accepts the parameters $file_visibility and $file_path, and returns one of the filter value constants (i.e., Automattic\VIP\Files\Acl\FILE_IS_PUBLIC , Automattic\VIP\Files\Acl\FILE_IS_PRIVATE_AND_ALLOWED , and Automattic\VIP\Files\Acl\FILE_IS_PRIVATE_AND_DENIED) to indicate what level of access to a file can be granted for a request.

Requests for Access-controlled files can be sent with HTTP Authorization header X-Original-Authorization and User Agent X-Original-User-Agent. One or both of these headers can be included in a vip_files_acl_file_visibility filter for additional validation of a request.

The HTTP Authorization header can be sent with credentials for authenticating a request. If the token value assigned to the Authorization header in a request can be matched and validated by the environment receiving the request, the request is identified as legitimate. A matching value on the receiving environment can be stored as an environment variable.

In this code example, requests from a mobile application are granted access to Access-controlled files if the token passed by X-Original-Authorization matches the environment variable APP_FILE_ACCESS_TOKEN, and the filter value constant returned is FILE_IS_PRIVATE_AND_ALLOWED:

/**
 * Allow mobile app requests to have access to Access-controlled files
 */
function vip_check_file_visibility_for_mobile_request( $file_visibility, $file_path ) {
    /**
     * Allow mobile requests with a token
     */
    $token_header = isset( $_SERVER['HTTP_X_ORIGINAL_AUTHORIZATION'] ) ? sanitize_text_field( $_SERVER['HTTP_X_ORIGINAL_AUTHORIZATION'] ) : false;

    // Get token from environment variable.
    $token = vip_get_env_var( 'APP_FILE_ACCESS_TOKEN', '' );
    if ( $token === $token_header ) {
        return Automattic\VIP\Files\Acl\FILE_IS_PRIVATE_AND_ALLOWED;
    }

    return $file_visibility;
}
add_filter( 'vip_files_acl_file_visibility', 'vip_check_file_visibility_for_mobile_request', 11, 2 );

Considerations

Performance Impact

Enabling this feature can increase response times for files uploaded to the WordPress Media Library. Serving a file while this feature is active may involve a request to the WordPress application to determine per-user permissions, adding to the overall response time.

  • For Access-controlled files and media, all requests can be around 10-15% slower.
  • For public files and media, the first (uncached) request is expected to be around 10-15% slower. All future requests are cached and should not be impacted.

Incompatible with Basic Authentication

This feature is incompatible with VIP’s Basic Authentication. Environments with Basic Authentication enabled cannot activate the Access-controlled files feature.

To restrict access to the front end of a site while the Access-controlled files feature is active, using a different access restriction method is recommended, such as the maintenance mode plugin.

Potential conflict for self-referencing files

It might be necessary to import a WordPress XML file to an environment that has the same domain as the site from which the XML file was exported. This will result in an import that is “self-referencing”, meaning that it both exports from and imports into the same domain. An import of this kind can happen when adding media library references to a site’s media library following a media import.

If Access-controlled files is enabled, the WordPress importer will be unable to access the media path for a given media asset. The WordPress importer is only able to add media references to a media library if the media path is publicly accessible.

To prevent this issue, set VIP_FILES_ACL_ENABLED to false in /vip-config/vip-config.php for the duration of the XML import. The constant can be set back to true after the import has been completed.

Last updated: March 19, 2024

Relevant to

  • WordPress