How I Secured My Static Site’s API Keys Using WordPress as a Backend

How I Secured My Static Site’s API Keys Using WordPress as a Backend

How I Secured My Static Site's API Keys Using WordPress as a Backend

How I discovered a simple solution to protect API keys in static websites using WordPress


My Journey Begins

A few years ago, I decided to improve my frontend development skills. To make it practical, I came up with the idea of building a static website. The goal was simple: showcase my blog articles and professional experiences.

However, I didn't stop there. I wanted to add a contact form and—because I love cycling—I had the brilliant idea to add weather information.

Why weather? Simple: I enjoy riding my bike, but I don't enjoy getting wet. Therefore, having accurate weather data for the next 1–2 hours in my town was important to me.

The First Steps

I started developing the site. The frontend part was challenging. Nevertheless, integrating the weather API was surprisingly easy.

Here's what I did:

  • Created an account with the weather service
  • Got my API key
  • Added it to my code
  • Everything worked smoothly

The Security Wake-Up Call

But—there's always a "but"—later, during my cybersecurity training, I realized something alarming. My API token was publicly accessible.

That was a wake-up call.

Consequently, I began researching how to secure API usage in a static site. To my surprise, it wasn't straightforward.

The Hard Truth About Static Sites

Here's the truth: in a static site, you can't keep secrets.

Why? Because everything runs in the browser. Any API key in your JavaScript is visible to anyone who opens the developer console.

The only real solution? Use a backend.

Exploring Backend Options

So I started exploring lightweight backend options to handle this securely. I considered three main approaches:

  • A custom backend
  • Netlify functions
  • WordPress

Let me explain each option and why I made my final choice.

Option 1: Custom Backend

Creating a custom backend would have been the easiest solution technically. However, I wanted to keep the site static. Moreover, I wanted to host it on my existing server—which I already pay for.

Therefore, I didn't want extra costs just for a small backend.

Option 2: Netlify Functions

Next, I tried Netlify, a great project I hadn't heard of before. It worked really well.

But there was a catch: I had to publish the entire site on Netlify. Since I wanted to host it on my own server, that wasn't ideal.

Option 3: WordPress (The Winner!)

Then I had an idea: my server already runs WordPress.

Could WordPress act as my backend?

The answer turned out to be yes!


How WordPress Became My API Backend

I discovered that you can add custom API endpoints directly in WordPress. As a result, your frontend can call them securely.

This way, the API key stays on the server. The static site never exposes it.

The Three-Step Approach

Here's the approach I used:

  1. Create a custom endpoint in WordPress using add_action('rest_api_init', ...)
  2. Write a PHP function that fetches weather data using your API key
  3. Return the data as JSON to your frontend

Simple, right? Let me show you the actual code.

Implementation Example

Here's the code I used in my functions.php:

add_action('rest_api_init', function () {
    register_rest_route('custom/v1', '/weather', array(
        'methods' => 'GET',
        'callback' => 'get_weather_data',
    ));
});

function get_weather_data() {
    // API key stored securely on the server
    $api_key = 'YOUR_SECRET_API_KEY';
    $city = 'Paris';
    $url = "https://api.weatherprovider.com/data?city={$city}&key={$api_key}";

    $response = wp_remote_get($url);

    if (is_wp_error($response)) {
        return ['error' => 'Unable to fetch weather data'];
    }

    return json_decode(wp_remote_retrieve_body($response), true);
}

Calling It from My Static Site

My static site can now call the WordPress endpoint. It looks like this:

async function getWeather() {
    const response = await fetch('https://yourwordpresssite.com/wp-json/custom/v1/weather');
    const data = await response.json();
    // Display weather data
}

That's it! Simple and secure. No API key exposed to the client.


Bonus: Adding Cache and Rate Limiting

Once I got the basic setup working, I added a few improvements. These optimizations made the solution even better.

Caching to Reduce API Calls

First, I added caching. This reduces the number of calls to the weather API. As a result, I save on API quota and improve response time.

function get_weather_data() {
    $cache_key = 'weather_data';
    $cached = get_transient($cache_key);

    // Return cached data if available
    if ($cached !== false) {
        return $cached;
    }

    // ... fetch from API ...

    // Cache for 15 minutes
    set_transient($cache_key, $data, 15 * MINUTE_IN_SECONDS);
    return $data;
}

Rate Limiting to Prevent Abuse

Next, I added rate limiting. This prevents someone from overwhelming my server with requests.

function get_weather_data() {
    $ip = $_SERVER['REMOTE_ADDR'];
    $limit_key = 'weather_limit_' . md5($ip);

    if (get_transient($limit_key)) {
        return new WP_Error('rate_limit', 'Too many requests', ['status' => 429]);
    }

    // Allow 1 request per minute per IP
    set_transient($limit_key, true, 60);

    // ... rest of the code ...
}

Lessons Learned

This project taught me several important lessons:

About Static Sites

Static sites are great. However, they have limitations when it comes to secrets. You simply cannot hide credentials in client-side code.

About Security

Security matters. Never expose API keys in client-side code. Always use a backend proxy for sensitive operations.

About WordPress

WordPress is more versatile than you think. It's not just a blogging platform. In fact, it can act as a lightweight backend for your static site.

Why I Chose WordPress

The main reasons this solution worked for me:

First, I already had WordPress running on my server. No need to set up additional infrastructure.

Second, no extra costs. I was already paying for the hosting. Therefore, this solution was essentially free.

Third, simple setup. Just add code to functions.php. No complex deployment pipelines.

Fourth, easy to maintain. Update API keys in one place. No need to redeploy the entire site.

Finally, built-in features. WordPress provides caching, error handling, and more out of the box.

Conclusion

What started as a simple static site project taught me an important lesson about web security.

The journey was valuable. Going from exposing my API key to implementing a secure solution made me a better developer.

My Hope for You

If you're building a static site and need to integrate APIs securely, I hope my experience helps you. Moreover, I hope you avoid the same mistakes I made.

Whether you use WordPress or another backend solution, remember this: never trust the client with secrets.

The Final Result

Now I can check the weather before my bike rides. I don't worry about security vulnerabilities anymore.

And honestly? That feels pretty good.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *