google+ api moments.insert 401 Unauthorized with python-requests - python

I have successfully inserted a moment with this procedure before and am trying to figure out if the API is currently broken or i'm making a mistake.
I have obtained a valid access_token with request_visible_actions=http://schema.org/AddAction as seen in the partial url below from the auth stage as well as plus.login scope:
https://accounts.google.com/o/oauth2/auth?access_type=offline&request_visible_actions=http%3A%2F%2Fschema.org%2FAddAction&
the request code:
import requests
import json
moment = {"type":"http://schema.org/AddAction",
"object": {"id": "object-id-1",
"type":"http://schema.org/AddAction",
"name": "The Google+ Platform",
"description": "A page that describes just how awesome Google+ is!",
"image": "https://developers.google.com/+/plugins/snippet/examples/thing.png"}}
url ='https://www.googleapis.com/plus/v1/people/me/moments/vault'
params = {'access_token': 'MY_VALID_ACCESS_TOKEN'}
r = requests.request("POST",url=url, params=params, json=moment, headers=headers)
print r.url
print r.json()
and the result:
https://www.googleapis.com/plus/v1/people/me/moments/vault?access_token=MY_ACCESS_TOKEN
{u'error': {u'code': 401,
u'message':
u'Unauthorized',
u'errors': [{u'domain': u'global', u'message': u'Unauthorized', u'reason': u'unauthorized'}]}}
I tried to verify with the tokeninfo endpoint that request_visible_actions are present, but it's not listed there.
confirmed granted scopes:
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.profile.emails.read',
'https://www.googleapis.com/auth/plus.moments.write',
'https://www.googleapis.com/auth/plus.me',
'https://www.googleapis.com/auth/plus.profile.agerange.read',
'https://www.googleapis.com/auth/plus.profile.language.read',
'https://www.googleapis.com/auth/plus.circles.members.read'
I am able to get moments/vault with the same token so i know it's valid.
Any ideas here?

The procedure shown in the question does in fact work as long as request_visible_actions=space separated list of app activity types was included when the user makes the first connection to your app and the app activity type you are trying to post was included. If you want to update the list or add the moment.insert permission after initial authentication, the user must first disconnect the app from their google+ settings and reconnect.
It seems this is a bug with google's implementation of request_visible_actions and an incremental authorization strategy.
request_visible_actions seems to only be accepted during initial authorization and disregarded after that. This makes incrementally adding this parameter impossible.
Further more, request_visible_actions is not available when calling the tokeninfo endpoint, which leads me to believe that request_visible_actions is somehow dissociated from token auth and merely an attribute assigned to the user's app connection on instantiation.
Posted to exising moments.instert 401 issue:

Related

Python Requests / HTTPX - Authenticate All Redirected URL - How To

I wonder if there is a way to authenticate each redirected URL when working with Python modules such as httpx or requests?
Problem Statement
I am trying to connect to an API endpoint under the company network. Due to the company's cyber security measures, the API endpoint will be randomly masked with a company proxy, which causes the 307 Redirect status code.
my current code snippet looks like the below:
import httpx
api_url = 'https://demo.vizionapi.com/carriers'
head = {
'X-API-Key':'API KEY'
}
response = httpx.get(url=api_url, verify='supporting_files/cacert.pem',
headers=head, auth=('my username', 'my password'),
follow_redirects=True)
With above code, I received the 401 authentication needed error (But auth has been passed). This error will only happen when redirection occurs due to the company proxy.
Question:
My assumption is the authentication is only being passed into the first URL not the redirected URL. Therefore, I wonder if anyone know how I can use the same auth parameter for all URLs (direct & redirect)?
Any suggestion will be deeply appracaited.
I don't know what requests behavior with regards to auth during redirect is, but the first solution to come to mind is to manually follow the redirects yourself. Put your request in a loop that checks for the 3xx response codes, and handle auth however you want to.

How to debug error 403 on Rest API with valid token with Python Requests package

I'm new to using APIs and I'm trying to access an Adobe Rest API using the Requests package.
I have managed to get a token but I get a 403 error (logged out) with any request I attempt.
I have performed the OAuth Authentication successfully and, Using a Legacy Application Flow (required by Adobe), I've fetched a token that grants me read and write access. I've tried a few get requests get the 403, session expired error.
I've looked up online and tried to clear my cookies before generating a new token, with the same results. However the token generated works fine with Postman and I can do get requests from there, so it doesn't seem to have anything to do with authentification/credentials/session.
Adobe helpdesk have no clue as to why this is happening either!
Here is the token I get back after identification:
{'access_token': 'some-encoded-string',
'expires_at': 1552652569.358807,
'expires_in': 3599,
'refresh_token': 'some-encoded-string',
'scope': ['read', 'write'],
'token_type': 'bearer'}
Here is the request and error:
r = requests.get('https://url-endpoint')
r : <Response [403]>
r.json()
{'code': 'ACCESS_DENIED',
'message': 'Your session has expired. Please proceed to the login page'}
I'm at a loss as to why this isn't working or even where to start!
#Devesh Kumar Singh yes that's the right idea, I forgot one step - in the end I used
client = OAuth2Session(client_id, token=token)
and from there
r = client.get('https://url-endpoint', params=params) works perfectly.

