Google API usage with OAuth2

I’m not sure how the API expects it, but have you tried just adding the metadataHeaders multiple times.

format: metadata
metadataHeaders: Message-ID
metadataHeaders: from

Sometimes the brackets are also needed.

format: metadata
metadataHeaders[]: Message-ID
metadataHeaders[]: from

Yes, I tried that too and it throws an error unfortunately. The sample I found from stack overflow of a working version was

message2 =gmail_service.users().messages().get(userId='me', id=thread['id'], format='metadata', metadataHeaders=['subject','from','to','date']).execute()
for num in range(0,4):
  if message2['payload']['headers'][num]['name'].lower() == "subject":
    subject=message2['payload']['headers'][num]['value']
  elif  message2['payload']['headers'][num]['name'].lower() == "from": 
    From=message2['payload']['headers'][num]['value']
  elif  message2['payload']['headers'][num]['name'].lower() == "to": 
    to=message2['payload']['headers'][num]['value']
  elif  message2['payload']['headers'][num]['name'].lower() == "date": 
    date=message2['payload']['headers'][num]['value']

f.write("Date : %s "  % date.encode('utf8')+'\n')
f.write("Subject : %s "  % subject.encode('utf8')+'\n')
f.write("From : %s "  % From.encode('utf8')+'\n')
f.write("To : %s "  % to.encode('utf8')+'\n')

Obviously that persons code does more than just that, but in line 1 you can see how he sent the headers to the API.
I have also tried adding a setValue step as an Array and then passing that into the value, but no luck sadly.

The querystring should become format=metadata&metadataHeaders=Message-ID&metadataHeaders=from, so having multiple metadataHeaders.

Seems that the api action doesn’t support having multiple query parameters with the same name. You could try:

format: metadata
metadataHeaders[0]: Message-ID
metadataHeaders[1]: from

Maybe google supports that format.

Unfortunately, Google doesn’t understand that, it looks like whenever they do not understand something like that they just give the full results instead, although with some of my attempts I have actually got them to produce an error.

Even though it did not work, I have to congratulate you for coming up with the one way I actually never tried though, when I asked the original question I honestly thought I had tried every variation, haha.

alternative you could just put the query directly in the url, that should work

https://www.googleapis.com/gmail/v1/users/userId/messages/id?format=metadata&metadataHeaders=Message-ID&metadataHeaders=from
2 Likes

If I could give that 5 hearts I would, that works like a charm.
I had tried it but not like you did, I tried this originally

https://www.googleapis.com/gmail/v1/users/userId/messages/id?format=metadata&metadataHeaders=["Message-ID","from"]

and this

https://www.googleapis.com/gmail/v1/users/userId/messages/id?format%3Dmetadata%26metadataHeaders%3D%5B%22Message-ID%22%2C%22from%22%5D

I understand a little more of how they expect it now.
THAAAANK YOU

1 Like

I have this app finally working pretty well at the moment, only I am still fighting with being unauthenticated after the access token expires after 1 hour. Is there a preferred way to get the refresh token from the session and send it to Google for them to renew my access token without the user having to interact at all?

Sorry @patrick but i think this will be one of my last little stumbling blocks with this project.

I haven’t set this up using Wappler yet, but I usually create a table to store the access token, refresh token, scope, and expires in date/time. These are provided when the oAuth process returns the user to your app after sign in.

This is from Bubble, but hopefully helps. This workflow runs when Google redirects the user back to the specified redirect URL on my app.

Step 2 grabs the access_token, expires_in, refresh_token, and scope and inserts them into a record in a table.

Step 4 creates a scheduled job to run 120 seconds before the expires date/time to request a new access token. This scheduled job will provide the Refresh token to another workflow.

The workflow it calls, makes a call to https://www.googleapis.com/oauth2/v4/token with the following parameters and will return a new access_token and expires_in for you to store. You then need to setup a new scheduled job to run before the new expires_in time to repeat the process.

