i will develope a wordpress plugin to access google analytics and visualize the data in a widget. So i checked some existing wordpress plugins, like the famous known "Google Analytics Dashboard for WP (GADWP)" - https://wordpress.org/plugins/google-analytics-dashboard-for-wp/. I was looking for a way how the user authorizes and get refresh and access token to access ga data in behalf of the user (who installed the plugin). And there i found that this plugin (and all other google analytics wodpress plugins) publish there secret. Because in a plugin (which the user downloads) it is impossible (i think) to hide the client secret, because the user of course see's the source code.
As the google documententation describes (https://developers.google.com/identity/protocols/OAuth2WebServer): Important: Do not store the client_secrets.json file in a publicly-accessible location. In addition, if you share the source code to your application—for example, on GitHub—store the client_secrets.json file outside of your source tree to avoid inadvertently sharing your client credentials.
So in this case i think the authentication of the request is lost. If i get or guess a refresh token of any other website that uses the plugin, i will be able to exchange refresh token with access token (because i know the client id and secret) and access the ga data. I already tested that.
So i am looking for a more secure way to access the ga data in my plugin without letting everybody know my secret. Are there any solutions or hints? I thought about sending every request through my server, so nobody know's my secret, but this is also not the solution of the problem. When exchanging the authorization code and receiving the refresh token maybe i have to exchange something like a key pair that will be used to encrypt every following request? Every following request will be to get a new access code for a refresh token.
Of course every user can create his own client id and secret. But this is now very user friendly.
Maybe is it possible to create a new api project and oauth authentication via api (what you normaly do via the google api console)?
Thanks for your help and hints,
Harald
Related
I currently have a backend running on AWS Lambda and I'm using DynamoDB as a database. In Dynamo, there is a list of users and each user has specific permissions as to what routes they have access to through the API. There is no issue here.
I have not built the front end yet, but I will be logging in users using Google Auth, more specifically with the react-google-login component.
My question is: Once a user is logged in to the site, should I trust the JWT from Google (after verifying its legitimacy
here with the Google API) which returns the user information (Name, Email), lookup the user item inside of Dynamo to retrieve their permissions, and then serve their request?
This seems like the logical thing to do but I was looking for some confirmation. My one worry is that someone could use a supervisors name & email to authorize a request but if the lambda must accept a JWT created by Google as entry, I believe this problem is solved correct?
I have API Keys as well for every user for some external functionality, but I have that covered since it's just a Dynamo call away. My only concern is with the front end requests to Lambda since I do not want to roll my own auth/jwt.
Here is what I was envisioning.
Thank you!
Normally you should use access tokens for that purpose. The ID token should be meant only to authenticate the user, and the access token should be used to authorize access.
The best scenario would be to have a separate Authorization Server which could issue access tokens, and there are some open source solutions out there which you can use.
If you really don't want to setup your own AS then you could follow the scenario you outlined - the part with verifying JWT from Google and checking permissions in the DynamoDB is what the Authorization Server would normally do to issue an access token.
Just remember to thoroughly validate the incoming JWT - not only the signature with Google, but also check if that is a token created for your client / audience, etc. Otherwise someone could take a Google ID token JWT from their client and gain access to your API. This article lists best security practices when working with JWTs.
Also remember that ID tokens might have short expiration times and there are no means of automatically refreshing them (like you can do it with a refresh token in case of an access token), so you might end up having to reauthenticate quite often.
Not sure if that is possible: I would like to switch from server flow to native client flow in order to provide a better authentication experience for my users.
The problem is that Azure AppService requires a "web application" OAUTH setup (contains client ID and a secret), while the native login works with just a client ID and not secret. This means that after the login on the phone, I do have a Google token, but AppService wouldn't know what to do with it and returns me an HTTP Unauthorized.
The mobile client SDK gives me an API, but that doesn't work with such a token.
var jObject = new JObject(
new JProperty("access_token", auth.AccessToken),
new JProperty("id_token", auth.IdToken));
await ServiceClient.LoginAsync(MobileServiceAuthenticationProvider.Google, jObject);
Any idea on the proper way to integrate this without having to write my own server-side token validation?
You would still need to configure the web application in Google since you are attempting to access a non-Google API. The native login on its own is not enough.
That means you will still need to provide the backend with an ID and secret. The client is responsible for obtaining an id token and authorization code which get sent to the server, and the server does the actual retrieval of the access token, per the Google documentation.
So that means your call will actually look something like the following:
var jObject = new JObject(
new JProperty("authorization_code", auth.ServerAuthCode), // not sure what property your auth binding exposes this as
new JProperty("id_token", auth.IdToken));
await ServiceClient.LoginAsync(MobileServiceAuthenticationProvider.Google, jObject);
There isn't documentation for the end-to-end using Xamarin.Android, but you might find it useful to glance over the App Service iOS documentation for this scenario just to see the moving parts. The general pattern you will follow is:
Configure everything for the server flow (as you've done before)
Set up the Google Sign-in SDK (seems like you've done that already, too).
Make the call as described above
The main issue you might run into is making sure that you have the API console registration correct. You'll want to make sure you have an Android client there connected to the web application client ID you are using. I'd recommend giving the Google Sign-in for Android setup instructions a quick look. Also note that authorization codes are one-time use, and there are some throttles that Google puts in place for a user requesting too many of them within some span of time. You might run into that during dev.
AS far as I know, the native client flow also use the google code flow to get access token.
According to this article, the Android, iOS, or Chrome applications doesn't need the secret to get the access token.
The client secret obtained from the API Console. This value is not needed for clients registered as Android, iOS, or Chrome applications.
But the web app backend will not authorized this access token if you don't set in your backend to enable Azure App Service authentication/authorization. Because the backend will have its own logic(the mobile server library write the logic according to the access token) to return the auth token according to the access token.
Now, the most easily way to enable the client flow in your mobile app is set in your backend to enable Azure App Service google authentication/authorization with the same clientid and secret(based on my test: if you don't set the right secret, the backend will still return the auth token).
Here is the test image:
If you still don't want to enable the app google easy auth, I suggest you could create custom authentication which contains your own logic to check the accesstoekn and get the user information from the google.
If the checked result is success and get the enough value, you could generate the auth token and return to the client side.
More details about how to create custom authentication in the mobile app backend , you could refer to this article.
I'm building an application that needs to have access to Google Drive and Google Sheets. I want the user to go to https://mydomain.appspot.com/authenticate to go through the Google login flow and authenticate themselves so that the backend receives access tokens for both Google Drive and Google Sheets.
After that I want the backend to be able to access Drive and Sheets without user interaction. For example, I would like a scheduled task to run every hour and retrieve some data from Drive and Sheets. I want the backend to use the token it received when the user authenticated themselves.
Is this possible? I really hope so. I have been looking here and I don't really find anything that can help me. https://developers.google.com/sheets/api/guides/authorizing
The backend is developed in Java and deployed on Google App Engine.
A long lived access token is actually called a refresh token. You will need to have your users authenticate your application then you will receive a refresh token. the refresh token can then be used to request a new access token from the Google authentication servers when ever you need.
Note: Do not get yourself side tracked with serviced accounts its not the same thing. You can run automated scripts using a refresh token gained from Oauth2, googles terminology is just a little confusing.
Check out the official google java client library it should handle most of it for you. Using OAuth 2.0 with the Google API Client Library for Java
You need to setup Offline Access as defined at:
https://developers.google.com/identity/protocols/OAuth2WebServer#offline
After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.
After reading the documents of Google API. I know that if a project we create needs to access private data, we should use oauth. But here is my situation. we will open a business account in Youtube, and we will create a project to push videos to our own account, we don't need to operate other user's' account. Can we use google youtube data api without OAuth?
There are two ways to access private user data with Google APIs.
Strait Oauth2. where you have a consent for asking the owner of the account if you can access it
Service accounts which are technically pre authorized by the developer.
Normally I would say because you are only accessing the one account that you own, use a service account. Unfortunately the YouTube API does not support service account authentication.
Due to the lack of service account support you will have to use Oauth2. I have done this in the past.
Authentication your script once, using a server sided language of some kind. The Authentication server will return to you a Refresh token. Refresh tokens can be used at any time to get a new access token. Access tokens are used to access Google APIs and are only valid for an hour. Save this refresh token someplace. You will then be able to allow access the YouTube account in question when ever you like.
Note: You will have to watch it. Refresh tokens can on rare occasion become invalid. I recommend having a script ready that will allow you to re authenticate the application again storing a new refresh token. Its rare that it happens but it can happen best to be pre-paired.
Oauth Play ground
Part of the point of Oauth is that it identifies your application to Google though the creation of your project on Google developer console. Things like quota and access to which APIs is controlled though that. If you spam the API they will know and shut you down. (never seen this happen)
When you request access of a user it pops up with the name of the project on google developer console. This is identified by the client id and client secrete for that project on google developer console. When I use oauth playground I get asked 'Google OAuth 2.0 Playground would like to ..'
So by using playground you are using Googles client id and client secrete to create a refresh token for yourself. If N other devs are also doing this the quota for YouTube may be used up in the course of a day. Also security wise you are now giving that project access to your data. Ignore that for a second what if google suddenly decides to remove change the client id or generate a new one. Your refresh token will no longer work. What if random dev X is using it as well and he starts spamming everything and the client id gets shut down (Think this happened last year) your going to have to wait for google to upload a new client id for the one that has now been banned.
Google OAuth 2.0 Playground might seam nice but its not for daily use IMO its good for testing nothing more. Create your own project and get your own access its not hard just requires a programing language that can handle a http Post.
My tutorial Google 3 legged oauth2 flow
Trying to test installation process for my marketplace application. Google documentation says that I can test installation process by using Test Install Flow button in the console. When I click on that button, I see the authorization dialog and I click accept. The dialog is closed and app is installed on the domain I am testing.
Question: Should I be getting and storing a refresh_token at some point in this installation process?
There is an Install URL that I can specify in Drive SDK but I can't find documentation about when Google posts to this install URL and what gets posted.
Here is a project which shows you how to do just that:
Checkout the section called: Cached Credentials
http://www.codeproject.com/Articles/488185/Working-with-Google-Drive-in-WPF
Excerpt from the above URL:
Provided the user allows access, the authorization server will return the authorization code. It can be sent back either by the Google server calling a web service endpoint opened by your application or in the title of the page sent back to the browser. Because of the challenges of spooling up a web server, opening a connection through any possible firewall(s), etc... it is much easier for installed applications to simply scrape the authorization code from the title of the resulting web page. That is the technique used in the sample project. If successful, the title will be set to Success code=xxxxxxxxx where the xxxx's are replaced by a unique authorization code.
The authorization code only gets you invited to the party. You can't do anything with that code as far as API access. The Authorization Code must be exchanged for a short-lived access code and a long-term refresh code. In the Google.Apis.Authentication.OAuth2 library is a class called NativeApplicationClient. This is the wrapper for the authorization server and it has a method called 'ProcessUserAuthorization'. This method takes the authorization code we retrieved after the user authorized the application's access and turns it into the access token and the refresh token. The access token is what we actually need for the task at hand and it is maintained in the NativeApplicationClient. It gets passed with all subsequent API calls. The nice thing about the NativeApplicationClient is that it knows how to verify the access token and how old the token is. If the token has expired, the client will use the refresh token to get a new access token. That takes the burden off of us to manage token lifetimes.
The short answer to your question around the refresh_token is - No. You won't get a refresh token upon install. You have to instead ask for a fresh access_token using a Service Account key you've got.
So basically, the way a Google Apps Marketplace (GAM) app is supposed to work is to get itself a Service Account and build with that for all authorization. There are no refresh_token with Service Accounts, just fresh new access_token. For an app that is installed by consumers you should use standard web server flow. This is one area of complexity that wants to be both a consumer and enterprise app.
When an admin installs your app, he/she is in essence authorizing your app's Service Account key to his/her domain.
Once an app is installed, that Service Account has full delegated access
Regarding the Install URL for a Drive app. You can ignore that for a GAM app.
Hope this helps. We'll release some end to end sample at some point soon .