how to build a facebook signed_request string in python? - python

there is plenty of docs on how signed_request-s are build up, but could not find (and come up with) a simple method that creates a signed request
does anyone has a solution?
the basic docs are here:
I would need it for unit tests. More precisely, I'm using facebook-sdk, and just wrote a nice middleware for using facebook authentication together with tastypie. To test this I need the mock the auth process of facebook, and the last missing step is to create the cookies set in the browser when the auth happens.
The result will be open sourced.

Like following:
from hashlib import md5
def fb_signature(request, app_secret):
fb_request = dict([(k,request[k]) for k in request if k.startswith('fb_sig')])
payload = ''.join(['%s=%s' % (k[len('fb_sig_'):], fb_request[k]) \
for k in sorted(fb_request.keys()) if k != 'fb_sig' ])
return md5(payload + app_secret).hexdigest()
Here request --- your request to calculate signature, app_secret --- your FB app secret.

Related

Can Python Functions be used in Flask or Django?

I need help with a question I have in mind.I've been working on big data and machine learning lately.I'm going to do some work on twitter data first, but I don't want my work to remain only on the terminal screen.I want to see the data on the web, is it possible using flask or django?It doesn't have to be just twitter data, as I said at first, it could be any data.
For Example: I want to build a structure like this
from twython import Twython
CONSUMER_KEY = '***'
CONSUMER_SECRET = '***'
ACCESS_TOKEN = '***'
ACCESS_TOKEN_SECRET = '***'
twitter = Twython(CONSUMER_KEY, CONSUMER_SECRET,
ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
user = twitter.get_user_timeline(screen='jack')
print(user[0]['user']['friends_count'])
print(user[0]['user']['statuses_count'])
print(user[0]['user']['favourites_count'])
How do I use this code structure in django or flask? If I write this in a class, if I call it in django or flask, do I do a proper job?
Short answer yes, all kind of python function will work.
Flask and Django will help you to create either API or web interface. For this, you need a web server. Here are things that you need to look while using your any function in these frameworks.
Install a web server
Install Django or Flask
Integrate Web server with installed application
Define Entry point for your request. ex www.abc.com/landing_page for this you need to create a host on your system www.abc.com when this points to your application then define a route landing_page so it will handle the incoming request.
Then check how Django and Flask handle these request and define request handler
After handling these request finally call your function in the request handler
Final if API return response in JSON, TEXT or any other format else showing web page then call desired template and display page.

401 Unauthorized making REST Call to Azure API App using Bearer token

I created 2 applications in my Azure directory, 1 for my API Server and one for my API client. I am using the Python ADAL Library and can successfully obtain a token using the following code:
tenant_id = "abc123-abc123-abc123"
context = adal.AuthenticationContext('https://login.microsoftonline.com/' + tenant_id)
token = context.acquire_token_with_username_password(
'https://myapiserver.azurewebsites.net/',
'myuser',
'mypassword',
'my_apiclient_client_id'
)
I then try to send a request to my API app using the following method but keep getting 'unauthorized':
at = token['accessToken']
id_token = "Bearer {0}".format(at)
response = requests.get('https://myapiserver.azurewebsites.net/', headers={"Authorization": id_token})
I am able to successfully login using myuser/mypass from the loginurl. I have also given the client app access to the server app in Azure AD.
Although the question was posted a long time ago, I'll try to provide an answer. I stumbled across the question because we had the exact same problem here. We could successfully obtain a token with the adal library but then we were not able to access the resource I obtained the token for.
To make things worse, we sat up a simple console app in .Net, used the exact same parameters, and it was working. We could also copy the token obtained through the .Net app and use it in our Python request and it worked (this one is kind of obvious, but made us confident that the problem was not related to how I assemble the request).
The source of the problem was in the end in the oauth2_client of the adal python package. When I compared the actual HTTP requests sent by the .Net and the python app, a subtle difference was that the python app sent a POST request explicitly asking for api-version=1.0.
POST https://login.microsoftonline.com/common//oauth2/token?api-version=1.0
Once I changed the following line in oauth2_client.py in the adal library, I could access my resource.
Changed
return urlparse('{}?{}'.format(self._token_endpoint, urlencode(parameters)))
in the method _create_token_url, to
return urlparse(self._token_endpoint)
We are working on a pull request to patch the library in github.
For the current release of Azure Python SDK, it support authentication with a service principal. It does not support authentication using an ADAL library yet. Maybe it will in future releases.
See https://azure-sdk-for-python.readthedocs.io/en/latest/resourcemanagement.html#authentication for details.
See also Azure Active Directory Authentication Libraries for the platforms ADAL is available on.
#Derek,
Could you set your Issue URL on Azure Portal? If I set the wrong Issue URL, I could get the same error with you. It seems that your code is right.
Base on my experience, you need add your application into Azure AD and get a client ID.(I am sure you have done this.) And then you can get the tenant ID and input into Issue URL textbox on Azure portal.
NOTE:
On old portal(manage.windowsazure.com),in the bottom command bar, click View Endpoints, and then copy the Federation Metadata Document URL and download that document or navigate to it in a browser.
Within the root EntityDescriptor element, there should be an entityID attribute of the form https://sts.windows.net/ followed by a GUID specific to your tenant (called a "tenant ID"). Copy this value - it will serve as your Issuer URL. You will configure your application to use this later.
My demo is as following:
import adal
import requests
TenantURL='https://login.microsoftonline.com/*******'
context = adal.AuthenticationContext(TenantURL)
RESOURCE = 'http://wi****.azurewebsites.net'
ClientID='****'
ClientSect='7****'
token_response = context.acquire_token_with_client_credentials(
RESOURCE,
ClientID,
ClientSect
)
access_token = token_response.get('accessToken')
print(access_token)
id_token = "Bearer {0}".format(access_token)
response = requests.get(RESOURCE, headers={"Authorization": id_token})
print(response)
Please try to modified it. Any updates, please let me know.

Flask-Stormpath Token based authentication

I am trying to implement token based authentication for my Flask REST API. I am using Stormpath as my third-party authentication service.
I looked into flask-stormpath built on top of flask-login. Looks like it uses password based authentication as they are trying to maintain session on the server. Also, the documentation doesn't provide me enough information.
Do we have a flask integration for stormpath token based authentication ?
If yes, can someone point me to a sample code.
I have already gone through the stormpath/flask-stormpath-sample on github, which again maintains sessions in server.
References:
https://stormpath.com,
https://github.com/stormpath/stormpath-flask
So here is the way I am currently using until rdegges shall build this feature into flask-stormpath.
You will need stormpath python sdk latest version and wraps from func tools.
from stormpath.api_auth import (PasswordGrantAuthenticator, RefreshGrantAuthenticator, JwtAuthenticator)
from functools import wraps
You can create your application as such.
stormpathClient = Client(id=KEYS['STORMPATH_ID'], secret=KEYS['STORMPATH_SECRET'])
stormpathApp = stormpathClient.applications.search('your-application')[0]
This decorator shall help you with securing endpoints.
def tokenRequired(func):
"""
Decorator to apply on all routes which require tokens.
"""
#wraps(func)
def wrappingFunc():
#check the auth header of the request for a bearer token.
authHeader = request.headers.get('Authentication')
#make sure that the string is a bearer type.
if len(authHeader)<8 or (not authHeader[:7] == 'Bearer ') or (
not authHeader):
return Response("401 Unauthorized",401)
authToken = authHeader[7:]
try:
authenticator = JwtAuthenticator(stormpathApp)
authResult = authenticator.authenticate(authToken)
request.vUser = authResult.account
except:
return Response("403 Forbidden",403)
return func()
return wrappingFunc
#Use this decorator like below.
#flaskApp.route('/secure-route',methods=['GET','POST'])
#tokenRequired
def secureEndpoint():
# return JSON based response
return Response("This is secure Mr." + request.vUser.given_name ,200)
Let me know in the comments if someone wishes to know the token issuing and refreshing end points as well.
I'm the author of the Flask-Stormpath library. The answer is no. I'm actually working on a new release of the library (coming out in a month or so) that will provide this functionality by default, but right now it only supports session based authentication.

How to generate the X-PAYPAL-AUTHORIZATION header in Paypal with the Access Token once third-party permissions are granted?

After being granted third-party permissions by obtaining the Access Token (token:xxxxxx and tokenSecret:xxxxxxx) using the Paypal's Permissions API as per https://developer.paypal.com/webapps/developer/docs/classic/permissions-service/ht_permissions-invoice/, I am not having success in following up with other API calls on behalf of the third-party as it is not clear how the X-PAYPAL-AUTHORIZATION header should be generated.
Based on sample node.js code written in another SO question: Generating Authentication Header, I have done a Python port
from hashlib import sha1
import hmac
from base64 import b64encode
from urllib import urlencode
from datetime import datetime
def paypal_urlencode(s):
encode = lambda x: x if x in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_+" else '%%%x' % ord(x)
return ''.join(map(encode, s.replace(' ','+')))
def paypal_authorisation(token, ep, consumer, method="POST", sandbox=True):
params = dict(
oauth_consumer_key=consumer['key'],
oauth_version='1.0',
oauth_signature_method="HMAC-SHA1",
oauth_token=token['key'],
oauth_timestamp=datetime.now().strftime('%s')
)
key = "&".join((paypal_urlencode(consumer['secret']), paypal_urlencode(token['secret'])))
sig_base = "&".join((method, paypal_urlencode(ep), paypal_urlencode("oauth_consumer_key=%(oauth_consumer_key)s&oauth_signature_method=%(oauth_signature_method)s&oauth_timestamp=%(oauth_timestamp)s&oauth_token=%(oauth_token)s&oauth_version=%(oauth_version)s" % params)))
h= hmac.new(key.encode('ascii'), sig_base.encode('ascii'), sha1)
signature=b64encode(h.digest())
return "token=%s,signature=%s,timestamp=%s" % (token['key'], signature, params['oauth_timestamp'])
However, I am getting an authentication error code 10002. Appreciate any suggestions in debugging this. Note that the Access Token was successfully received.
From the PayPal Developer documentation:
PayPal API Error Codes
Error Code 1000:
This error can be caused by an incorrect API username, an incorrect API password, or an invalid API signature. Make sure that all three of these values are correct. For your security, PayPal does not report exactly which of these three values might be in error.
Make certain that you are using the correct credentials (client id, client secret must be included). If you are in sandbox mode you need to make certain that the credentials you are using are from a business Pro Sandbox Account. If you are in live mode, make certain you are using your live PayPal Credentials.
This sample comes directly from the PayPal Developer site:
Complete Integration Guide for Rest API
Request Sample
curl https://api.sandbox.paypal.com/v1/oauth2/token \
-H "Accept: application/json" \
-H "Accept-Language: en_US" \
-u "<Client-Id>:<Secret>" \
-d "grant_type=client_credentials"
For Rest API here are the authentication and headers you should be using:
Authentication and Headers Rest API
Client Credentials are found in the Rest API Application you submitted on the PayPal Developer Site.
Just in case you need it, here is the link to making your first API call it includes creating a Rest API Application:
PayPal Rest API Making your first call

Understanding "runwithfriends" facebook-app sample code

this is my first web-programming experience so I hope my questions doesn't sound very dumb. I have been stucked on this for many days.
I am trying to understand a sample code:
https://github.com/facebook/runwithfriends
However I am not understanding very well how the information flow works and how can I modify that sample (i.e. how the code works).
For example, in the following section of the code:
class RecentRunsHandler(BaseHandler):
"""Show recent runs for the user and friends"""
def get(self):
if self.user:
friends = {}
for friend in select_random(
User.get_by_key_name(self.user.friends), 30):
friends[friend.user_id] = friend
self.render(u'runs',
friends=friends,
user_recent_runs=Run.find_by_user_ids(
[self.user.user_id], limit=5),
friends_runs=Run.find_by_user_ids(friends.keys()),
)
else:
self.render(u'welcome')
As I understand (along with HTML) is useful for showing friends that are using the same app, and if I understand correctly, here is the essential part:
*friends_runs=Run.find_by_user_ids(friends.keys())*
But what if I want to show any given friend. How can I do it?
Summarizing, I would like to know:
1- How the flow of the code works? (I don't fully understand the explanation here)
2- How can I manipulate the code so to get, for example, to show a list of friends of the user (not necessary that use the same app)?
Moreover, Can I show friends filtered by some characteristic (for example, gender)?
Thanks a lot!
The python "SDK" for facebook I use I took from https://gist.github.com/1190267
and combined it with the code from the example app to achieve the functionality I wanted both for a canvas app and for website usage.
It depends whether you're using facebook with websites or a canvas application. For a canvas application you probably could do well with the javascript SDK but for a "login with facebook" I required serverside logic that should work with javascript turned off so I've completed that solution with details you might have help to know. You can try make small changes of that specific app 'runwithfriends' to get an understanding which code does what. The project you're looking at contains some outdated practice though:
getting and setting cookies is likely preferable now doing with webapp2's builtin functions for this instead of the code that comes with the FB example app
logging in and out is now done with OAuth 2.0 so it's likely that the login system you're looking at is outdated and you need to use OAuth 2.0 which is described here. I much rather do login/logout serverside so I did an OAuth 2.0 pure python solution to login / logout following the authentication steps mentioned in the tutorial from FB. I had to clear the cookie to log a user out which was not documented.
To upgrade to python 2.7 I had to also modify so that HTTP header did not cast to unicode. I don't know why but otherwise it complained that headers were "not strings"
To more elaborately answer your specific questions:
1) The requesthandler class you posted is a subclass of a BaseHandler so to fully understand what it does you can look at the BaseHandler class since what you are posting is a BAseHandler. The BaseHandler uses django templates for rendering and if you want to can switch the template engine to jinja2 which is remmended. Further the code accesses the user object inherited from the BaseHandler and does some operations on it and renders it to a template. You can try make a requesthandler of your own, subclass BaseHandler and do what you want.
2) I could manipulate the code and I'm not an expert so you should be able to do it too. I wanted a simple FB app to display random images and I could manipulate it to select random images via blobs and render to to a template while keeping the facebook base functions. A function to use for getting the user using the Graph API I do this:
def parse_signed_request(signed_request, secret):
"""
Parse signed_request given by Facebook (usually via POST),
decrypt with app secret.
Arguments:
signed_request -- Facebook's signed request given through POST
secret -- Application's app_secret required to decrpyt signed_request
"""
if '.' in signed_request:
(esig, payload) = signed_request.split('.')
else:
return {}
sig = urlsafe_b64decode(str(esig))
data = _parse_json(urlsafe_b64decode(str(payload)))
if not isinstance(data, dict):
raise SignedRequestError('Pyload is not a json string!')
return {}
if data['algorithm'].upper() == 'HMAC-SHA256':
if hmac.new(secret, payload, hashlib.sha256).digest() == sig:
return data
else:
raise SignedRequestError('Not HMAC-SHA256 encrypted!')
return {}
def get_user_from_cookie(cookies, app_id, app_secret):
"""Parses the cookie set by the official Facebook JavaScript SDK.
cookies should be a dictionary-like object mapping cookie names to
cookie values.
If the user is logged in via Facebook, we return a dictionary with the
keys "uid" and "access_token". The former is the user's Facebook ID,
and the latter can be used to make authenticated requests to the Graph API.
If the user is not logged in, we return None.
Download the official Facebook JavaScript SDK at
http://github.com/facebook/connect-js/. Read more about Facebook
authentication at http://developers.facebook.com/docs/authentication/.
"""
cookie = cookies.get('fbsr_' + app_id, '')
if not cookie:
return None
response = parse_signed_request(cookie, app_secret)
if not response:
return None
args = dict(code=response['code'], client_id=app_id,
client_secret=app_secret, redirect_uri='')
file = \
urllib.urlopen('https://graph.facebook.com/oauth/access_token?'
+ urllib.urlencode(args))
try:
token_response = file.read()
finally:
file.close()
access_token = cgi.parse_qs(token_response)['access_token'][-1]
logging.debug('returning cookie')
return dict(uid=response['user_id'], access_token=access_token)
See http://developers.facebook.com/docs/api for complete documentation for the API. And you can get the the official Facebook JavaScript SDK at http://github.com/facebook/connect-js/
I'm now writing code to sync a webapp2_extras.auth account with facebook so that custom accounts and facebook accounts can co-exist and we're discussing solutions for this in the webapp2 groups and categories. The current way I do it is adding the recommended current_user to a basehandler and using that as the FB identity while working on "merging" my class FBUser that is a custom class for facebook users that autheorized my website and/or canvas application to sync with webapp2_extras.auth.models.User which is an expando model so it can just add the properties it doesn't have such as facebookid, firstname, lastname, etc.
#property
def current_user(self):
if not hasattr(self, '_current_user'):
self._current_user = None
cookie = get_user_from_cookie(self.request.cookies,
facebookconf.FACEBOOK_APP_ID,
facebookconf.FACEBOOK_APP_SECRET)
if cookie:
# Store a local instance of the user data so we don't need
# a round-trip to Facebook on every request
user = FBUser.get_by_key_name(cookie['uid'])
if not user:
graph = GraphAPI(cookie['access_token'])
profile = graph.get_object('me')
user = FBUser(key_name=str(profile['id']),
id=str(profile['id']),
name=profile['name'],
profile_url=profile['link'],
access_token=cookie['access_token'])
user.put()
elif user.access_token != cookie['access_token']:
user.access_token = cookie['access_token']
user.put()
self._current_user = user
return self._current_user
You can also solve your authentication with session objects and build your authentication system around that. That is what I do when using both custom accounts and facebook accounts and you're welcome to have a lok at my repository for more code examples how to intregrate facebook with google app engine using python 2.7.

Categories

Resources