Streamlabs API 405 response code

I'm trying to use Streamlabs API. Streamlabs API uses Oauth2 for creating apps. So first I send whoever's using my app to an authorization link containing my app's client id and the scopes I want to use.
(Something like this: streamlabs.com/api/v1.0/authorize?client_id=CLIENT-ID-HERE&redirect_uri=REDIRECT-URI&response_type=code&scope=SOME+SCOPES+HERE)
Once I've done that I receive a code at the redirect uri specified. I then use that code to get the access token for permanent access to the connected user's account. I then receive the access token from a POST request that works perfectly... Now I run into the problem. When getting the temporary code before the access token I specified the scopes: "donations.read +donations.create+alerts.write+alerts.create".
When authorizing, the app asks for permission to the different scopes. The scope in focus is "alerts.write" so that I can send test alerts using POST requests. But this doesn't work for some reason. To send a test alert I have to send a POST request to this url: "https://streamlabs.com/api/alerts/send_test_alert"
I've tried doing that in two different ways.
1:
import requests
url = "https://streamlabs.com/api/alerts/send_test_alert"
data = {
"access_token":"UserAccessTokenHere",
"type":"donation"
}
response = requests.post(url=url, data=data)
print(response.text)
2:
import requests
url = "https://streamlabs.com/api/alerts/send_test_alert?access_token=UserAccessTokenHere&type=donation"
response = requests.post(url=url)
print(response.text)
If I do print(response) it prints "Response [405]".
But if I do print(response.text) I get a long HTML document for this page: Error response page
Any ideas what's going wrong with my Python requests? send_test_alert documentation here: Link
I've contacted support and looks like you've made the same error as me.
You're not actually sending a request to the right URL.
You are a sending a request to: "https://streamlabs.com/api/alerts/send_test_alert"
You should be using the URL: "https://streamlabs.com/api/v1.0/alerts/send_test_alert"

JSON-RPC - Cannot retrieve correct POST data response from a logged in site with Python Requests library

