Rgoogleads - Issue with Service Account - r

I am trying to migrate my RAdwords code to rgoogleads and keep bumping into the same authentication nightmare. Some context:
Use R in my local computer, but all deployments are in a remote server that runs shiny, RStudio and other goodies.
I have managed to successfully activate the service account. I am (almost) sure about it since I successfully connect to Google Ads with Python.
I tried the same code with local OAuth2.0 and it works fine. However when I try to do so with the ServiceAccount authentication I keep getting the same error. I am sure I am doing something wrong.
This is a sample of my code:
library(rgoogleads)
gads_auth(path='../serviceAccount.json')
gads_auth(email='my_email#company.com',
developer_token = '_my_dev_token_'
)
gads_set_login_customer_id('xxx-xxx-0524')
gads_get_accessible_customers()
And this is the response
<error/rlang_error>
Request had insufficient authentication scopes.
Backtrace:
1. rgoogleads::gads_get_accessible_customers()
2. gargle::response_process(ans, error_message = gads_check_errors2)
8. rgoogleads:::error_message(resp)
9. rgoogleads:::gads_abort(paste(client_id, msg))
10. cli::cli_abort(message = message, ..., .envir = .envir)
Even when I try gads_has_token() it returns TRUE (!)
Any clues? I can't seem to get my head around this.

Related

How to use the resource_owner grant within Microsoft365R

I'm trying to implement an unattended script accessing files within OneDrive using Microsoft365R.
I've setup everything like in the docs using the default app registration.
The interactive flow with auth_type="device_code" works without issues:
odb <- Microsoft365R::get_business_onedrive(auth_type="device_code")
But when trying auth_type="resource_owner" like shown in the docs here, I get the following error:
odb <- Microsoft365R::get_business_onedrive(tenant=tenant, app=app, username=user, password=getPass(), auth_type="resource_owner")
Error in process_aad_response(res) :
Bad Request (HTTP 400). Failed to obtain Azure Active Directory token. Message:
AADSTS50126: Error validating credentials due to invalid username or password.
My guess is, that the default app is missing some privileges to use the "resource_owner" flow.
Can someone point me to the right direction on how to get the resource_owner flow working?
(Using Service Principles is not a solution for my setup, but I did also try it with a dedicated service account and it was not working either)

Why would a callback URL not work (for a GroupMe bot)?

I am creating a GroupMe bot, and I'm testing out the callback URL and the basic WSGI app I've set up so far. I am planning host the bot on Heroku, but am testing it on my local machine first. I registered a bot, with the callback URL http://MY_IP_ADDRESS:8000. When I open a different shell and run requests.post('http://MY_IP_ADDRESS:8000', data = 'something') in the Python interpreter, everything works fine. However, when there is activity in the GroupMe group, nothing happens, not even an error message.
Here's my (simplified) code:
from wsgiref.simple_server import make_serve
def app(environ, startResponse):
try:
requestBodySize = int(environ.get('CONTENT_LENGTH', 0))
except ValueError:
requestBodySize = 0
# requestBody = environ['wsgi.input'].read(requestBodySize)
print('something')
responseBody = bytes('successful', 'utf-8')
status = '200 OK'
responseHeaders = [('Content-Type', 'text/plain'), ('Content-Length', str(len(responseBody)))]
startResponse(status, responseHeaders)
return [responseBody]
server = make_server('', 8000, app)
server.serve_forever()
I'm sure I'm doing something obvious, but I can't for the life of me figure out what. I'd appreciate any help!
I never figured out why the callback URL wasn't working with localhost, but when I deployed the app on Heroku, everything worked fine! It must have had something to do with my firewall settings.
When you run servers on your local machine your firewall doesn't really like that. GroupMe also cant send to anything but public facing addressees, which is why Heroku works. One thing I can recommend in the future is using Ngrok, https://ngrok.com/ this will work with your server to make a public facing address on your machine that you can use as callback url. I use Ngrok to test my bots and quickly iterate before pushing to a dedicated server like Heroku, honestly looking through Heroku log files is a pain...

Previously working Python script using Google Reporting API v4 now returning 403

