node.jsexpressaxiospaypalhttp-status-code-401

How to Resolve a 401 Unauthorized Error with PayPal Webhooks Using Axios in Node.js?


I am integrating PayPal Webhooks into my Node.js application using Axios, but I encounter a 401 Unauthorized error when triggering the webhook. Below is the error I receive:

Error data: {
  name: 'UNAUTHORIZED',
  message: 'Authorization failed due to insufficient permissions.',
  debug_id: 'b02145e0fae22',
  details: [
    {
      issue: 'PERMISSION_DENIED',
      description: 'You do not have permission to access or perform operations on this resource.'
    }
  ]
}
Error status: 401
Error headers: Object [AxiosHeaders] {
  // headers omitted for brevity
}

Here's a simplified version of my server-side code handling the webhook event. This snippet focuses on verifying the webhook signature and handling the event.

require('dotenv').config();
const express = require('express');
const axios = require('axios');

const paypalRouter = express.Router();

paypalRouter.post("/subscriptions/webhook", async (req, res) => {
  console.log("Received headers:", req.headers);
  const verification = {
    auth_algo: req.headers['paypal-auth-algo'], 
    cert_url: req.headers['paypal-cert-url'], 
    transmission_id: req.headers['paypal-transmission-id'],
    transmission_sig: req.headers['paypal-transmission-sig'],
    transmission_time: req.headers['paypal-transmission-time'], 
    webhook_id: process.env.WEBHOOK_ID,
    webhook_event: req.body,
  };

  const params = new URLSearchParams();
  params.append("grant_type", "client_credentials");
  const authResponse = await axios.post("https://api-m.sandbox.paypal.com/v1/oauth2/token", params, {
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    auth: {
      username: process.env.PAYPAL_CLIENT_ID,
      password: process.env.PAYPAL_SECRET,
    },
  });

  const access_token = authResponse.data.access_token;
  const verifyResponse = await axios.post("https://api-m.sandbox.paypal.com/v1/notifications/verify-webhook-signature", verification, {
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${access_token}`
    },
  });

  if (verifyResponse.data.verification_status === "SUCCESS") {
    console.log("Webhook verified");
    // more code 
 } else {
    console.error("Webhook verification failed:", verifyResponse.data);
    return res.status(401).send('Webhook signature verification failed');
  }
});

module.exports = paypalRouter;

What I need help with:

  1. Understanding why the 401 error occurs despite seemingly correct authentication and permission settings.

  2. How to ensure that my webhook verification step with PayPal is correctly implemented.

I've already tried reviewing PayPal's official documentation and ensured that all permissions and API credentials are correctly configured. The error persists, and I'm unsure how to debug this further.


Solution

  • This commonly happens when you are missing one HEADERS. To resolve this you need to hit the same endpoint from POSTMAN and pass all the HEADERS on your NODE code.