We are going to finally use frontity_source_auth
as discussed in Support for auth header in Source packages because it won’t only contain the token, but the whole header
Just an important note:
The preview plugin uses a Bearer
token in the Authentication
header, so if you are using Apache as your web server you would need to add the following lines in your .htaccess
file in order to support it:
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
We have merged the PR: https://github.com/frontity/frontity-embedded-proof-of-concept/pull/3
We are also going to do a release of Frontity that supports the frontity_source_auth
query in the post type handlers later today as discussed in this FD: Auth header in Source packages and Frontity Query Options
Ok, it’s released now
To get the preview working in Frontity while using the Embedded mode, please:
- Update the Embedded mode PoC plugin to the latest version (1.1.0): https://github.com/frontity/frontity-embedded-proof-of-concept
- Update Frontity and its packages to the latest version: https://docs.frontity.org/guides/keep-frontity-updated
It should work without any extra work.
Let us know how it goes!!
If you are using a custom handler for the post types, you need to add support for the preview=true
query.
This is an example of the code that is required. Please adapt it to your needs.
// Overwrite properties if is a preview and a token is present in the state.
if (query.preview && state.source.auth) {
// Fetch the latest revision using the auth token.
const response = await libraries.source.api.get({
endpoint: `posts/${data.id}/revisions?per_page=1`,
params: state.source.params,
auth: state.source.auth,
});
// Get modified props from revision and merge them with the entity.
const [{ title, content, excerpt }] = await response.json();
const entity = state.source[data.type][data.id];
Object.assign(entity, { title, content, excerpt });
}
Preview works fine but images are not getting loaded on the preview. This is what I got in the console.
That’s weird. How are the URLs of the images and how they should be?
URLs are fine but images are not getting loaded, see
You can check it live here
WordPress: https://api.divaksh.com/beginners-guide-google-spreadsheet-using-java/
Frontity: https://divaksh.com/beginners-guide-google-spreadsheet-using-java/
Oh, it’s not the images what is not loaded. It’s the JavaScript. You’re using lazy loading for the images using JavaScript, so that’s the reason the images don’t load.
Once we release the final version of the Embedded mode this will be automatic, but for now you can use the --public-path
option to point the correct URL:
npx frontity build --public-path https://divaksh.com/static
Spent some time reviewing and testing this and it works well. Didn’t run into any issues getting it to work. Awesome work!
From a security standpoint, I don’t see any obvious issues but I see some potential for improvements.
Restrict capabilities that can be performed through the jwt token
I see that the approach taken here is very flexible and basically allows the creation of JWT token with any WP capabilities.
However, I wonder if that’s really necessary. If FRONTITY_JWT_AUTH_KEY
is leaked, it means that an attacker will be able to craft an arbitrary JWT token with any capability he wants, essentially gaining full control of the WP website through a feature that was built to add preview support. Unless we are trying to build an alternative authentication mechanism to the REST API, I’d suggest we change the approach a bit.
My suggestion here is to take capabilities
and allowed_methods
out of the JWT payload and replace with a type=preview
. Then when reading the token we validate the token and by checking the type we perform the necessary checks for allowed_methods and which capabilities we need to change in order to make that request successful. So even if the auth key is leaked, it would only expose the preview
feature.
We should also check if this token was generated by Frontity, either by checking the supported types or adding a “frontity signature” to it. Just to make sure we don’t try to read an token generated with SECURE_AUTH_KEY
for other purposes.
Minor: Avoid using glob to load files
In frontity-embedded.php
the PoC is using glob to include the files in php-jwt
, it’s preferable to just hardcode the files (or use an autoloader).
$jwt_files = array(
'BeforeValidException.php',
'ExpiredException.php',
'JWK.php',
'JWT.php',
'SignatureInvalidException.php',
);
// Load php-jwt classes.
foreach ( $jwt_files as $filename ) {
require_once plugin_dir_path( __FILE__ ) . '/includes/php-jwt/' . $filename;
}
Another potential but minor issue is that it is just going to include any files in that folder, which would give attackers a new way of running malicious code if they manage to upload a file to that folder.
Ah, on another note - at first I almost thought that subscribers users would be able preview any posts because we weren’t checking if the user had permission to edit the post when generating the token but as it turns out WordPress will return false in is_preview()
if the user logged in has no permission to preview a post.
If we want to be extra careful we could add an extra check to make sure the logged in user can indeed edit/preview a post.
$id = get_the_ID();
if ( $id && is_preview() && is_user_logged_in() && current_user_can( 'edit_post', $id ) ) {
Could be an extra layer of security if other plugins are messing with is_preview
.
Just a note here, I’ve never played with the _method
global parameter of the WP REST API and so I’m not sure if it could cause any security problems, but I think we should check that case because the capabilities
implementation checks the HTTP method used to make the REST API request.
I’m not sure which method would return $_SERVER[ 'REQUEST_METHOD' ]
with this call:
GET /wp-json/wp/v2/posts/42?_method=DELETE HTTP/1.1
Host: example.com
Thanks so much for your work here. Frontity is truly an incredible piece of software at this point. I am looking to support post previews on an upcoming project wiith Frontity, but I don’t see anything in the Docs or Guides. Searching brings me here to the community forums and I see the feature is marked “released”. Is there anywhere that a start-to-finish explanation on how to support post previews exists?
If not, could you give me a quick summary? I’d be happy to make a contribution in the form of documentation once I get this working in my project.
Thanks!
We have released some docs for the Embedded mode plugin (Frontity Embedded Mode - API Reference) and right now @mburridge and @juanma are working on a rewrite of the “Architecture” section of the main docs that explains the differences between the Decoupled mode and the Embedded mode: Rewrite of Architecture section by mburridge · Pull Request #296 · frontity/docs · GitHub
It’s also worth noting that you can use the Embedded mode for the post previews only, even if you use Frontity in Decoupled mode for the visitors.
Please review the docs and the PR and let us know what parts you think that need to be improved
Awesome, thanks! This all makes conceptual sense to me now that I’ve had a chance to look at embedded mode. My note about documentation would have been exactly what @mburridge and @juanma are working on in #296, bringing that to more eyes in the main docs.
Thanks again, all.
I’m glad to hear that
If you have more feedback, other comments, or want to help to improve this part of the docs please do so.