Impersonated User unauthorized in Google Analytics API, using Service Account - google-api

I'm using the Google's PHP API Client, release 1.1.6.
We have a company Google account which controls our many Google Analytics account as well as our Google Developer apps.
I'm working on an app accessing our Google Analytics, using a Service Account set-up. I'm using the same code provided here:
https://developers.google.com/api-client-library/php/auth/service-accounts#delegatingauthority
$credentials = new Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
$user_to_impersonate,
);
In this case $client_email is the App Service Account client (random-chars#developer.gserviceaccount.com) and $user_to_impersonate is our company's Google Account.
As of a couple days ago this was all working correctly, and I could access all our Google Analytics accounts through the API after the above authentication. As of yesterday, I'm getting this error:
Error refreshing the OAuth2 token, message: '{
"error" : "unauthorized_client",
"error_description" : "Unauthorized client or scope in request."
}'
With the $user_to_impersonate parameter removed the authenticated works without error. However, I've been using the $user_to_impersonate as we have several hundred GA accounts and the Service Account client is not a permitted user on them (and would have a limit of 200 accounts anyway).
I couldn't find any recent updates to the way Google Dev's authentication works, but maybe I'm missing something.
Any ideas?
UPDATE: Apparently this was a temporary error with Google's overall API, and is now fixed:
https://github.com/google/google-api-php-client/issues/891
UPDATE 2: Wasn't a temporary issues after all. The solution, if others need, is listed here. Basically giving your app perpetual access to the given account/scope.
https://github.com/google/google-api-php-client/issues/801#issuecomment-171417538

Google probably changed the handling of service accounts and this doesn't work anymore. It's not related to specific Google API client (PHP) nor specific API (Analytics), but it seems to me as a general change which affects everything.

Related

Google Cloud Run Hosted User Sign-In 'Redirect' Throws Error When Using External Identity Providers

I have a Google Cloud App Engine app that functions correctly when either I allow unauthenticated AllUsers access or turn on IAM for controlling access in Identity Aware Proxy. However when I follow the instructions on this page https://cloud.google.com/iap/docs/cloud-run-sign-in to enable Cloud Run Hosted sign-in with external identities and attempt to access either the login page or the Google Cloud Run hosted sign-in page, I receive the following error in the browser.
"Could not fetch URI /computeMetadata/v1/instance/service-accounts/default/token?scopes=https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/identitytoolkit"
For context, the Google Cloud Run service hosting the user sign-in is set to allow all Unauthenticated. It should re-direct to the Google App Engine web app. I think this is related to permissions or redirects, but I am at a loss as to how to fix. Any thoughts? Thanks!
I attempted to fix by re-deploying the Cloud Run Service, switching IAP on and off, switching between IAM and external identities, but to no success.
Thanks #John Hanley, I discovered that one my compute engine service account was disabled for some reason within the project. Re-enabling solved the problem partially. I'll spend more time matrix out the permissions and re-directs to make sure they are aligned.
I originally thought I completely answered my own question and solved my problem. Unfortunately, I only solved one of the problems with my implementation of the external identities authentication method.
Description of the other problem:
I enabled email/password and Google as providers, but when I click on the the option to authenticate with Google, I receive the following text in the browser: "The requested action is invalid."
At the Console in Dev Tools I get the following error:
GET https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectConfig?key=*mykey*&cb=1599165379363 403
The following url is displayed in the URL bar:
https://.firebaseapp.com/__/auth/handler?apiKey=mykey&appName=%5BDEFAULT%5D-firebaseui-temp&authType=signInViaRedirect&providerId=google.com&customParameters=%7B%22hl%22%3A%22en%22%7D&scopes=profile&redirectUrl=https%3A%2F%2Fiap-gcip-hosted-ui-app-engine-app-myserver-uc.a.run.app%2F%3FapiKey%3Dmykey**&v=7.16.0&fw=FirebaseUI-web
mykey and myserver were removed for this post and is not the actual values.
Email/password sign-in works, but not the Google sign-in. What am I missing here?

Google API giving unauthorized token error

We have an application hosted in GCP which uses GSuite APIs to sync users from GSuite to our application and visa-versa using Service Account. It used to work well until recently some of our customers started facing issues.
We started getting
401 unauthorized. "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
There as been no change in our application and neither in the list of permissions granted. Following are the list of api access granted :-
https://apps-apis.google.com/a/feeds/domain,
https://www.googleapis.com/auth/activity,
https://www.googleapis.com/auth/admin.directory.group,
https://www.googleapis.com/auth/admin.directory.orgunit,
https://www.googleapis.com/auth/admin.directory.user,**
https://www.googleapis.com/auth/admin.directory.user.readonly,
https://www.googleapis.com/auth/drive,
https://www.googleapis.com/auth/drive.appdata,
https://www.googleapis.com/auth/drive.file,
https://www.googleapis.com/auth/drive.metadata,
https://www.googleapis.com/auth/drive.metadata.readonly,
https://www.googleapis.com/auth/admin.directory.rolemanagement.readonly,
https://www.googleapis.com/auth/admin.directory.rolemanagement,
https://www.googleapis.com/auth/admin.directory.device.chromeos.readonly,
https://www.googleapis.com/auth/admin.directory.device.chromeos,
https://www.googleapis.com/auth/drive.apps.readonly,
https://www.googleapis.com/auth/drive.photos.readonly,
https://www.googleapis.com/auth/drive.scripts
The affected GSuite domains were working perfectly until yesterday. Also there are some domains which still work without any problem.
Can somebody please suggest what could the problem be. Is there any change in the APIs recently? Any help will be much appreciated.
"Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
There are several ways to authenticate to Google.
web based applications
native applications
mobile applications
and service accounts
The clients you create for these types is different as is the code to use them. The message you are seeing above means that the code you are using does not match the type of client you have created.
Make sure your code is designed for use with service accounts and make sure that the credentials file you have downloaded from google developer console is in fact credentials for a service accounts.
Why it worked previously and suddenly stopped i cant tell you this is an error you will always get if your code does not match your credential type.
The last option would be to double check that all of those apis are enabled in the Google developer console for your service account project.

