HIGH clickjackingphoenixbearer tokens

Clickjacking in Phoenix with Bearer Tokens

Clickjacking in Phoenix with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Clickjacking is a client-side attack that tricks a user into interacting with a hidden or disguised UI element, often by nesting the target site inside an invisible iframe. When a Phoenix application uses Bearer Tokens for authentication—typically sent in the Authorization header—clickjacking can expose privileged actions even when the token itself is not leaked via the DOM. The risk arises because the token is stored in browser memory or in secure HTTP-only cookies and is automatically included by the browser in requests initiated from within the embedded page, provided same-site and cross-origin cookie policies allow it.

In Phoenix, if an endpoint performs sensitive operations (for example, changing an email, upgrading a subscription, or deleting a resource) based solely on the presence of a valid Bearer Token and does not enforce additional UI-level protections, an attacker can craft a page that embeds your Phoenix endpoint in an iframe. The attacker then overlays invisible controls or mimics a legitimate UI on top of the iframe, causing the victim to inadvertently trigger state-changing requests. Because the browser includes the Bearer Token automatically, the forged interaction is executed in the context of the victim’s authenticated session.

This combination is particularly dangerous when:

  • The Phoenix app sets session cookies with SameSite=None; Secure to support cross-origin requests (e.g., for embedded widgets) without also enforcing anti-CSRF measures at the UI layer.
  • Endpoints rely only on the Authorization header Bearer Token and lack frame-busting headers or X-Frame-Options protections.
  • The UI contains interactive elements that can be triggered via GET requests or predictable POST payloads, enabling automated click sequences via CSS or JavaScript within the iframe.

For example, consider a Phoenix endpoint that accepts a POST to /api/v1/users/email with a JSON body and an Authorization Bearer Token. An attacker can host a page with an invisible iframe pointing to that endpoint and overlay a button styled to look harmless. When clicked, the user unknowingly changes their email address, and the request carries the victim’s token automatically. The attack does not require token exfiltration; it exploits the trust placed in the browser’s automatic credential handling and the absence of frame isolation.

Because middleBrick scans the unauthenticated attack surface, it can detect missing anti-clickjacking headers and misconfigured frame policies during a standard scan. This helps teams identify exposed endpoints where Bearer Token authentication is not complemented by UI-level defenses.

Bearer Tokens-Specific Remediation in Phoenix — concrete code fixes

Remediation focuses on layering defenses so that even if a request originates from an embedded context, it does not result in unintended actions. The key is to avoid relying solely on the Bearer Token’s presence and to enforce explicit UI-origin checks and strict same-site cookie policies.

1. Set SameSite and Secure Cookie Attributes

Ensure session and authentication cookies use SameSite=Lax or SameSite=Strict and Secure. For APIs using Bearer Tokens in Authorization headers, this prevents cookies from being sent in cross-site requests, reducing the impact of clickjacking when tokens are tied to cookies.

# In config/runtime.ex or a similar configuration module
defmodule MyAppWeb.Endpoint do
  plug Plug.Session,
    store: :cookie,
    key: "_myapp_key",
    signing_salt: "signing_salt_here",
    same_site: "Lax",
    secure: true
end

2. Explicit Frame-Busting and X-Frame-Options

Add headers to prevent the application from being embedded in iframes. In Phoenix, you can use a plug to set X-Frame-Options and inject a frame-ancestors CSP directive.

# In a plug pipeline or router
pipeline :browser do
  plug Plug.Parsers, parsers: [:urlencoded, :multipart, :json]
  plug Phoenix.Controller.set_session, secure: true
  plug :set_frame_options
end

defp set_frame_options(conn, _opts) do
  put_resp_header(conn, "x-frame-options", "DENY")
  |> put_resp_header("content-security-policy", "frame-ancestors 'self'")
end

3. Require Anti-CSRF Tokens for State-Changing Requests

Even when using Bearer Tokens in the Authorization header, treat sensitive POST, PUT, PATCH, and DELETE requests as state-changing and enforce origin validation. Phoenix does not enable CSRF protection by default for API pipelines, so add explicit checks for custom headers or Origin validation.

# In a controller that handles sensitive actions
defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  action_fallback MyAppWeb.FallbackController

  plug :validate_csrf_header when action in [:update_email, :delete_account]

  def update_email(conn, %{"email" => email}) do
    # business logic
  end

  defp validate_csrf_header(conn, _) do
    case get_req_header(conn, "x-csrf-token") do
      [token] when token == get_session(conn, :csrf_token) -> conn
      _ -> Plug.Conn.send_resp(conn, 403, "Invalid request origin") |> halt()
    end
  end
end

4. Validate Referer and Origin Headers

For endpoints that accept Bearer Tokens via Authorization headers, validate the Referer or Origin header to ensure requests originate from your own frontend. This is not a standalone defense due to header spoofing in some environments, but it adds a layer when combined with SameSite cookies and CSRF tokens.

plug :validate_request_origin when action in [:create, :update, :delete]

defp validate_request_origin(conn, _) do
  allowed_origin = "https://app.mycompany.com"
  case get_req_header(conn, "origin") do
    [origin] when origin == allowed_origin -> conn
    [referer] when referer == allowed_origin -> conn
    _ -> Plug.Conn.send_resp(conn, 403, "Forbidden") |> halt()
  end
end

5. Use POST with Request Body Validation and Avoid GET for Sensitive Actions

Design endpoints so that sensitive operations require a POST with a JSON body and do not rely on query parameters. Combine this with strict parameter validation to ensure that forged GET requests cannot trigger state changes.

# In router.ex
post "/api/v1/users/email", UserController, :update_email, :api

# In controller
plug validate_json_body when action == :update_email

defp validate_json_body(conn, _) do
  case conn.body_params do
    %{"email" => email} when is_binary(email) and email =~ ~r/@/ -> conn
    _ -> Plug.Conn.send_resp(conn, 400, "Missing or invalid email") |> halt()
  end
end

By combining these measures—SameSite cookies, frame denial headers, CSRF-like origin checks, and strict parameter validation—you reduce the risk that Bearer Token–protected Phoenix endpoints can be abused via clickjacking, even when the application is embedded in hostile contexts.

Frequently Asked Questions

Can clickjacking leak my Bearer Token?
Clickjacking does not directly leak the Bearer Token string, but it can trick the browser into making authenticated requests using the token stored in headers or cookies. The token itself stays in the browser’s credential store; the risk is unauthorized actions, not token exfiltration.
Does middleBrick fix clickjacking issues?
middleBrick detects missing anti-clickjacking headers and exposes misconfigured frame policies in its findings, providing remediation guidance. It does not apply fixes automatically; developers must implement the recommended header and CSP changes.