node.jsfirebasefirebase-dynamic-linksrequest-promise

Firebase Cloud Functions: Requests from referer <empty> are blocked. - PERMISSION_DENIED


I am not sure why the following code is throwing google api key permission denied. I have the api or service enabled both in firebase console and google console.

export async function createJobDynamicLink(job){
    if(job.jobStatus !== 'approved' ||  (job.dynamicLink).length > 2){
        console.log('Dynamic link already exist!');
        return false;
    }

    console.log(dynamic_links);
    console.log(dynamic_links_key);
    // Firebase web api key logs just fine
    const options = {
        method: 'POST',
        uri: `https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=${dynamic_links_key}`,
        body: {
            "longDynamicLink": makeDynamicLongLink(job)
        },
        json: true
    };

    return await requestpromise(options)
        .then(function (parsedBody) {
            console.log(parsedBody);
            return parsedBody.shortLink;
        })
        .then((shortLink) => {
            //post.shareUrl = shortLink;
            console.log('short link: ' + shortLink);
            //return event.data.ref.set(post);
            return shortLink;
        })
}
export async function makeDynamicLongLink(job) {
    return buildUrl(`${dynamic_links}`, {
        queryParams: {
            link: `https://app.com/jobs/${slugify(job.jobTitle)}-${job.id}`,
            apn: "com.app.appe",
            ibi: "com.app.app",
            dfl: "https://app.com",
            st: job.jobTitle,
        }
    });
}

Is something wrong with the way I am doing the request using request-promise?

StatusCodeError: 403 - {
  "error": {
    "code": 403,
    "message": "Requests from referer <empty> are blocked.",
    "status": "PERMISSION_DENIED",
    "details": [{
      "@type": "type.googleapis.com/google.rpc.Help",
      "links": [{
        "description":"Google developer console API key",
        "url": "https://console.developers.google.com/project/904573jjwj/apiui/credential"
      }]
    }]
  }
}

Solution

  • Because you are invoking your function from a node.js environment, the HTTP Header Referer isn't being set. When you create requests through a browser, the browser will automatically fill this field for you.

    You can get a suitable referrer value using:

    "https://" + process.env.GCLOUD_PROJECT + ".cloudfunctions.net/createJobDynamicLink"
    // becomes "https://your-project-id.cloudfunctions.net/createJobDynamicLink"
    

    This generated URL isn't callable, because it doesn't start with a region, but it means you now have a URL that can be used to identify that the call is coming from a Cloud Function.

    To use it, add it to your request-promise options object.

    const options = {
            method: 'POST',
            uri: `https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=${dynamic_links_key}`,
            body: {
                "longDynamicLink": makeDynamicLongLink(job)
            },
            headers: {
                "Referer": "https://" + process.env.GCLOUD_PROJECT + ".cloudfunctions.net/createJobDynamicLink"
            },
            json: true
        };
    

    Note: I'd use request-promise-native instead of request-promise - same API but skips loading Bluebird.