HIGH clickjackinghapiapi keys

Clickjacking in Hapi with Api Keys

Clickjacking in Hapi with Api Keys — how this specific combination creates or exposes the vulnerability

Clickjacking is a client-side social engineering attack where an invisible or disguised UI element tricks a user into performing unintended actions. In Hapi applications that rely on API keys for authentication, clickjacking can bypass intended authorization boundaries when API key handling is coupled with UI flows that lack frame-protection mechanisms.

When an endpoint validates access solely by the presence of a valid API key—typically passed via an Authorization header or a cookie—and the same endpoint serves HTML that is intended to be embedded, the application may expose actions to clickjacking. For example, an Hapi route that accepts an API key and performs a sensitive operation (such as changing an account email or initiating a fund transfer) can be loaded inside an invisible iframe on a malicious site. If the user is already authenticated via a session or long-lived API key cookie, the browser will automatically include that credential with the request, executing the action without the user’s consent.

The presence of API keys does not inherently protect against clickjacking; it can inadvertently increase risk if the API key is stored in a cookie without SameSite protections or if developers assume key-based authentication replaces the need for anti-CSRF and frame-defence controls. Attackers combine social engineering—such as a fake button claiming to "Refresh Profile"—with an invisible form that submits to the Hapi endpoint. Because the browser includes credentials automatically, the request succeeds, and the API key context is abused.

To illustrate, consider a Hapi route that expects an API key in an Authorization header and performs a state-changing POST. If this route returns HTML that can be embedded, and no X-Frame-Options or Content-Security-Policy frame-ancestors directive is set, an attacker can lure a victim to a page with:

<img src="https://api.example.com/change-email?api_key=STOLEN_KEY" style="display:none">
<iframe src="https://your-hapi-app.com/transfer" width="0" height="0" style="display:none"></iframe>

Even if the Hapi endpoint requires an API key, if the key is exposed in logs, browser history, or passed insecurely, the combined effect of a missing frame-protection policy and improper key usage enables successful clickjacking. This highlights the need for defense-in-depth: treat API keys as credentials that must be protected in transit and in storage, and enforce strict framing rules on any UI that shares routes with key-validated operations.

Api Keys-Specific Remediation in Hapi — concrete code fixes

Remediation focuses on two areas: protecting the API key material and preventing the UI from being framed. For API key handling, avoid embedding keys in URLs, enforce strict transport security, use HttpOnly and SameSite cookies when keys are stored in cookies, and rotate keys regularly. For UI routes, apply anti-clickjacking headers and ensure that endpoints performing sensitive actions do not serve embeddable content.

Below are concrete Hapi examples that implement these protections. The first example shows how to configure Hapi to reject requests that do not include a valid API key in a secure, HttpOnly cookie and to enforce SameSite and Secure flags. This reduces the risk of the key being leaked via logs or referer headers and limits exposure to cross-site contexts.

// Secure cookie-based API key handling in Hapi
const Hapi = require('@hapi/hapi');

const init = async () => {
  const server = Hapi.server({
    port: 3000,
    host: 'localhost',
    routes: {
      security: {
        hsts: {
          maxAge: 31536000,
          includeSubdomains: true,
          preload: true
        },
        frameguard: {
          action: 'deny' // Enforce X-Frame-Options equivalent
        }
      }
    }
  });

  server.ext('onPreResponse', (request, h) => {
    const response = request.response;
    if (response.variety === 'view') {
      // Ensure no sensitive keys in HTML-exposed contexts
      return response;
    }
    return h.continue;
  });

  server.route({
    method: 'POST',
    path: '/transfer',
    options: {
      handler: (request, h) => {
        // Validate API key from secure cookie
        const apiKey = request.state.apikey;
        if (!apiKey || !isValidKey(apiKey)) {
          return h.response('Unauthorized').code(401);
        }
        // Perform sensitive action
        return { status: 'ok' };
      },
      state: {
        apikey: {
          ttl: 24 * 60 * 60 * 1000,
          isSecure: true,
          isHttpOnly: true,
          sameSite: 'strict'
        }
      }
    }
  });

  await server.start();
  console.log('Server running on %s', server.info.uri);
};

init();

function isValidKey(key) {
  // Constant-time comparison against stored key(s)
  return key === process.env.API_KEY;
}

The second example demonstrates how to explicitly set CSP frame-ancestors and X-Frame-Options headers for routes that serve HTML or are at risk of being embedded. This ensures browsers enforce framing policies, mitigating clickjacking regardless of API key presence.

// Enforce framing and CSP in Hapi routes
server.route({
  method: 'GET',
  path: '/profile',
  options: {
    handler: (request, h) => {
      return h.view('profile', { user: request.auth.credentials });
    },
    security: {
      hsts: {
        maxAge: 31536000
      },
      frameguard: {
        action: 'deny'
      },
      csp: {
        directives: {
          ...CSP_DEFAULT_DIRECTIVES,
          'frame-ancestors': ["'none'"]
        }
      }
    }
  }
});

These examples highlight that API keys must be handled with the same care as session cookies: never expose them in URLs, always mark cookies as Secure and HttpOnly, and enforce strict framing policies on any UI that shares routes with key-authenticated operations. Combining these measures reduces the attack surface for clickjacking against API key-protected Hapi services.

Frequently Asked Questions

Does using API keys instead of sessions eliminate clickjacking risk in Hapi?
No. API keys do not prevent clickjacking. If routes that validate API keys also serve HTML or cookies without SameSite and Secure flags, or lack frame-protection headers, attackers can still trick users into making unintended requests. Defense-in-depth with framing headers and secure cookie attributes is required.
Should I embed API keys in HTML or JavaScript to handle clickjacking in Hapi?
No. Embedding API keys in HTML or JavaScript exposes them to theft and increases risk. Keep API keys in HttpOnly, Secure, SameSite cookies or environment variables, and use anti-clickjacking headers (X-Frame-Options, CSP frame-ancestors) to protect UI routes.