Setup: Python 2.7.10, Requests library, Windows 8.1
I am new to json-rpc and need to set up automation tests for sending POST requests and checking the response. I am having difficulty accessing the data after logging in. I need to log in to the system first with a POST request ("method": "identity.authenticate"), and then the test after that is also a POST request that should return data after I have been logged in.
The developers also gave me a Bearer token to pass in the Headers which they claimed should work across all tests, and it did seem to work when I tried it in Postman (although I did have some mixed results), but for some reason when I try to use it with my Python Requests set up, it returns an error every time. The code is below (have to change the working data to dummy data, so trying to run the below code as-is won't work, but hopefully seeing the set up can help to pinpoint what I may be doing wrong):
import requests
from pprint import pprint
base_url = "https://rpc_url.com/rpc"
custom_headers = {"Content-Type":"application/json", "Authorization":"Bearer token"}
'''Sign in payload'''
signinPayload = {"method" : "identity.authenticate",
"id" : 1,
"jsonrpc" : "2.0",
"params" : {"password" : "password", "username" : "username"}}
test1_Payload = {"jsonrpc" : "2.0",
"method" : "fc.pick.getPendingPicks",
"id" : 20, "params" :{"_tags" :{"device" : "device",
"deviceOS" : "deviceOS", "firstName" : "firstName",
"devicetype" : "devicetype", "appVersion" : "appVersion",
"login" : "username", "devicelabel" : "devicelabel",
"lastName" : "lastName"}}}
with requests.Session() as s:
# below passes the login payload, which returns proper data.
login_post = s.post(base_url, json=signinPayload, headers=custom_headers).json()
pprint(login_post)
###########################
# passes the test payload, which doesn't work correctly
r = s.post(base_url, json=test1_Payload, headers=custom_headers).json()
pprint(r)
I've tried many variations, such as not passing the Bearer token in the headers, only passing the Bearer token and not the signin payload, and nothing has worked so far.
When I run the above code with non-dummy data, this is the console output (with my added comments for clarity):
# Below is returned for sign in authenticate, which appears to be good data
{u'fcFlingVersion': u'1.0.9',
u'id': 1, u'jsonrpc':
u'2.0',
u'result': {
u'_idp': {u'accessToken': 'accessTokenNumber'},
u'administratorId': 1,
u'changePassword': False,
u'companyId': 1,
u'daysUntilPasswordExpires': 100,
u'firstname': u'firstName',
u'groupList': u'groupList',
u'lastname': u'lastName',
u'login': u'username',
u'passwordDirectory': u'identity',
u'photoUrl': u'https://photoURL',
u'roles': [],
u'userId': 1,
u'username': u'username'}}
# Below is the returned error data for test1_Payload after the successful sign in test from above.
{u'error': {u'code': 404, u'data': None, u'message': u'module not found'},
u'fcFlingVersion': u'1.0.9',
u'id': 20,
u'jsonrpc': u'2.0'}
The issue is the error with the "module not found" response, where it should be returning relevant data for that request.
On non-rpc HTTPS sites I've used POST data to log into a site as I am doing above, and then ran through a for loop of URLs as GET requests to check data is being returned properly in that logged in site, so I'm not sure if it's because I have to send POST requests here to retrieve the test responses. If anybody has any helpful hints, I would greatly appreciate it.
I finally found out the issue was due to a recent URL change in the API that I was not informed about, which explains why the URL originally worked in Postman.
To make it more confusing, the URL for only some of the methods were changed, which is why the login identity.authenticate POST worked, as it was still using the original URL. For the other POST commands, the methods/modules were no longer present with the original URL, hence the error message "module not found."
Once I updated the base_url variable with the new base_url for the payloads that were receiving the error message, they returned the proper data.
Hopefully this can help others, in the event they run into something similar.
To sum up: the code works fine, it was the data that was being input into the code that was flawed and why the error message was being received. In this case, the data that was flawed was the base_url variable was pointing to an outdated URL.

Invalid response (404) with Twitter API in Python (and in general)

tl;dr:
I am trying to set headers in a Python HTTP request for the first time and am getting a 404. I would appreciate any help (see bottom).
I have been experimenting with the Twitter API and have not been having much luck. Eventually I am trying to get all of the media (photos) a user has posted (20 or 50 or whatever per fetch)
In my experience with other APIs, this process would go as follows: Get The userID, Make a get request to some endpoint using that userId, get a JSON feed response.
It seems to be much more complicated in Twitter.
For instance, I do not see any URLs where I can attach an access token or client ID. Instead, in their documentation they show a place where I can retrieve my
Comsumer Key, Consumer Secret, Access Token, and, Access Token Secret
If I enter my request URI and "query", it generates an oAuth Signature, which in this case consists of a
Signature base string, Authorization header and cURL command
This is where things get confusing. It says
Important: This will only be valid for a few minutes. Also remember the cURL command will actually execute the request.
So:
Question 1: right away I am wondering how I can use these credentials to retrieve media over an entire day or a weekend if they become invalid only a few minutes later?
Question 2: Using their "exploring API" console, I can test this query (where I am trying to get the user ID for the Ford" twitter account I use GET https://api.twitter.com/1.1/users/lookup.json?screen_name=hyundai
Typing that into the browser alone returns a 404
{"errors": [{"message": "Bad Authentication data","code": 215}]}
But using their little console APP I can pick "O Auth 1 authentication" (using a twitter app I made) and I get the JSON response I want. Examining the request object in the console shows:
GET /1.1/users/lookup.json?screen_name=hyundai HTTP/1.1
Authorization:
OAuth oauth_consumer_key="555SECRET555",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1421370510",oauth_nonce="1869828628",oauth_version="1.0",oauth_token="333DONTHACKMEPLEASE333",oauth_signature="444SECRET444"
Host:
api.twitter.com
X-Target-URI:
https://api.twitter.com
Connection:
Keep-Alive
tl;dr Version:
So, I thought this was the headers object I would need to send from Python (3) to make the identical request. So here is that code:
import urllib.request
header = {
"Authorization" : "OAuth",
"oauth_consumer_key" :"555SECRET555",
"oauth_signature_method": "HMAC-SHA1",
"oauth_timestamp" : "1421362844",
"oauth_nonce":"1201915763",
"oauth_version": "1.0",
"oauth_token":"333CHANGINGTHIS33333",
"oauth_signature":"222CHANGEDTHIS222",
"Host": "api.twitter.com",
"X-Target-URI": "https://api.twitter.com",
"Connection": "Keep-Alive"
}
endpoint = 'https://api.twitter.com/1.1/users/lookup.json?screen_name=hyundai'
q = urllib.request.Request(endpoint, headers=header)
a = urllib.request.urlopen(q)
print(a.read().decode('utf-8'))
But I get a bad, 404 response.
Have I formatted my headers wrong here or is there another way to do this?
If you capture the network traffic from your request (use http not https), you will see that the headers you send are not the same as the header that are expected. This is why you are getting a 404 response.
What you want is something like
header = {
"Authorization": 'OAuth oauth_consumer_key="555SECRET555",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1421362844",oauth_nonce="1201915763",oauth_version="1.0",oauth_token="333CHANGINGTHIS33333",oauth_signature="222CHANGEDTHIS222"',
"Host": "api.twitter.com",
"X-Target-URI": "https://api.twitter.com",
"Connection": "Keep-Alive"
}
Of course, you could always use an OAuth library, such as RAuth or similar, see
Python: OAuth Library for a discussion

Categories