How to get authorization for accessing Google Play developer API

I am trying to access Google play developer API https://developers.google.com/android-publisher/ to build an inapp purchase product for my company Application.
We have to get authorization to make a GET call to the Google play developer API. https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/get
I followed the steps presented here. https://developers.google.com/android-publisher/authorization
Created an Oauth client and and also service account. The gmail account I used was part of the 'Users and permissions' in play.google.com console.
But when I tried to access the API, I got an error
As I started searching about this error, I understood that there is something else called 'API Access' in play.google.com. When I tried to access it, All I saw was
But I saw in other posts that there exists a screen with details like
https://i.stack.imgur.com/Hdjjy.png
So how can I go forward to access API. I did everything as mentioned in documentation of google but it didnt work. Also I dont have access to see the screen of 'API Access'.
Also I am confused, if you can create service accounts from both 'API Access' screen and also from 'credentials' screen in console.developers.com, which one should be used ?
Just to check you understand there are a few different APIs to do with in-app purchases.
Play billing library is designed to be used in your app. This is what allows users to buy things from your app
Configuring in app products. When your app supports in-app products you have to support what the products are and the prices. This is done via the Play console, either manually or in batches uploading CSV files.
Finally is the API you refer to in your question. This is not designed for use in your app, and you don't have to use it to support in-app products. Instead this API allows your server (not app) to validate a user's purchase. In order to use this API, you need to enable the "API access" in the page you found. This can only be enabled by the account owner for the Play console, for security reasons. You will need to find the Owner of your Google Play account, and get them to log in and create a service account which has API access.
I am able to access it now. I am not the owner of the Google Play console.That was the issue. You just have to go to API Access page and click on "create OAuth Client" or "create Service Account ".
You can use those credentials to access API from postman or through your code.

Google+ Domains API via service account fails with 403 Forbidden

I have a simple Ruby code that I combined from several examples. It uses Google+ Domain API. I followed all steps to authorize a service account (https://developers.google.com/+/domains/authentication/delegation), but my requests fail with 403 Forbidden:
{"error"=>{"errors"=>[
{"domain"=>"global", "reason"=>"forbidden", "message"=>"Forbidden"}],
"code"=>403, "message"=>"Forbidden"}}
The same queries work fine if I execute them using Google APIs Explorer console. I think it's related to the service account vs. user account authentication. What did I miss?
The full code is here https://github.com/admitriyev/propellant/blob/master/main.rb
[edited] I added an installed app flow into the same code, and it worked fine (full code is on Gihub above). I still don't know what I missed in the service flow though.
I figured it out, I was missing the email of the actual domain user on behalf of whom it should be authorized. I also switched to use Google::APIClient::JWTAsserter which is a cleaner
abstraction:
client_asserter = Google::APIClient::JWTAsserter.new(
config['client_email'],
PLUS_LOGIN_SCOPE,
key
)
$client.authorization = client_asserter.authorize(config['user_email'])
My full example is here: https://github.com/admitriyev/propellant/blob/master/main.rb

Using OAuth 2.0 for Devices - Google API - Google Drive

I took a look in some docs at developers.google and some questions here in stackoverflow and I really would like to found an objective answer about use the Google OAuth Server to authenticate an application and grant access to download docs into a Google Drive account with NO BROWSER interaction.
As far as I could look, docs like "Using OAuth 2.0 for Server to Server Applications", "Using OAuth 2.0 for Devices", answers here, I couldn't found an article saying "Is possible to authorize an application to get files from a common Google Drive account in Devices with no browser...".
Anyone have tried and had success in this jorney?
The Devices flow is meant for applications that run on devices where no browser is present (fancy example could be a wristwatch that shows new G+ notifications) and requires the user to do manual steps on a device that has a browser. Also this is for getting access to data on the user's account.
UPDATE:
As you say you have an embedded application running without a browser available and want to access data on behalf of a user, this is definitely the way to go. This however still needs the user to login (once) on another device with a browser. After you got an access token using this flow, you can then access the Google Drive API either manually or by using some library.
So you want to access data on Google Drive that belongs to a special account and only your application can access it without a browser involved?
A Service Account (the Server-to-Server flow) would be exactly what you need. These however are only for usage on a web server, as otherwise your private keyfile would have to be deployed to a client, where it could easily be extracted.
One thing you could do is use your own web server that fetches data from your Google account using a Service Account and have a client application that only connects to your own web server. This has of course also its downsides, especially when it comes to locking down your web server so no third party clients could access it.
It can be done, but a browser does need to be used. I've successfully gotten OAuth 2.0 working on an IBM i (AS/400, iSeries, System i, whatever the name is today) which doesn't have a browser. I've so far implemented the Calendar and Google Cloud Print APIs.
During the OAuth 2.0 negotiation you will be returned a URL and a code. You need to display the URL for the user to go to, then the code to enter to grant authority for that specific API/scope. I have an example in our documentation here:
http://docs.bvstools.com/home/greentools-for-google-apps/docs/g4g-base-commands/g4gregsvc
But, the issue now is that the drive API is not yet available to devices. But, Google has said that soon it should be.

Resources