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.
Related
I am integrating Google's login Apis on a website, and I need to place the user's details in our databases to use it the next time they login.
Googles developer documents clearly out lines that developers should never store user IDs in a database, instead you should use Token IDs generated by google to auth the legitimacy of the user.
I completely agree with this, but a token's live cycle is only a short period of time. If we insert the token in our databases, the next time the user logs in, they token will be different to that in our database. So how do we auth users via token id with google sign in?
I've read all of googles developer docs https://developers.google.com/identity/sign-in/web/backend-auth and theres nothing specifically explaining this, other than their process of authentication.
Could someone please help who may have had experience in this ?
Thanks alot
This is googles warning
Warning: Do not accept plain user IDs, such as those you can get with
the GoogleSignInAccount.getId() method, on your backend server. A
modified client application can send arbitrary user IDs to your server
to impersonate users, so you must instead use verifiable ID tokens to
securely get the user IDs of signed-in users on the server side.
Googles developer documents clearly out lines that developers should never store user IDs in a database
No, they don’t.
They are telling you that your server should not trust user ids send to it directly by the client - because anyone could easily fake those.
Instead, you are supposed to send the token, that you acquired on the client side, to the server (those tokens can’t be “guessed”, therefor you can not simply fake them) - and then you make a server-side API call using that token, to get the user id.
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).
This used to be a relatively simple thing to do (not as simple as it was a year ago, and now even less simple). Caveat: I am not well-versed in the Facebook API — I don't build apps; I just build web sites, and every once in a while need to display a simple (but far too custom for a facebook widget) display of a facebook page's feed. No problem, usually, but…
I usually just used a client token — just generated it once and stored it permanently as a variable. But for this site, accessing the feed requires a user access token because it's age-restricted (alchohol site). The way this would have been done earlier is to just generate a token with "offline_access", and I could store that permanently as a variable. But offline_access has been deprecated.
From what I understand, now my only option is a long-term access token. But these must be extended every sixty days.
All I want to do is display a feed — I don't want the user to have to do anything but see the feed — never be prompted to log in, etc. And I certainly don't want myself or my client to have to generate a new token every two months.
Is there some simple, permanent (I mean, until facebook changes the rules again) way to do this?
The offline access feature is still enabled but is deprecated and will (very soon) be removed.
Facebook does not provide an exact replacement for this feature. The only thing to do is to generate a long term token and regenerate it when it's about to expire.
In other words (as Facebook conceives it, I guess) : if the user does not visit your site for more than 60 days, then they're not interested anymore and you can no longer access their data.
If it's not the case, you could simply renew the token from time to time. As you know the token's expiration date (the API returns it along with the token), you can store it and check the best opportunity to display the connection dialog. Even if the 60 days delay have expired, you could fetch a new token when they are back without asking for permissions again.
You can think of it exactly as the "remember me" cookie. It's meant to provide comfort, not to circumvent security policies : it's irrevocability (by simple means) causes privacy and security issues.
I am using the stock SDK for php/javascript. Now the app I am building many parts of it, if a user approves the use and accepts the permissions acts as a layer on top of facebook. Where it is planned to have my App pretty much interact with it as if the user was logged on at the time.
Previously I was playing with the offline_access but I recently read that that permission is coming out of the api completely and soon enough any tokens already in existence will just convert to 60 day tokens. I know from what I read that I can renew the tokens on a daily basis if need be when a user logs into my app. But my two biggest questions that I can't figure out one way or another is.
How do I ensure I get the "long-lived" tokens, and with these tokens do I store them on my end and pass them through the api to FB or is facebook storing these and through the use of the api the way it is and I don't need to store them somewhere. I know currently when I login it generates a token and stores it in a php session but the session is usually only good for the duration of the user being on my app. Note this is also a desktop app, not an app within facebooks canvas.
If I have to store the tokens to use them, and the php sdk bases itself off of whats stored in a session do I recreate the session with the stored access token for the user or I dunno, Im confusing myself as I type this out, hopefully someone can shed some light on the subject for me.
Here you can find some help on how to handle the expired tokens,
https://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/
And here more info on how to use the new method,
Facebook offline access step-by-step
All this matter always makes me doubt as well, but I have noticed that facebook usually keeps the token somewhere on the user end, probably a cookie, so that it will automatically connect. So I don't think that the token only lasts a session and I'd rather say you won't have too many problems with the depreciation of offline_access, though this might just be my personal opinion.
Facebook document that you need to do the following for canvas login
Include facebook library
Instantiate class with App Id and secret
Check that the user has a valid session
If they do check also that you can get there user object by doing an api call /me
If they dont then process the login redirect
All this especially the Facebook calls can take quite some time to process
The example shows this in terms of code
http://github.com/facebook/php-sdk/blob/master/examples/example.php
And from what I read it seems required on every page. Because a user can logout / remove app / change permissions etc during the session
My question is what is the ideal way of doing the above in terms of performance gains, but still making sure that it conforms to the nuiances of facebook.
Facebook do give a session expire time which seems to be in GMT.
I code in PHP using the Zend Framework but I suppose the above relates to all languages.
Appreciate your help on this
Ian, store your user facebook credentials in the user related table (or whatever)
facebook_user_id
facebook_secret
facebook_token
make it come out like something like:
$user->facebook_session_array();
Then just pass that into your api class when you want to reuse it. There is nothing you can do to make the oauth process (on authentication) go any faster because it has to happen live.
Cache the living daylights out of anything and everything you bring back from facebook.. run some crons in the background to either insert that stuff to table or stamp it down on a drive. Your cron script should be able to handle potential rate limitations. I wrote some, but facebook is so slow, I think it was pointless.
Facebook is slow.. don't make your app wait for it in any way you can avoid it.
first of all you'll have to authorize a user via facebook api, if you like to work with data of this user. As a result of a successful authentication your application will receive an access_token and a expire_time. The value of expire time is expressed in seconds, not a timestamp in GMT.
Your application has the permission, to store the access_token and expire_time within it's own session handling, e.g. You'll need the access_token to make requests on behalf of the user to the facebook api. With the expire_time value (and the time you authorized the user) you can check the validity of your access_token before calling fb API methods... and in case it expired, you should reauthenticate.
You definitly do NOT need to reauthenticate on every page reload of that user.
If the user changes something on facebook (e.g., removes your application) then a call to the api might fail with an "OAuthException" error. Your application should be aware of such errors and handle them appropriate.