Can't find JWS signature for signed proxy redirect

Sorry if this is a bit of a noob question, but I have been scouring the forum for most of the day without being able to find any clear answer. I have set up a signed proxy redirect rule that calls a Netlify function on my app running at indigologic-dev.netlify.app (I’m currently working in deploy preview 28). My netlify.toml file looks like:

[[redirects]]
  from = "/api/contactMail"
  to = "/.netlify/functions/sendEmail"
  status = 200
  force = true
  signed = "API_SIGNATURE_TOKEN"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

When I review the header from the function, I can’t see an X-Nf-Sign element or any other element that appears to hold the jws. I also don’t see any cookies being passed. Here is a printout from my function log of the headers for a recent attempt (obtained via console.log(event)).

headers: {
    accept: '*/*',
    'accept-encoding': 'br, gzip',
    'accept-language': 'en-US,en;q=0.9',
    'client-ip': '100.64.0.54',
    connection: 'keep-alive',
    'content-length': '0',
    'content-type': 'application/json',
    forwarded: 'for=136.37.205.119;proto=https',
    host: 'deploy-preview-28--indigologic-dev.netlify.app',
    origin: 'https://deploy-preview-28--indigologic-dev.netlify.app',
    referer: 'https://deploy-preview-28--indigologic-dev.netlify.app/contact',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'sec-gpc': '1',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36',
    via: 'http/1.1 Netlify[7e3845c9-c361-4dbe-9c49-0354a6899c96] (Netlify Edge Server)',
    'x-bb-ab': '0.274655',
    'x-bb-client-request-uuid': 'f605a57a-2a0b-4cd4-9ee9-c8cad30b36a9',
    'x-bb-ip': '136.37.205.119',
    'x-bb-loop': '1',
    'x-cdn-domain': 'www.bitballoon.com',
    'x-country': 'US',
    'x-datadog-parent-id': '8358442185749973012',
    'x-datadog-trace-id': '13591957236999180729',
    'x-forwarded-for': '136.37.205.119, 100.64.0.54',
    'x-forwarded-proto': 'https',
    'x-language': 'en,en;q=0.9',
    'x-nf-cache-gen': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Cg.eyJnZW4iOiI2MGJlNjk5MDk0MTEyZjAwMDc3YWY1YWE6MTYyMzA5MTY0NTgxNiJ9Cg.KRCmUhDK7Iu8eDfE2-ILXcMQiI_4HUeFzxkHxzk6JOw',
    'x-nf-client-connection-ip': '136.37.205.119',
    'x-nf-connection-proto': 'https',
    'x-nf-request-id': 'f605a57a-2a0b-4cd4-9ee9-c8cad30b36a9'

I’m calling the api from a button in the front-end of my application and the redirect is happening as it should, but I can’t identify where to obtain the jws in order to verify it. Can you help?

TIA!

1 Like

Hey there, @IndigoLogic :wave:

Thanks for reaching out, and welcome to the Netlify Forums. This is a great question :slight_smile:

In terms of finding your JWS signature, if you open your dev tools on your netlify site for the proxied site, /api/contactMail , you should be able to see it under the response headers.

Right now, you most likely aren’t seeing this because you are proxying internally. Since you are proxying from Netlify to Netlify, this information would not be needed. You can check out this doc for more information on signed proxy redirects.

Let me know if this helps!

Thank you @hillary! I really appreciate the help!

The only x-nf value I’m seeing in the response header in my dev tools is ‘x-nf-request-Id’

That aside, the reason I’m doing an internal proxy is to add a jws signature to protect my endpoint from being available outside my own site, as explained in this post. My plan was to verify the jws in my function and return an unauthorized response if the signature could not be validated using the secret in the environment variable. Here’s the sample code from my handler:


    const jwsValue = event.headers['X-Nf-Sign'];

    if (!jwsValue) {
      return {
        statusCode: 401,
        body: 'Unauthorized',
      };
    }

    const secret = process.env.API_SIGNATURE_TOKEN;

    const verified = jws.verify(jwsValue, 'HS256', secret);

    console.log('verified ', verified);

    if (!verified)
      return {
        statusCode: 401,
        body: 'Unauthorized - Invalid Signature',
      };

Am I missing somewhere other than the “context” and “event” variables passed to the Netlify function that I can view the header? Any other suggestions? Thanks again!

Hey @IndigoLogic , I’ve run into the same situation and wondering if you found a solution/workaround? @hillary is it possible to sign redirects using netlify when they’re internal? The doc you linked doesn’t give much information on this.

Hi @ph-git! Unfortunately, not yet, but I’ll be sure to post something here if I do. Would appreciate if you would do the same. :grin:

1 Like

Hi all,
My colleague and I dug into this and here’s what we found: the x-nf-sign header only appears when you proxy externally. You can check this out by getting a free account with https://requestbin.com/ and setting your proxy “to” destination in your netlify.toml to the endpoint you get from requestbin. When you hit the endpoint, you’ll see the x-nf-sign header in the response. Here’s mine:

From there, you (or your code) can decode the JWT to ensure that it’s properly signed. https://jwt.io/ says this token payload decodes to roughly:

{
  "deploy_context": "production",
  "exp": 1623876755,
  "iss": "netlify",
  "netlify_id": "1b2665fe-2d11-4b1f-b6e1-6e8b3a07aaaa",
  "site_url": "https://mysitename.com"
}

Presumably, the reason we don’t sign internally proxied requests is because… we already know the requests come from Netlify- that’s how they got the header in the first place- so it would be a bit redundant. But we could definitely add a note about this in our docs!

This gets to another issue. You said:

I’m doing an internal proxy is to add a jws signature to protect my endpoint from being available outside my own site

This setup wouldn’t ensure that, even if we supported internally proxied signed requests. Anyone could use curl to make requests to yoursite.com/api/contactMail, and those requests would ultimately hit your function with the correct x-nf-sign header.

I think what you’re looking for is a way to secure your function endpoints. The only way I know of to do that is with our role-based access + Netlify Identity- which lets you gate access to certain entire pages where those function endpoints are called from.

I know that was a lot! Please let us know if you have any followup questions!

1 Like