https://www.googleapis.com/oauth2/v4/token?refresh_token=[refresh_token]&client_id=[client_id]&client_secret=[client_secret]&grant_type=refresh_token

This is typically how you keep your access token up-to-date for your app to use, and does not require your user to reauthenticate.

Shoutout to @mebeingken for helping me with this process long ago. :wink:

1 Like

Thanks so much, thats very helpful indeed, as far as i know from what Patrick has said the Wappler session already stores and manages to access token, refresh token, etc. so although i could easily save this into my own database, I am kind of hoping that i could access the properties of that already stored cookie or session to send the data needed.
This would cut out the entire step of saving and updating the database, but not too sure if it can work that way.
I think @mebeingken did find a way to access the properties from the Wappler Cookie?

1 Like

Long ago indeed! I’m in the middle of dealing with tens of millions of db records and cringe at the thought of attempting in the bubble. :anguished:

1 Like

Seems like there are generally two use cases here. Doing things on behalf of a user when they are actively engaged online, and doing things for users when they are offline.

Wappler oauth2 action with sessions for the former and Wappler oauth2 action with database for the latter.

If you try and use session when the user is offline, I would think you have no way of knowing which session you want.

2 Likes

Well I think I have finally got the Auth sorted out on my Google App.

I must ask though, what I have quoted above makes it sound like it should have been far simpler than it was, therefore I assume, I have possibly jumped through a few hoops incorrectly.

So I have an OAuth Provider step and an OAuth2 Authorise step and a redirect step all in a single server action, it does a great job here.

The user clicks a button on my home page, it opens a google account chooser page, they click the account they want, it moans about an un authorised app, which is expected, they say ok, they accept the permissions from google and now i land up on my main page where all their data is displayed.

The data is displayed using a series of api calls, each server action that accesses the API starts with the OAuth2 Provider step, without another Authorise step, because if I do use another authorise step then it takes the user back to the Google Account Chooser page.

So far so good. However after exactly 1 hour, regardless of if I am working on the page or not, the account is logged out, as unauthorised.

The way I read what I quoted above, the provider should have automatically handled the refresh for me and therefore even after 1 hour the user should not be logged out and have to go through the authorise step again.

Sorry to harp on and on about this but I just want to make sure I am understanding this all correctly.

If you’re using session storage – and we’re talking about server session storage in php – I believe the default timeout is 24 minutes. You may need to increase the timeout.

https://stackoverflow.com/questions/8311320/how-to-change-the-session-timeout-in-php

No I am talking about the actual timeout of the access token provided by google before needing to use the refresh token to get a new access token
The Google Access Token expires in 3600 seconds, i.e. 1 hour.

My question is that Patrick said
“Our provider automatically does the refresh for you”
Obviously this is when you are not using the OAuth Self Maintain option, but what I have found is that it does not handle the refresh token automatically for me. If I am using the app I have made and checking emails etc. after exactly 1 hour it logs me out and I have to re authenticate. Which is not correct according to what Patrick was saying.

1 Like

Patrick said they are storing the access token and refresh token in a session. If the session is expiring before it’s time for a refresh, then it’s possible your details are being destroyed by the server before it’s time to refresh thent.

I see what you are saying but I did check my session timeouts and those are more than an hour to account for if that were the case.
I have physically used the app for the entire hour, and i watch the clock and as it hits 59 minutes and 59 seconds it unauthenticates and I have to re authenticate, so I am pretty sure it is the access token that is expiring and causing my entire issue.

I have made a way around it so it is working for the moment, but I can not imagine a user would have to go through all the steps I have done to get this working according to the way Patrick explained it.

Since I’m unsure if it’s browser session vs server session. Could you see if the details are saved in browser session or server session?

This should show all server session variables

<!DOCTYPE html>
<html>
<body>

<?php
print_r($_SESSION);
?>

</body>
</html>

hmm, all i get is NULL, which is odd because if no session were set then how is it staying up for even a minute let alone an hour.

This Google API OAuth thing has got my head in a total knot.

Is the browser session storage empty also?

Yes also empty