Skip to main content

WordPress Plugin (CA Manager)

Objective

Install CA Manager on a WordPress site and enable the automatic issuance of CAs.

Prerequisites

  • WordPress administrator privileges

Procedure

1. Plugin Installation

  1. Download the plugin: Visit the "Releases" page and download the WordPress plugin (wordpress-ca-manager.zip) from the Assets section.
  2. Upload the plugin: Refer to the "Upload Plugin" section on the WordPress "Add Plugins" screen.
  3. Activate the plugin.
  4. Configure the plugin: Go to "Settings > CA Manager" in the WordPress admin dashboard and enter the required information as described in the next section, "Plugin Settings."

2. Plugin Settings

After activating the plugin, you must configure it by entering the following required fields. Settings can be configured via the WordPress dashboard under Settings > CA Manager.

[CA issuer's Originator Profile ID]: Specify your Originator Profile ID

Example:

dns:media.example.com

[CA Server Hostname]: Specify the hostname of the CA server to use

Example:

dprexpt.originator-profile.org

[Authentication Information]: Specify the information required to access the CA server

Example:

cfbff0d1-9375-5685-968c-48ce8b15ae17:GVWoXikZIqzdxzB3CieDHL-FefBT31IfpjdbtAJtBcU

Verification Target Type

Example:

TextTargetIntegrity

CSS Selector for Verification Target Element

Example:

h1.wp-block-post-title, .wp-block-post-content>*:not(.post-nav-links)

HTML Containing the Verification Target Element

Example:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1 class="wp-block-post-title">%TITLE%</h1>
<div class="wp-block-post-content">%CONTENT%</div>
</body>
</html>

%TITLE% is replaced by the post title, and %CONTENT% is replaced by the WordPress post content after apply_filters() has been applied; these are then sent to the CA server as the target[0].content property of the request.

[CA Presentation Type]: Specify whether the CAS is embedded or linked

The default is "Embedded".

  • Embedded: Posts the article with the CAS in embedded format.

Example of the HTML output when "Embedded" is selected:

<script type="application/cas+json">
["eyJ..."]
</script>

Log Output Settings

This is disabled by default.

If enabled, logs related to the CA Manager plugin will be generated, and you will be able to download the log files. For details on the generated log files, please refer to "Log file generation."

The Content Attestation issuance function will not operate correctly unless these settings are configured. Once the settings are correctly applied, any posts updated or created thereafter will be automatically sent to the CA server.

How to Check

Once configuration is complete, create a new post or update (re-save) an existing post. You can verify whether the CA has been correctly issued using the following two methods:

  • Check using Developer Tools
    Open your browser's developer tools and check if a <script> tag with the type cas+json is embedded in the page. If an element like the one below exists, the CA has been issued and configured correctly.

Example:

<script type="application/cas+json">
["eyJ..."]
</script>

Note: This method does not show verification results; use it only for a quick check to see if the CA has been issued.

  • Check using OP Inspector or Debugger Use OP Inspector or Debugger for a more detailed check.

    • Does the CA exist on the target page?
    • Was the CA verification successful?

    You can verify these points. Please refer to the OP Inspector documentation and Debugger documentation for instructions on how to use each tool.

If the CA does not exist

  • The plugin settings may be incorrect.
  • Enable the log output setting, save the page, and check the logs. For log output settings, please refer to Plugin Settings.

If verification fails

  • The cause depends on the error code.
  • Please refer to the Error Code List for details.

Features and Reference Information

Features

The main features of this plugin are as follows:

  1. Processing post content upon posting or updating in WordPress

    • Triggered by posting or updating content in WordPress
    • Processes the post content based on this trigger and sends it to the CA server's CA registration/update endpoint
  2. CAS delivery on WordPress post pages

Processing Flow

The processing flow for the WordPress integration plugin is as follows. It is assumed here that the user is utilizing a web browser and the extension.

Processing is executed in accordance with Hooks.

  • transition_post_status: Triggered when a post is created or updated; it converts the content and sends it to the CA server's registration or update endpoint.
    It is also triggered when a post changes from a published state to a non-published state (such as private or draft), using the content's CA ID to send a request to the CA server's deletion endpoint.
  • before_delete_post: Triggered when a post is deleted; it uses the content's CA ID to send a request to the CA server's deletion endpoint.
  • wp_head: Triggered when a post is viewed; it allows the user to retrieve the CAS via an embedded <script> element.

Through these processes, published content is automatically managed, enabling users to verify its authenticity.

File Structure

config.php

The config.php file, located in the includes directory, contains the configuration settings for this plugin.

Setting NameDescription
PROFILE_DEFAULT_CA_SERVER_HOSTNAMEThe default value for the Content Attestation server hostname. Registration, updates, and retrieval of Content Attestation data are performed via endpoints on this host. If the setting is modified via the configuration screen, this value is ignored.
PROFILE_DEFAULT_CA_SERVER_REQUEST_TIMEOUTThe default value for the Content Attestation server request timeout (in seconds).
PROFILE_DEFAULT_CA_TARGET_TYPEThe default value for the type of element to be verified.
PROFILE_DEFAULT_CA_TARGET_CSS_SELECTORThe default value for the CSS selector identifying the elements to be verified. By default, both the article title (h1.wp-block-post-title) and the direct child elements of the article body (.wp-block-post-content>*:not(.post-nav-links)) are targeted.
PROFILE_DEFAULT_CA_TARGET_HTMLThe default HTML structure containing the elements to be verified. %TITLE% is replaced by the post title, and %CONTENT% is replaced by the post body after apply_filters() has been applied.

CA Server API Authentication

Basic authentication for the CA server API is supported. Customization is required if you wish to use authentication methods other than Basic authentication (e.g., OAuth, JWT, API keys). For details on customization, please refer to the implementation of issue_ca() in includes/issue.php.

OP Support

Placing /.well-known/sp.json

Placement location:

If the document root is /var/www/html, place the file at the following path:

/var/www/html/.well-known/sp.json

Depending on your web server configuration, access to the .well-known directory may be restricted. Configure your server to allow access to .well-known as shown below:

Apache:

<Directory "/var/www/html/.well-known">
AllowOverride None
Require all granted
</Directory>

Verification:

$ curl -sSf https://example.com/.well-known/sp.json

Configuration is complete if the SP containing the OP information is successfully retrieved.

Alternative Method: Embedding the OP

It is possible to embed the OP directly into the HTML using a script element.

Example:

<script type="application/ops+json">
[
{
"core": "eyJ...",
"annotations": ["eyJ..."],
"media": ["eyJ..."]
}
]
</script>

For details, please refer to "Enabling OP Support on Your Site" or "Linking Content Attestation Set and Originator Profile Set to A HTML Document."

File Generation When CA Presentation Type is Set to "External" Link Format

When the CA Presentation Type is set to "External," the directory for generating static files is defined as follows:

const PROFILE_DEFAULT_CA_EXTERNAL_DIR = 'cas';

If the document root is /var/www/html, the static file will be placed at the following path:

/var/www/html/cas/<post-id>_cas.json

Example of the HTML output when "External" is selected:

<script
src="https://example.com/cas/1_cas.json"
type="application/cas+json"
></script>

If the cas directory does not exist under the document root, it will be created. Additionally, if the post ID is the same, the static file will be overwritten.

Verification method:

$ curl -sSf https://example.com/cas/1_cas.json

Log File Generation

The directory for generating log files is defined as follows:

const PROFILE_DEFAULT_CA_LOG_DIR = 'ca-manager-log';

If the document root is /var/www/html, logs are output to the following path. If the log file does not exist, it will be created.

/var/www/html/wp-content/uploads/ca-manager-log/ca-manager-debug.log

Additionally, when the CA Manager plugin is activated, files for access control are automatically generated at the following paths with the specified contents:

/var/www/html/wp-content/uploads/ca-manager-log/.htaccess
/var/www/html/wp-content/uploads/ca-manager-log/index.php

Apache:

<FilesMatch "\.(log|txt)$">
Require all denied
</FilesMatch>

Access control files for environments other than Apache are not automatically generated; please implement appropriate access control measures yourself (recommended).

Disabling the feature stops log output and deletes the log file.

Demo

A test environment with the plugin installed is available:

Please contact the development team if you require editing privileges for the demo site.

Usage with Playground

If you are unable to perform OP registration, you can use Playground to test the automatic issuance of Content Attestations (CAs). For details, please refer to the Playground guide.

Known Issues

Changing WordPress permalink settings alters the URLs of individual posts; consequently, previously issued Content Attestations (CAs) become invalid due to an allowedUrl mismatch.

Affected Actions:

  • Settings > Permalinks
    • Changing settings
    • Modifying the custom structure

If you change permalink settings, updating (editing and saving) all affected posts will trigger the re-issuance of CAs corresponding to the new URLs.

HTML Modification by Plugins, Filters, or Themes

In WordPress, you can split a post into multiple pages by inserting <!--nextpage--> into the post body. However, due to the influence of plugins, themes, or filter hooks, this may sometimes be output with incorrect markup, such as <p><!--nextpage--></p>. Such output can cause unintended line breaks or blank lines.

Workaround: You can correct the improper markup by applying a replacement process as follows:

// includes/issue.php

/**
* Create a list of unsigned Content Attestations
*
* @param \WP_Post $post Post object.
* @param string $issuer_id CA issuer ID
* @return list<Uca> List of unsigned Content Attestations
*/
function create_uca_list( \WP_Post $post, string $issuer_id ): array {
// ... Omitted ...

// Add replacement logic
$post->post_content = str_replace('<p><!--nextpage--></p>', '<!--nextpage-->', $post->post_content);

$postdata = \generate_postdata( $post );

// ... Omitted ...
}

Conflict with the Autoptimize Plugin

Autoptimize (including the Pro version) is a plugin that optimizes (minifies) HTML and images. This may cause the following problems:

Inconsistency with the Signed HTML

When the HTML before minification by Autoptimize is sent to the CA Server, it may not match the HTML that is actually displayed, potentially causing signature verification to fail.

Solution: Adjust the HTML after Autoptimize's minification process and send it to the CA Server.

Image URL Transformation via CDN in the Pro Version

In the Pro version, images are transformed via CDN, which may change their URLs. This can result in discrepancies between the signed HTML and the actual displayed content.

Response Plan: Obtain the image URL after CDN conversion and send the HTML reflecting it to the CA Server.

Data Deletion on the CA Server

If the CAS is stored in the metadata _profile_post_cas and the data on the CA server is manually deleted, an attempt will be made to register a new post specifying the UUID when updating the article. This may result in an error on the server side.

Workaround: Make the article private once to remove the metadata. By making it public again after that, it will be registered as a new entry without a specified UUID, and the registration will complete successfully.