Securing External Applications Embedded via iframe in WordPress with Token-Based Authentication

I have a WordPress site. I've developed three simple applications (features for testing) that are hosted externally (currently on Netlify). I want a small group of logged-in users on my site (employees using the service, around 100 people) to test these features. I've embedded these applications on WordPress pages using a standard iframe, which works fine, but now I need to add some security measures. Below is the logic I came up with. Please bear with me, as I work as a data analyst and engineer daily—this isn’t my primary area of expertise: Users register on the site (using the UserRegistration plugin), and after approval by an administrator, they gain access to protected content. I’m using the Members plugin, which allows creating custom roles and granting those roles access to specific pages. If someone lands on a page with a specific feature and isn’t logged in, a message is displayed stating the content is unavailable, and they are asked to log in. In this step, I need to secure the applications and prevent them from being used outside of the iframe. Below is the security logic I’ve considered: Securing the External Application: Implement a token system in the external application. When a user logs in to WordPress, generate a unique session token (it doesn’t have to be a full JWT). Store this token in the WordPress database, linked to the user ID and expiration time. Create a simple WordPress plugin that acts as an intermediary between WordPress and the external application. The plugin should: a) Check if the user is logged in and has the appropriate permissions. b) If so, generate a session token and store it in the database. c) Pass the token to the iframe as a URL parameter. The iframe should: a) Receive the token from the URL parameter. b) Validate the token with the WordPress server (via API). c) If the token is valid, load the appropriate application. WordPress API: Create a simple API endpoint in WordPress (this can be done as part of the plugin). The endpoint should accept the token and return whether the token is valid along with basic user information (e.g., ID, role). The implementation might look like this: Create a new page in WordPress where the iframe with your application will be embedded. Use the Members plugin or built-in WordPress functions to restrict access to this page only for logged-in users. Creating a simple WordPress plugin: Create a new plugin in WordPress that generates a unique token for the logged-in user. Add the following code to the main plugin file: /* Plugin Name: App Access Token */ function generate_app_token() { if (is_user_logged_in()) { $user_id = get_current_user_id(); $token = md5($user_id . time() . wp_rand()); update_user_meta($user_id, 'app_access_token', $token); return $token; } return false; } function modify_iframe_src($content) { if (is_page('your-iframe-page-slug')) { // Replace with your page slug $token = generate_app_token(); if ($token) { $content = str_replace('https://netlify.app/', 'https://netlify.app/?token=' . $token, $content); } } return $content; } add_filter('the_content', 'modify_iframe_src'); Modifying the application on Netlify: In your React application (assuming you’re using React), add logic to check the token from the URL: import React, { useEffect, useState } from 'react'; function App() { const [isAuthenticated, setIsAuthenticated] = useState(false); useEffect(() => { const urlParams = new URLSearchParams(window.location.search); const token = urlParams.get('token'); if (token) { // Here, you should add logic to verify the token with WordPress // For simplicity, we assume any token is valid setIsAuthenticated(true); } }, []); if (!isAuthenticated) { return <div>Access denied. Please log in on the WordPress site.</div>; } return ( // Your main application ); } export default App; Adding an API endpoint in WordPress: Add the following code to your WordPress plugin: add_action('rest_api_init', function () { register_rest_route('myapp/v1', '/verify-token', array( 'methods' => 'GET', 'callback' => 'verify_app_token', )); }); function verify_app_token($request) { $token = $request->get_param('token'); global $wpdb; $user_id = $wpdb->get_var($wpdb->prepare( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'app_access_token' AND meta_value = %s", $token )); if ($user_id) { return new WP_REST_Response(array('valid' => true, 'user_id' => $user_id), 200); } else { return new WP_REST_Response(array('valid' => false), 401); } } Updating the React application to verify the token: Modify the React code to verify the token with the WordPress API: useEffect(() => { const urlParams = new URLSearchParams(window.location.search); const token = urlParams.get('token'); if (token) { fetch(`https://wordpress-site.com/wp-json/myapp/v1/verify-token?token=${token}`) .then(response => response.json()) .then(data => { if (data.valid) { setIsAuthenticated(true); } }) .catch(error => console.error('Error:', error)); } }, []); Configure CORS in WordPress: Add the following code to your WordPress theme’s functions.php file: add_action('init', 'handle_preflight'); function handle_preflight() { header("Access-Control-Allow-Origin: https://netlify.app"); header("Access-Control-Allow-Methods: GET,POST,OPTIONS"); header("Access-Control-Allow-Headers: Content-Type"); if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { status_header(200); exit(); } } Given the approach described above for securing external applications embedded in WordPress using token-based authentication, I have two specific questions: 1. Does this solution cover all necessary aspects of security, or have I overlooked anything critical? 2. Are there any alternative methods or simpler approaches to achieve the same level of security for these external applications in this context? Any guidance or suggestions would be greatly appreciated.

Comment (0)

You’ll be in good company