GraphQL problem - The JWT string must have two dots

Hello,

I’m trying to use GraphQL. I installed the API module, set the correct permission (chmod 600 /etc/asterisk/keys/api_oauth_public.key).

Both my application, as well as the GraphQL Explorer always return the same responds.

{
  "error": "access_denied",
  "message": "The resource owner or authorization server denied the request.",
  "hint": "The JWT string must have two dots"
}

I use this query (documented here: GraphQL support in FreePBX 15 | FreePBX - Let Freedom Ring):

query {
  allModules {
    modules {
      name
      version
    }
  }
}

But also the other queries from the documentation page [1] all give the same error.

https://sangomakb.atlassian.net/wiki/spaces/PG/pages/25755702/GraphQL+PBX+APIs+Documentation

What am I doing wrong? I tested on both FreePBX 15 and 16.

Oke I got it to work for a simple external python script. For anyone that finds this post here’s how I fixed it.

First make a " Machine-to-Machine app" I copy the info from that page.

Then change some permissions:

sudo chmod 600 /etc/asterisk/keys/api_oauth.key

And here is a simple python script:

#!/usr/bin/env python3

import requests

# Replace these variables with your FreePBX server details and credentials
FREEPBX_URL = 'http://yourdomain.com:83/admin/api/api/gql'
TOKEN_URL = 'http://yourdomain.com:83/admin/api/api/token'
CLIENT_ID = '1f18302e0a241effasdasdasdasdasdasdasdasdasd38fbd96a9749'
CLIENT_SECRET = '5810fc91f15asdasdasdasdasdasbc8295'

def get_access_token():
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
    }
    
    data = {
        'grant_type': 'client_credentials',
        'client_id': CLIENT_ID,
        'client_secret': CLIENT_SECRET,
    }
    
    response = requests.post(TOKEN_URL, headers=headers, data=data)
    
    if response.status_code == 200:
        result = response.json()
        return result['access_token']
    else:
        print(f"Failed to obtain access token: {response.status_code}")
        print(response.text)
        return None

def get_extensions_status(access_token):
    query = """
    {
        fetchAllExtensions {
            status
            message
            totalCount
            extension {
                extensionId
                user {
                    name
                    outboundCid
                }
            }
        }
    }
    """

    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {access_token}',
    }

    response = requests.post(FREEPBX_URL, json={'query': query}, headers=headers)

    if response.status_code == 200:
        result = response.json()
        return result['data']['fetchAllExtensions']
    else:
        print(f"Failed to query GraphQL API: {response.status_code}")
        print(response.text)
        return None

if __name__ == "__main__":
    access_token = get_access_token()
    if access_token:
        extensions_status = get_extensions_status(access_token)
        if extensions_status:
            print(f"Status: {extensions_status['status']}")
            print(f"Message: {extensions_status['message']}")
            print(f"Total Count: {extensions_status['totalCount']}")
            for ext in extensions_status['extension']:
                print(f"Extension Number: {ext['extensionId']}")
                if ext['user']:
                    print(f"User Name: {ext['user']['name']}")
                    print(f"Outbound CID: {ext['user']['outboundCid']}")
                print("-----")
        else:
            print("Failed to retrieve extensions status.")
    else:
        print("Failed to obtain access token.")