Webhook extend with ability to receive time-limited access token before POST (Google API, spreadsheets) #3809

Open
opened 2026-02-28 03:41:35 -05:00 by deekerman · 1 comment
Owner

Originally created by @ww7 on GitHub (Dec 4, 2024).

Not found related issues.

🏷️ Feature Request Type

New notification-provider, Change to existing notification-provider

🔖 Feature description

I need to keep notifications on Google Spreadsheet.

It can be done via HTTP POST (Webhook). But require a time-limited token (to use as a variable at webhook).

✔️ Solution

Use Google Scripts middleware (see second comment).

Alternatives

Google API OAuth2 working with limited by 60 minutes ACCESS_TOKEN that can be received with e.g. curl:

curl --request POST \
  --data "client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&grant_type=refresh_token&refresh_token=$REFRESH_TOKEN" \
  https://oauth2.googleapis.com/token

I obtained CLIENT_ID and CLIENT_SECRET at Google Console Spreadsheet API and REFRESH_TOKEN exchanged at OAuth 2.0 Playground (select Spreadsheets v3 for "Authorize APIs" button.)
CleanShot 2024-12-05 at 00 50 26@2x

With such POST a new line will be added to the spreadsheet by curl:

curl --request POST \
  "https://sheets.googleapis.com/v4/spreadsheets/$SPREADSHEET_ID/values/$SHEET_NAME\!A1:append?valueInputOption=USER_ENTERED" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "values": [
      ["column 1", "column 2", "column 3"]
    ]
  }'
Originally created by @ww7 on GitHub (Dec 4, 2024). ### 📑 I have found these related issues/pull requests Not found related issues. ### 🏷️ Feature Request Type New notification-provider, Change to existing notification-provider ### 🔖 Feature description I need to keep notifications on Google Spreadsheet. It can be done via HTTP POST (Webhook). But require a time-limited token (to use as a variable at webhook). ### ✔️ Solution Use Google Scripts middleware (see second comment). ### ❓ Alternatives Google API OAuth2 working with limited by 60 minutes `ACCESS_TOKEN` that can be received with e.g. `curl`: ```sh curl --request POST \ --data "client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&grant_type=refresh_token&refresh_token=$REFRESH_TOKEN" \ https://oauth2.googleapis.com/token ``` I obtained `CLIENT_ID` and `CLIENT_SECRET` at Google Console Spreadsheet API and `REFRESH_TOKEN` exchanged at [OAuth 2.0 Playground](https://developers.google.com/oauthplayground/) (select `Spreadsheets v3` for "Authorize APIs" button.) ![CleanShot 2024-12-05 at 00 50 26@2x](https://github.com/user-attachments/assets/c3e0fc39-f665-44e4-9cc6-c19987d5c32b) With such POST a new line will be added to the spreadsheet by `curl`: ``` curl --request POST \ "https://sheets.googleapis.com/v4/spreadsheets/$SPREADSHEET_ID/values/$SHEET_NAME\!A1:append?valueInputOption=USER_ENTERED" \ --header "Authorization: Bearer $ACCESS_TOKEN" \ --header 'Content-Type: application/json' \ --data '{ "values": [ ["column 1", "column 2", "column 3"] ] }' ```
Author
Owner

@ww7 commented on GitHub (Dec 4, 2024):

If request difficult to achieve with Kuma, it can be solved with Google Scripts as middleware.

function doPost(e) {
  try {
    Logger.log('doPost function called');
    
    if (!e.postData || !e.postData.contents) {
      throw new Error('No POST data received');
    }
    
    Logger.log('POST data received: ' + e.postData.contents);
    
    var params = JSON.parse(e.postData.contents);
    
    var secret = params.secret;
    if (secret !== '<secret>') {
      throw new Error('Unauthorized: Invalid secret key');
    }
    delete params.secret;
    
    var status = params.status || 'No Status';
    var message = params.message || 'No Message';
    
    Logger.log('Status: ' + status + ', Message: ' + message);
    
    var spreadsheet = SpreadsheetApp.openById('<table_id>');
    //var spreadsheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/<or_such _ink>/edit');

    var sheet = spreadsheet.getSheets()[0];
    
    // example, not adjusted for message from Kuma 
    sheet.appendRow([
      new Date(),
      status,
      message
    ]);
    
    Logger.log('Data appended to sheet');
    
    var response = { result: 'success' };
    Logger.log('Returning response: ' + JSON.stringify(response));
    
    return ContentService.createTextOutput(JSON.stringify(response))
      .setMimeType(ContentService.MimeType.JSON);
    
  } catch (error) {
    Logger.log('Error occurred: ' + error.toString());
    
    var response = { result: 'error', error: error.toString() };
    Logger.log('Returning error response: ' + JSON.stringify(response));
    
    return ContentService.createTextOutput(JSON.stringify(response))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

// Example for test from Script editor
// function testDoPost() {
//   var e = {
//     postData: {
//       contents: JSON.stringify({
//         status: 'Test Status',
//         message: 'Test Message',
//         secret: '<secret>'
//       }),
//       type: 'application/json'
//     }
//   };

//   var result = doPost(e);
//   Logger.log(result.getContent());
// }

Publish on every save and use resulted link with Webhook notification at Kuma with Custom Body as

{
"secret": "<secret>",
"status": "Online",
"message": "Kuma testing"
}

One thing what I didn't get, with curl test it not returning JSON to terminal.

@ww7 commented on GitHub (Dec 4, 2024): If request difficult to achieve with Kuma, it can be solved with [Google Scripts](https://script.google.com/) as middleware. ```js function doPost(e) { try { Logger.log('doPost function called'); if (!e.postData || !e.postData.contents) { throw new Error('No POST data received'); } Logger.log('POST data received: ' + e.postData.contents); var params = JSON.parse(e.postData.contents); var secret = params.secret; if (secret !== '<secret>') { throw new Error('Unauthorized: Invalid secret key'); } delete params.secret; var status = params.status || 'No Status'; var message = params.message || 'No Message'; Logger.log('Status: ' + status + ', Message: ' + message); var spreadsheet = SpreadsheetApp.openById('<table_id>'); //var spreadsheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/<or_such _ink>/edit'); var sheet = spreadsheet.getSheets()[0]; // example, not adjusted for message from Kuma sheet.appendRow([ new Date(), status, message ]); Logger.log('Data appended to sheet'); var response = { result: 'success' }; Logger.log('Returning response: ' + JSON.stringify(response)); return ContentService.createTextOutput(JSON.stringify(response)) .setMimeType(ContentService.MimeType.JSON); } catch (error) { Logger.log('Error occurred: ' + error.toString()); var response = { result: 'error', error: error.toString() }; Logger.log('Returning error response: ' + JSON.stringify(response)); return ContentService.createTextOutput(JSON.stringify(response)) .setMimeType(ContentService.MimeType.JSON); } } // Example for test from Script editor // function testDoPost() { // var e = { // postData: { // contents: JSON.stringify({ // status: 'Test Status', // message: 'Test Message', // secret: '<secret>' // }), // type: 'application/json' // } // }; // var result = doPost(e); // Logger.log(result.getContent()); // } ``` Publish on every save and use resulted link with Webhook notification at Kuma with Custom Body as ``` { "secret": "<secret>", "status": "Online", "message": "Kuma testing" } ``` One thing what I didn't get, with `curl` test it not returning JSON to terminal.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/uptime-kuma#3809
No description provided.