Google Calendars: method of keeping track of API refresh tokens - php

I am using Google Calendar API to have offline access to user calendars.
So when a user first authenticates the app, I am given a refresh token.
On subsequent accesses, no refresh token is given.
So in order to keep these, I am storing the refresh token against my own database user table. So I know when a particular user of the site is logged in, that the Google refresh token is $refresh
This works just fine when the user only uses 1 Google account, but if they authenticate the app across multiple Google accounts. There are multiple refresh tokens, but on my database side, I am storing just one.
So the first thing to do was to store all refresh tokens, tying them all to the single website user.
But even still this is incorrect, When granting access to a specific calendar, I won't know what Google account that particular calendar is associated with. (unless I am missing something)
So when they grant access to a calendar, all I have to go with, is what user was signed into my website.
So if someone grants access to say 2 calendars, which are in 2 different Google accounts, but both tied to the one website user. How can I know which Google account was used for which calendar?
Without knowing that info, the refresh token is going to fail until I pick the right refresh token. Which would have to be done by cycling though the refresh tokens until one works.
Is there some way to store something that would help me know which refresh token is tied to each calendar (rather than only tying it to a website user) they have authenticated?
Or is my methodology wrong in the way I am storing the data, and there is a better way to store this info that makes better sense.

A refresh token is obtained in offline scenarios during the first authorization code exchange. Even though user has multiple accounts, refresh token is generated for each google account(even users are same).
Also, when you are storing the refresh token in your database store refresh token along with the user ID(google account id) and calendar ID(even though both ID's are same but in few scenarios, each user can have multiple calendars).

Related

Can I indefinitely generate access tokens using one refresh token in Google API

I'm kinda confused using Google API
I've a FORM on my website for booking events on my public calendar. Whenever a user books an event, I make a call to get an Access Token (using Client ID & Secret and Refresh Token), but using the same Refresh Token that I generated initially. For every new Access Token, I'm using the same Refresh Token. It's all working fine. But I don't understand the flow.
Do I need to generate a new Refresh Token on every call? What are some limitations of not doing so? Can I keep on generating Access Token with the same Refresh Token indefinitely? Thanks!
Refresh tokens are long lived they can expire if the user who's account was used to create it removes access. If its not used in the last six months google will also expire the refresh token. Here is one that is a bit tricky if you use the client id to request access of the user you get a refresh token if you do it again you get another refresh toke technically both refresh tokens work you can do this up to 50 times on the 51's time the first one will be expired. You can use a refresh token as many times as you want to get a new access token.
My question for you is who's google calendar are you writing to the users or some default one on your website? If this is a central Google calendar that you are writhing to then you should consider using a service account rather than Oauth2. I have an article on how service accounts are used if you are interested. Google Developer service accounts

Get Google OAuth2 authorised accounts

I have authorised multiple accounts via Google's OAuth2. How do I get a list of accounts that I have authorised? I want to be able to revoke access.
To make it clearer, I go through the OAuth2 flow multiple times, each time selecting a different account. Then, I get the access/refresh token and save it to my database. By doing that, I noticed that I still get access to resources not tied to the latest account but also those that are tied to previously authorised accounts. I want to be able to list and allow my users to revoke access to these accounts.
There is no way to get a list of the users who have authenticated your application. I have this problems as well because I have a number of users who are still using a very old version of my application who i would like to inform them they should upgrade but i cant as i have no contact to them.
Revoking access of known users:
Your application can have as many users as you want authorized to it. The refresh token gives you access to each of the users data. The access will remain until the user revokes it or the refresh token hasn't been used for six months.
You can revoke it programmaticly by revoking the token
Try using:
$client->revokeToken();
This should revoke the old access given by a user. You will have to load the old refresh token into the client of course.

Spotify automated playlist management with PHP back-end and rate limits

Two questions:
Question 1.
We need to manage 4 playlists of a Spotify user from our back-end (PHP) (without user login).
Visitors of our website can submit multiple of their favorite songs to our websites. Based on that, we create and manage 4 playlists which contain the ‘top most submitted songs’. We want to automate this process from our PHP back-end without the need of manually managing the playlist day to day for a period of multiple months.
We would like to use the Spotify API for this, but a user access token is needed to access and manage user playlists. We created a proof of concept, which “simulates a browser with PHP”. We log in, retrieve an authentication token, request an access token with the authentication token and then perform the necessary API calls – all without user intervention.
This method works, but we suspect and know this isn’t 100% the way to go :). We’re not after abuse of the API or whatsoever, but how can we periodically automated manage these 4 user playlists if this isn’t the right way?
Please note our back-end is Apache – PHP based. We could also use NodeJS, but then again, this isn’t the way to go either.
Question 2.
Users submit songs to our website. When the user types in the search field (song title / artist name), after one second we perform an ajax call to the Spotify API and show the search results based on the input. Taking into account the amount of visitors expected on the website, this might cause a lot of traffic to the API.
The docs (https://developer.spotify.com/web-api/user-guide/#rate-limiting) aren’t very clear on the applied rate limits. Is it possible to give us a better indication of these rate limits since we want to prevent this from crippling our website?
Thanks in advance.
Question 1
If you want to create playlists in a certain user's library you need to that user to grant those permissions to your app.
In your case, you would implement the Authorization Code flow to obtain both refresh and access tokens.
Store the obtained access token and refresh token, use the access token to perform the requests, and renew the access token whenever it expires using the refresh token.
If you are going to manage those playlists in a user you own, then there is no need to show any login form to users. Log in once, and use the fetched tokens in a script that will periodically make changes in your user's playlists.
Question 2
The limits are not specified on the Spotify Developer site at the moment, but they API should be able to handle your search requests. If you want to be extra-safe, authenticate your requests so they are limited by client_id basis. To obtain a token like this, that doesn't contain any user's information, you can use Client Credentials flow.

Is it necessary to re-authenticate with OAuth on every single page?

What I'm trying to do is basically have a system that allows people to post to Tumblr via this website using Tumblr's API. I think it would work something like:
Get the user to grant our application permission on Tumblr; get the token and secret from Tumblr.
If this user has never authenticated before, store the OAuth token, OAuth secret, and the user those belong to in a database.
If the user has authenticated before, check the OAuth token and secret that Tumblr just gave us against the ones already stored in the database to re-authenticate this user.
So, do I need to re-authenticate with OAuth on every single page? Or in other words, I need to contact Tumblr every time the user loads a page to make sure they're still the person they say they are?

Google Apps and OAuth best practices

I am working on integrating Google Apps into my PHP app. I have already a login system that assigns a session ID to a user (after entering username and password), which gets stored in the database when the user is logged in. Session ID's become invalid after a certain time of inactivity (configurable by the user, can be 5 minutes, 15, 60...). That session ID is passed in the url to check if a user is still logged in. When logging out, the session ID is removed from the database.
I let people log in with Google by storing their Google ID in the database, when they log in, I request an access token, query the userinfo, see if the google ID is in the database and if so, assign a session ID to this user. Since I want to be able to query other API's I also store the access token json in the database. When a user logs out, the access token is also removed from the database.
This works, my users are able to log in using their Google account and I can query the API's using the stored access_token, however some things feel clunky of make me feel uncertain about my workflow:
If you force_approval you get a refresh_token, I feel like I should be using this refresh token to get a new access token, instead of removing the old one from the database and entering a new one when the user logs in again. On the other hand, when logging in, I do not know who it is yet, so I don't know which refresh token to use. Maybe I'm misunderstanding what the refresh token is for. Also, I don't really want to force approval every time, so I can't even use the refresh_token in that case.
As said before, users can determine how long their session will last, however, the google access_token always expires after 3600 seconds. It'd be really stupid if users would work an hour on the system and after that the Google API's suddenly fail, forcing them to log in again. The Google OAuth playground shows a checkbox "Auto-refresh token before it expires", but I'm not seeing how to do this. Do I have to use the refresh token here? Or simply request a new token in the background (if I'm not forcing approval)?
At the moment, I'm using the userinfo query (https://www.googleapis.com/oauth2/v2/userinfo) to find the user id, but I can also use the tokeninfo (https://www.googleapis.com/oauth2/v1/tokeninfo). Tokeninfo is not listed in the oauth playground, but the result does show how long the token remains valid (however, I can also calculate this myself). Is one preferable over the other?
I'm storing the entire json object in the database (access_token, id_token, expires_in and token_type) but I feel my app will still work perfectly if I only store the access_token (only problem I foresee is if the expires_in time changes). Do I need to store the id_token for example?
I find the Google documentation (at developers.google.com) sometimes very lacking, if anyone knows any other good sources of information, I'm interested in them as well.
I think it might help if you took a look at the lastest OpenID Connect Specs where concepts like the userinfo endpoint come from. OpenID connect is built on top of OAuth 2. There's quite a lot in there, but it's still probably worth a look. This blog article is also very good (as are others in the same blog).
Unfortunately, I don't think Google's implementation is currently up to date with the latest spec draft so it will probably be a moving target for some time. These things have changed a lot over the past year.
I agree with your first point that you should be obtaining a new access token each time you authenticate a user, rather than refreshing an old one. You don't know who the user is until they have logged in and granted you an access token. In general, the lifespan of an access token is not linked to the user's session. Once issued, your application could theoretically use it to access resources independently of the user's presence. If you want to carry on accessing the resource beyond the token expiry time, then you need to submit the refresh token at that point to obtain a new access token. I'm afraid I don't know what the "auto-refresh" feature is for.
I believe Google's tokeninfo is analogous to the check_id endpoint of OpenID connect, but accepts either an access token or an id token, rather than just the latter. Note that the expiry times of the two may differ. You would typically be able to retrieve more detailed user data from the userinfo endpoint than from check_id, which would normally return the bare user_id.
You shouldn't need to store the id_token. It is a bit like a record of the user's authentication by the authorization server. The access token is what your application will be interested in maintaining once you have validated the user identity.

Categories