Search code examples
whatsapp-cloud-api

Whatsapp Embed SignupFlow You must provide an app access token, or a user access token that is an owner or developer of the app


I'm using the newest embed SignupFlow for Whatsapp cloud API.

since I'm its returning this message:

{"error":{"message":"(#100) You must provide an app access token, or a user access token that is an owner or developer of the app","type":"OAuthException","code":100,"fbtrace_id":"A8zmgXoQ4iVYPBqOu36aTHL"}}

I cant continue the integration to Fetch shared WABA IDs.

I created this configuration id and I'm the developer of the app too.

<script>

  var apiVersion = "v19.0";

  function debugToken(inputToken){
    const url = new URL(`https://graph.facebook.com/${apiVersion}/debug_token`);
    url.searchParams.set('input_token', inputToken);

    console.log('url');
    console.log(url);

    fetch(url)
    .then(function(response) {
      return response.json();
    })
    .then(function(myJson) {
      console.log(JSON.stringify(myJson));
    });

  }

</script>

<script>
  window.fbAsyncInit = function() {
    FB.init({
      appId            : '490956132922840',
      autoLogAppEvents : true,
      xfbml            : true,
      version          : apiVersion
    });
  };
</script>
<script async defer crossorigin="anonymous"
  src="https://connect.facebook.net/en_US/sdk.js">
</script>

<script>
  // Facebook Login with JavaScript SDK
  function launchWhatsAppSignup() {
    // Launch Facebook login
    FB.login(function (response) {

      console.log('response');
      console.log(response);

      if (response.authResponse) {
        const accessToken = response.authResponse.code;

        debugToken(accessToken);

        //Use this token to call the debug_token API and get the shared WABA's ID
      } else {
        console.log('User cancelled login or did not fully authorize.');
      }
    }, {
      config_id: '944207277310917', // configuration ID obtained in the previous step goes here
      response_type: 'code',     // must be set to 'code' for System User access token
      override_default_response_type: true,
      extras: {
        sessionInfoVersion: 2,  //  Receive Session Logging Info
      }
    });
  }
</script>

<button onclick="launchWhatsAppSignup()"
  style="background-color: #1877f2; border: 0; border-radius: 4px; color: #fff; cursor: pointer; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-weight: bold; height: 40px; padding: 0 24px;">
  Login with Facebook
</button>

Solution

  • Trying to figure out those APIs myself so this might not be a complete answer but at least some extra information.

    You can use response.authResponse.code in https://graph.facebook.com/{api_version}/oauth/access_token?client_id={app_id}&client_secret={app_secret}&code={code} (no auth header needed) to get access_token. That token has type=SYSTEM_USER and when calling /debug_token you can specify it as input_token but you'd still need the USER-type token for the Authorization header, not sure how to get around this. But you could use that token for other APIs (e.g. that token works as a Bearer token for /{api_version}/{waba_id}/phone_numbers)

    If you need to get the WABA ID selected by the user, you could add an event listener for a message event, as described in Facebook docs (this works only if you have "sessionInfoVersion": 2 in extras):

    const sessionInfoListener = (event) => {
      if (event.origin !== "https://www.facebook.com" && event.origin !== "https://web.facebook.com") {
        return;
      }
      
      try {
        const data = JSON.parse(event.data);
        if (data.type === 'WA_EMBEDDED_SIGNUP') {
          // if user finishes the Embedded Signup flow
          if (data.event === 'FINISH') {
            const {phone_number_id, waba_id} = data.data;
          }
          // if user cancels the Embedded Signup flow
          else {
           const{current_step} = data.data;
          }
        }
      } catch {
        // Don’t parse info that’s not a JSON
        console.log('Non JSON Response', event.data);
      }
    };
    
    window.addEventListener('message', sessionInfoListener);