Update query from the Backend or other viable solutions

I am looking to implement a Zoho ticketing dashboard within Grafana, and I have a few questions regarding the integration.

  1. Integration with Zoho API:

I need to utilize Zoho API calls that require a code, client ID, and client secret to generate an access token and refresh token. The access token expires every 60 minutes, requiring the need for a middleware to refresh it when any of the APIs returns a 401 error.

Additionally, the integration needs to run through Grafana’s backend plugin, as the endpoint will throw a CORS error from the frontend due to Grafana having a separate OAuth for frontend applications, which does not meet the use case.

  1. Storage of Tokens:
    My challenge lies in determining where to store the access token and refresh token securely. Initially, I considered saving them by creating two read-only inputs in the Query editor and exposing an endpoint through CallResource to retrieve the access token for the first time and save it directly as a query.

However, I am not sure how to update the access token once it has been refreshed. What is the best approach to achieve this functionality?


  1. Example cURLs:

Here are the example cURL requests for obtaining and refreshing the tokens. I have obfuscated the sensitive data for security purposes:

Create Token

curl --location --request POST 'https://accounts.zoho.com.au/oauth/v2/token?code=<code>&grant_type=authorization_code&client_id=<client_id>&client_secret=<client_secret>&scope=Desk.tickets.READ'

Refresh Token

curl --location --request POST 'https://accounts.zoho.com.au/oauth/v2/token?grant_type=refresh_token&client_id=<client_id>&client_secret=<client_secret>&refresh_token=<refresh_token>'

Could you please guide the best practices for implementing this within Grafana’s backend?

Also while calling the CallResource method from the ConfigEditor using getBackendSrv().fetch, I noticed it’s calling the CheckHealth method as well. Is there a way to prevent this? Cause I wanted the check health to be called after generating the tokens.

welcome to forum @riteshakya037

are you trying to develop your own custom plugin? or use an existing one?

Hi @yosiasz thanks for the prompt response. I’m building my own datasource with a backe d plugin enabled.

1 Like

How do you generate that <code> value?
I bet this will be your first problem. It looks like you are using Authorization Code Grant, which is not a best fit for this kind of (machine 2 machine) authentification.
I would focus on that auth flow first, otherwise you may spend a time on the implementation, which won’t be good enough.

1 Like

I understand your concern, but for our specific use case, the Authorization Code Grant works well. We’re aiming for a simple setup where an admin enters the code once to generate access and refresh tokens, use refresh token to create a new access token once the old one expires, allowing us to display live ticket counts on a large screen in the office.

One more thing I noticed is that the Promise is getting canceled even though the backend already responded with a 200. Below I’ve attached the code for calling the token API through backendSrv.

    const observable = getBackendSrv()
        url: `/api/datasources/${props.options.id}/resources/token`,
    const response = await observable.toPromose();

    console.log(response, JSON.stringify(response));


3/:1 Uncaught (in promise) {type: 'cancelled', cancelled: true, data: null, status: -1, statusText: 'Request was aborted', …}

Sucess in Network Tab:

P.S. I’m using version 7.5.17 of grafana.