I wrote a python script to pull yesterday's data from Google Analytics. I'm using OAuth v2 with Google Reporting API v4. The backbone of the script is essentially the same as Google's sample version, except I included recursion to overcome the pagination limitation and am outputting the results to a CSV file.
Today it started to return a 403 error:
HttpError 403 when requesting https://analyticsreporting.googleapis.com/v4/reports:batchGet?alt=json returned "The caller does not have permission"
I did my due diligence by searching for a solution, but I already am using the ViewID and the computer that it's running on isn't signed into any other accounts (it exists to only run reports). I've also tried creating a new client_secrets.json file and verifying that I am within quotas, but the issue still persists. Nothing changed between yesterday and today, yet it refuses to run today.
EDIT
I'm using the same connection object, it's only instantiated once, the code is the exact same as on Google's website here -> Hello Analytics Reporting API v4 - Python
def initialize_analyticsreporting():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[tools.argparser])
flags = parser.parse_args([])
flow = client.flow_from_clientsecrets(
CLIENT_SECRETS_PATH, scope=SCOPES,
message=tools.message_if_missing(CLIENT_SECRETS_PATH))
storage = file.Storage('analyticsreporting.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage, flags)
http = credentials.authorize(http=httplib2.Http())
analytics = build('analytics', 'v4', http=http, discoveryServiceUrl=DISCOVERY_URI)
return analytics
I'm invoking it the batchGet method on each request like so...
response = analytics.reports().batchGet(body=loaded_request.get("request", {})).execute()
I've managed to work around this by using the exponential back-off in conjunction with recursion and try/except block, similar to the method recommended by Google here -> Error Responses
Like so:
try:
response = analytics.reports().batchGet(body=loaded_request.get("request", {})).execute()
except HttpError as err:
print(err)
time.sleep(2**expontential_backoff)
expontential_backoff += 1
if expontential_backoff < 5:
get_response(analytics, request, page_token, file_name, expontential_backoff)
else:
print("expontential_backoff:", expontential_backoff, "Exceeded")
return
If the error hits then when by when n > 1 it usually works just fine. I'm not terribly fond of this method, ideally I would like it to work correctly.
If there is no other solution, then hopefully this will help someone in the future.

SignalR negotiate fails (Bad Gateway)

Someone any idea, I’ve been struggling with this for some time.
I'm using SignalR (Asp.net 5). when I try to debug local (ISS 10.0 express) everything is working fine. SignalR is working (Long poll).
Now when I publish the app to Azure it I can access : .azurewebsites.net/signalr/hubs
but I cannot access .azurewebsites.net/signalr/hubs/negotiate
it returns:
The specified CGI application encountered an error and the server terminated the process.
When my web app calls $.connection.hub.start() it will fail.
GET XHR http://xxxx.azurewebsites.net/signalr/negotiate [HTTP/1.1 502 Bad Gateway]
I’m running out of idea's. Don't know how I can get more debug information.
Small selection of my ‘already tried’ list:
Set $.connection.hub.url path manual to http://xxxx.azurewebsites.net/signalr/
Enable/Disable websockets
Removed forwardWindowsAuthToken from the web.config httpPlatform
EDIT:
Now getting more details on this error:
CryptographicException: The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating.
Still absolutely no idea how to solve this!
Solved by using appBuilder.UseAesDataProtectorProvider();
(from Owin.Security.AesDataProtectorProvider;)
I have no idea if this is the best solution.

Authorization for accessing BigQuery from R session on server

I am using R and package bigrquery to access Bigquery from an R session.
This works great as long as I am on my local machine.
However, when I try to access Bigquery from R on a remote server it does not work at all.
I tried to copy the .httr-oauth file into my home directory on the server but this does not work.
I get the error message:
Auto-refreshing stale OAuth token.
Error in refresh_oauth2.0(self$endpoint, self$app, self$credentials) :
client error: (400) Bad Request
I really have no idea about where to store the necessary credentials and unfortunately I was not able to find anything useful about that by google-searching the topic.
By default httr, which is used by bigrquery for oauth, will look in the R session's current working directory for .httr-oauth. You can override this location with the following (perhaps putting it in your .Rprofile if you like):
options("httr_oauth_cache"="~/.httr-oauth")
But for error message you received, its seems like the location is not the issue and it might be easier to just redo the oauth flow on the remote server to cache a new credential. To trigger a new oauth flow on the remote server:
ensure the .httr-oauth file does not exist
restart R
perform one query with bigrquery
Note that if httr tries to redirect to localhost, you can force it to do an out-of-band oauth flow with:
options(httr_oob_default = TRUE)

Resources