Python: Facebook API showing invalid token - python

I am using facepy facebook graph API to access my mailbox/messages and I followed the following two approaches:
1st Approach:
I used the access token I got from Graph Explorer facebook page and use the below code:
from facepy import GraphAPI
graph = GraphAPI(token)
print graph.get('/me')
#Rest of the code
The above code worked fine and I was able to retrieve all my messages using an FQL Query. The problem arised when my auth_token expired after sometime.
So, after some googling I shifted to approach two:
Now, what I did was created a facebook app gave it read_mailbox permission and got it's id and key and then used get_application_access_token method of facepy to get the token.
After retrieving the token I used:
token = facepy.utils.get_application_access_token(app_id, key)
graph.get('/me')
## OUT: OAuthError: [2500] An active access token must be used to query information about the current user.
facepy.utils.get_extended_access_token(token, app_id, key)
# OUT: OAuthError: [1] No user access token specified
Now, you can see the error(commented #) generated on using the application token.
I believe the error I am getting is because facebook needs the user_token and I am supplying it with app_token.
So, is it possible to access user data using the app_token and if not how can one issue a extended token which can access user data.
Update:
So, I followed #Johannes suggestion and tried this but ran into error:
from facepy.utils import get_extended_access_token
from facepy import GraphAPI
token = "My user access token got from https://developers.facebook.com/tools/explorer"
long_lived_access_token = get_extended_access_token(token)
graph = GraphAPI(long_lived_access_token)
graph.get('/me')
Now, when I ran the above code I got
TypeError: get_extended_access_token() takes exactly 3 arguments (1 given)
So, I changed it to long_lived_access_token = get_extended_access_token(token, None, None) and got
facepy.exceptions.OAuthError
So, I again I changed it to long_lived_access_token = get_extended_access_token(token, app_id, key) and I got the same exception/error as above.
So, is this a bug or am I doing something wrong.
PS: I installed the latest version from git.

You're right in your assumption that you cannot use application access tokens to read a user's mailbox, but the error you're getting stems from the fact that you haven't initialized graph with an access token at all.
Be that as it may, you're on the right track in asking for how you can extend the user's access token. As you have already discovered, Facepy HEAD (soon to be version 0.9) has a function get_extended_access_token which accepts an existing short-lived user access token and extends it. Extended user access tokens last for 2 months, and you can read more about them in Facebook's documentation on the removal of offline_access permission.
If you want to use get_extended_access_token right now, you will have to install facepy from git:
$ pip install git+git://github.com/jgorset/facepy.git#b5153f460f2f52cef9a5e49a3b48b3fb8742356c
Once you've installed the right version of Facepy, you can extend an existing short-lived user access token and initialize a new instance of GraphAPI with it:
from facepy.utils import get_extended_access_token
from facepy import GraphAPI
long_lived_access_token, expires_at = get_extended_access_token(short_lived_access_token, application_id, application_secret_key)
graph = GraphAPI(long_lived_access_token)
graph.get('/me')

There is nothing wrong with the API you are just not interpreting the result in a right way.
If you try to print the result of long_lived_access_token = get_extended_access_token(token) it will not directly give you a long_lived_access_token instead it will provide you a tuple with contents:
long_lived_access_token = ('your token', datetime_object).
You can verify this by looking at the source code of utils.py. If you look at get_extended_access_token method it returns token, expires_at.
According to the facebook docs to get the extended access token one has to make request at the below endpoint
https://graph.facebook.com/oauth/access_token?
client_id=APP_ID&
client_secret=APP_SECRET&
grant_type=fb_exchange_token&
fb_exchange_token=EXISTING_ACCESS_TOKEN
and the response is something like token=mytoken&expire=5184000 where 5184000 means 60 days.
So, your final code will look something like:
from facepy.utils import get_extended_access_token
from facepy import GraphAPI
app_id = 'id'
key = 'key'
short_lived_access_token = 'short_token'
long_token = get_extended_access_token(short_token, id, key)
graph = GraphAPI(long_token[0])
print graph.get('/me')

Related

Blob.generate_signed_url() failing to AttributeError

So I'm trying to produce temporary globally readable URLs for my Google Cloud Storage objects using the google-cloud-storage Python library (https://googlecloudplatform.github.io/google-cloud-python/latest/storage/blobs.html) - more specifically the Blob.generate_signed_url() method. I doing this from within a Compute Engine instance in a command line Python script. And I keep getting the following error:
AttributeError: you need a private key to sign credentials.the credentials you are currently using <class 'oauth2cl
ient.service_account.ServiceAccountCredentials'> just contains a token. see https://google-cloud-python.readthedocs
.io/en/latest/core/auth.html?highlight=authentication#setting-up-a-service-account for more details.
I am aware that there are issues with doing this from within GCE (https://github.com/GoogleCloudPlatform/google-auth-library-python/issues/50) but I have created a new Service Account credentials following the instructions here: https://cloud.google.com/storage/docs/access-control/create-signed-urls-program and my key.json file most certainly includes a private key. Still I am seeing that error.
This is my code:
keyfile = "/path/to/my/key.json"
credentials = ServiceAccountCredentials.from_json_keyfile_name(keyfile)
expiration = timedelta(3) # valid for 3 days
url = blob.generate_signed_url(expiration, method="GET",
credentials=credentials)
I've read through the issue tracker here https://github.com/GoogleCloudPlatform/google-cloud-python/issues?page=2&q=is%3Aissue+is%3Aopen and nothing related jumps out so I am assuming this should work. Cannot see what's going wrong here.
I was having the same issue. Ended up fixing it by starting the storage client directly from the service account json.
storage_client = storage.Client.from_service_account_json('path_to_service_account_key.json')
I know I'm late to the party but hopefully this helps!
Currently, it's not possible to use blob.generate_signed_url without explicitly referencing credentials. (Source: Google-Cloud-Python documentation) However, you can do a workaround, as seen here, which consists of:
signing_credentials = compute_engine.IDTokenCredentials(
auth_request,
"",
service_account_email=credentials.service_account_email
)
signed_url = signed_blob_path.generate_signed_url(
expires_at_ms,
credentials=signing_credentials,
version="v4"
)
A much complete snippet for those asking where other elements come from. cc #AlbertoVitoriano
from google.auth.transport import requests
from google.auth import default, compute_engine
credentials, _ = default()
# then within your abstraction
auth_request = requests.Request()
credentials.refresh(auth_request)
signing_credentials = compute_engine.IDTokenCredentials(
auth_request,
"",
service_account_email=credentials.service_account_email
)
signed_url = signed_blob_path.generate_signed_url(
expires_at_ms,
credentials=signing_credentials,
version="v4"
)

Firebase admin SDK Python - cannot verify custom tokens

I'm trying to play with the firebase admin sdk for python for making custom tokens and verify those while testing my app. Problem is that while I try to verify the token I always get such an error:
ValueError: Firebase ID token has incorrect "aud" (audience) claim. Expected "my_project_id" but got "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit". Make sure the ID token comes from the same Firebase project as the service account used to authenticate this SDK. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
I followed the guide to create the app and making the tokens:
import firebase_admin
from firebase_admin import auth, credentials
cred = credentials.Certificate('/path/to/file.json')
app = firebase_admin.initialize(cred)
custom_token = auth.create_custom_token('some-uid', app=app)
auth.verify_id_token(custom_token, app=app)
and here I get the error. It seems that _TokenGenarator is initialised with the defaults that are coming back from the error. I thought when passing the app it should automatically change those but it's not happening. Am I missing something?
verify_id_token() only accepts ID tokens. Custom tokens do not fall into that category. See this test case. Raising a ValueError is the expected behavior in this case.
ID tokens can be obtained from a client SDK. You can exchange a custom token for an ID token by calling one of the provided signInWithCustomToken() methods.

How to get Salesforce username using REST api?

I am using web server flow for oAuth and simple-salesforce REST api to login the user using the access token and instance url. I have gone through the http://www.salesforce.com/us/developer/docs/api_rest/index.htm documentation and coudn't find anything on it.
Based on your comment saying you're using https://github.com/neworganizing/salesforce-oauth2 : you can do something like :
import urllib
# After you get the code
response = salesforce_oauth_2.get_token(code)
print urllib.urlopen(response['id'])
The json object response returned by get_token should contain an id attribute which is an url that you can query for more information about the current user. See here for more details (paragraph 5).
Get your salesforce dev to write a simple method that when pinged returns the context user details that you're after. See here for an example.

Posting to Facebook App page wall as the App Page in python

I am trying make a post on my apps page wall as if it is coming from the app page (not another user) After researching I seem to find no solution that actually works!
I have tried to follow the documentation here:
I then get my 'access_token_page' by getting it from:
https://graph.facebook.com/oauth/access_token?client_id=APP_ID&client_secret=CLIENT_SECRET&grant_type=client_credentials
Then using the facebook python api I try:
graph1 = facebook.GraphAPI(access_token_page)
graph1.put_wall_post(fbmessage, attachment, profile_id=APP_PAGE_ID)
However this just returns the following facebook error:
*** GraphAPIError: (#200) The user hasn't authorized the application to perform this action
Any ideas on what I am missing? Remember, I am looking to have the App Page make a post to itself, not have a post be generated from another username.
Thank you!
What you had done is using App Access Token to publish to page.
You should using Page Access Token to post on page admin behalf instead. User Access Token is works too but it's a bug as reported at https://developers.facebook.com/bugs/647340981958249, so it's not recommended to use User Access Token by this time of writing.
As documented at https://developers.facebook.com/docs/reference/api/page/#page_access_tokens:
Page Access Tokens
To perform the following operations as a Page, and not the current
user, you must use the Page's access token, not the user access token
commonly used for reading Graph API objects. This access token can be
retrieved by issuing an HTTP GET to /USER_ID/accounts with the
manage_pages permission.
More info about different type of access token please visit https://developers.facebook.com/docs/facebook-login/access-tokens/
Try Django Facebook:
https://github.com/tschellenbach/Django-facebook
This will deal with many of your API problems.
You need the page access token, see here:
https://developers.facebook.com/docs/facebook-login/access-tokens/
Ask for manage_pages as an extra permission
After getting that setup, simply do:
user_graph = OpenFacebook(user_access_token)
response = user_graph.get('me/accounts')
# turn the response to a dict, and be sure to get the page you want
page_access_token = response['data'][0]['access_token']
graph = OpenFacebook(page_access_token)
graph.set('me/feed', message='helloworld')
You can find more docs here:
http://django-facebook.readthedocs.org/en/latest/open_facebook/api.html

Programmatically getting an access token for using the Facebook Graph API

I am trying to put together a bash or python script to play with the facebook graph API. Using the API looks simple, but I'm having trouble setting up curl in my bash script to call authorize and access_token. Does anyone have a working example?
Update 2018-08-23
Since this still gets some views and upvotes I just want to mention that by now there seems to exist a maintained 3rd party SDK: https://github.com/mobolic/facebook-sdk
Better late than never, maybe others searching for that will find it. I got it working with Python 2.6 on a MacBook.
This requires you to have
the Python facebook module installed: https://github.com/pythonforfacebook/facebook-sdk,
an actual Facebook app set up
and the profile you want to post to must have granted proper permissions to allow all the different stuff like reading and writing.
You can read about the authentication stuff in the Facebook developer documentation. See https://developers.facebook.com/docs/authentication/ for details.
This blog post might also help with this: http://blog.theunical.com/facebook-integration/5-steps-to-publish-on-a-facebook-wall-using-php/
Here goes:
#!/usr/bin/python
# coding: utf-8
import facebook
import urllib
import urlparse
import subprocess
import warnings
# Hide deprecation warnings. The facebook module isn't that up-to-date (facebook.GraphAPIError).
warnings.filterwarnings('ignore', category=DeprecationWarning)
# Parameters of your app and the id of the profile you want to mess with.
FACEBOOK_APP_ID = 'XXXXXXXXXXXXXXX'
FACEBOOK_APP_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
FACEBOOK_PROFILE_ID = 'XXXXXX'
# Trying to get an access token. Very awkward.
oauth_args = dict(client_id = FACEBOOK_APP_ID,
client_secret = FACEBOOK_APP_SECRET,
grant_type = 'client_credentials')
oauth_curl_cmd = ['curl',
'https://graph.facebook.com/oauth/access_token?' + urllib.urlencode(oauth_args)]
oauth_response = subprocess.Popen(oauth_curl_cmd,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE).communicate()[0]
try:
oauth_access_token = urlparse.parse_qs(str(oauth_response))['access_token'][0]
except KeyError:
print('Unable to grab an access token!')
exit()
facebook_graph = facebook.GraphAPI(oauth_access_token)
# Try to post something on the wall.
try:
fb_response = facebook_graph.put_wall_post('Hello from Python', \
profile_id = FACEBOOK_PROFILE_ID)
print fb_response
except facebook.GraphAPIError as e:
print 'Something went wrong:', e.type, e.message
Error checking on getting the token might be better but you get the idea of what to do.
Here you go, as simple as it can get. Doesn’t require any 3rd-party SDK etc.
Make sure Python 'requests' module is installed
import requests
def get_fb_token(app_id, app_secret):
url = 'https://graph.facebook.com/oauth/access_token'
payload = {
'grant_type': 'client_credentials',
'client_id': app_id,
'client_secret': app_secret
}
response = requests.post(url, params=payload)
return response.json()['access_token']
Easy! Just use facebook-sdk.
import facebook
app_id = 'YOUR_APP_ID'
app_secret = 'YOUR_APP_SECRET'
graph = facebook.GraphAPI()
# exactly what you're after ;-)
access_token = graph.get_app_access_token(app_id, app_secret)
You first need to set up an application. The following will then spit out an access token given your application ID and secret:
> curl -F type=client_cred -F client_id=[...] -F client_secret=[...] https://graph.facebook.com/oauth/access_token
Since a web browser needs to be involved for the actual authorization, there is no such thing as a "standalone script" that does it all. If you're just playing with the API, or are writing a script to automate something yourself, and want a access_token for yourself that does not expire, you can grab one here: http://fbrell.com/auth/offline-access-token
There IS a way to do it, I've found it, but it's a lot of work and will require you to spoof a browser 100% (and you'll likely be breaking their terms of service)
Sorry I can't provide all the details, but the gist of it:
assuming you have a username/password for a facebook account, go curl for the oauth/authenticate... page. Extract any cookies returned in the "Set-Cookie" header and then follow any "Location" headers (compiling cookies along the way).
scrape the login form, preserving all fields, and submit it (setting the referer and content-type headers, and inserting your email/pass) same cookie collection from (1) required
same as (2) but now you're going to need to POST the approval form acquired after (2) was submitted, set the Referer header with thr URL where the form was acquired.
follow the redirects until it sends you back to your site, and get the "code" parameter out of that URL
Exchange the code for an access_token at the oauth endpoint
The main gotchas are cookie management and redirects. Basically, you MUST mimic a browser 100%. I think it's hackery but there is a way, it's just really hard!
s29 has the correct answer but leaves some steps to solve. The following script demonstrates a working script for acquiring an access token using the Facebook SDK:
__requires__ = ['facebook-sdk']
import os
import facebook
def get_app_access_token():
client = facebook.GraphAPI()
return client.get_app_access_token(
os.environ['FACEBOOK_APP_ID'],
os.environ['FACEBOOK_APP_SECRET'],
)
__name__ == '__main__' and print(get_app_access_token())
This script expects the FACEBOOK_APP_ID and FACEBOOK_APP_SECRET environment variables are set to the values for your app. Feel free to adapt that technique to load those values from a different source.
You must first install the Facebook SDK (pip install facebook-sdk; python get-token.py) or use another tool like rwt to invoke the script (rwt -- get-token.py).
Here is the Python Code. Try running some of these examples on command line, they work fine for me. See also — http://www.pythonforfacebook.com/

Categories