[PYTHON] Create a filter to get an Access Token in the Graph API (Flask)

Introduction

I have investigated how to use the Graph API when creating an app that uses Facebook friend information in Python, so I will summarize it. It is intended for applications that use Flask.

Get an authorization code

If you redirect to https://graph.facebook.com/oauth/authorize?client_id=****&redirect_uri=****&scope=**** and the app is not allowed, app allow Page is displayed. In Flask, you can specify this URL and do return redirect (https: // ****).

Parameters Settings
client_id Application ID set in Facebook Developers
redirect_uri URL to redirect after authentication(URI encoding required)
scope Permission to request

If allowed, it will transition to the redirect destination set in redirect_uri. The code (authentication code) returned as a parameter at this time will be used for the next access token acquisition. Also, if any error occurs, the JSON string with ʻerror` set as shown below will be returned.

error_sample


{
    "error": {
        "message": "redirect_uri isn't an absolute URI. Check RFC 3986.",
        "type": "OAuthException",
        "code": 191,
        "fbtrace_id": "XXXXXXXXXXX"
    }
}

Get an access token

Use the verification code obtained above to go to https://graph.facebook.com/oauth/access_token?client_id=****&client_secret=****&redirect_uri=****&code=**** Access and get an access token.

Parameters Settings
client_id Application ID set in Facebook Developers
client_secret App secret key set in Facebook Developers
redirect_uri URL to redirect after authentication
code Authentication code obtained above(URI encoding required)

Since the acquired data is in the form of ʻaccess_token =**** & expires =****, the value immediately after ʻaccess_token = is fetched. In Python, it's a good idea to use something like ʻurllib2.urlopen` to get the results. The method of extraction is appropriate.

main.py


from werkzeug.urls import url_quote_plus
import urllib2

...

app_id = "xxxxxxxx"
app_secret = "xxxxxxxx"
url_redirect = url_quote_plus( "https://hogehoge.com" )
code = "xxxxxxxx"

url_token = ( "https://graph.facebook.com/oauth/access_token"
              "?client_id={0}&client_secret={1}"
              "&redirect_uri={2}&code={3}" )

try:
    resp = urllib2.urlopen( url_token.format( app_id, app_secret, url_redirect, code ) )
    data = resp.read().split('&')
    access_token = data[0].strip('access_token=')

finally:
    resp.close()

...

You have now obtained an access token.

Make it a Flask filter

It's a Flask filter that automatically gets an access token when you visit a particular page. (In the sample below, the processing when an error is returned is omitted.) By the way, is Python a decorator for such a filter? Is that so? I'm still not sure about this area.

main.py


from werkzeug.urls import url_quote_plus
from functools import wraps
from flask import Flask, request, redirect, session
import urllib2

...

domain = "https://hogehoge.com"
app_id = "xxxxxxxx"
app_secret = "xxxxxxxx"

#Generate a URL for obtaining the verification code--------------------------------------------------
def create_url_for_auth_code( path_orig ):
    url_orig = url_quote_plus( domain + path_orig )
    return ( "https://graph.facebook.com/oauth/authorize"
             "?client_id={0}&redirect_uri={1}&scope={2}" )

#Get an access token--------------------------------------------------
def get_access_token( path_orig, code ):
    url_orig = url_quote_plus( domain + path_orig )
    url_token = ( "https://graph.facebook.com/oauth/access_token"
                  "?client_id={0}&client_secret={1}"
                  "&redirect_uri={2}&code={3}" )

    try:
        resp = urllib2.urlopen(url_token.format(app_id, app_secret, url_orig, code))
        data = resp.read().split('&')
        access_token = data[0].strip('access_token=')
    finally:
        resp.close()

    return access_token

#Filter body--------------------------------------------------
def oauth_filter(f):

    @wraps(f)
    def wrapper(*args, **kwargs):
        #If the session has an access token, return as it is
        if session.has_key('access_token'):
            return f(*args, **kwargs)

        #If the session does not have an access token, get it by oauth authentication
        code = request.args.get('code')

        #Case classification according to the state of request parameters
        if code is None:
            #Get the code if no authorization code has been set
            return redirect( create_url_for_auth_code( request.path ) )

        else:
            #Get an access token if an authorization code is set
            session['access_token'] = get_access_token( request.path, code )
            return redirect( domain + request.path )

        #If the conditions are not met, exit as is
        return f(*args, **kwargs)

    return wrapper

...

Apply to each routing

Apply the above filter. That said, just add @oauth_filter to the method that specifies each routing.

main.py


from flask import Flask, render_template, redirect, session
app = Flask(__name__)

...

#Does not apply to top page
@app.route('/')
def index():
    return render_template("top.html")

#Applies to My Page
@app.route('/mypage')
@oauth_filter #Application! !!
def mypage():
    return render_template("mypage.html")

#Remove access token from session when logging out
@app.route('/logout')
def logout():
    if session.has_key( 'access_token' ):
        del session['access_token']
    return redirect( '/' )

...

in conclusion

With the above, it should work for the time being. This information was created based on a PHP sample using the Graph API below and a description of the Python login decorator.

reference

Recommended Posts

Create a filter to get an Access Token in the Graph API (Flask)
Get an access token for the Pocket API
Create a function to get the contents of the database in Go
How to create a Rest Api in Django
Create a command to get the work log
I want to create an API that returns a model with a recursive relationship in the Django REST Framework
How to get the last (last) value in a list in Python
An introduction to the modern socket API to learn in C
I tried to create a Python script to get the value of a cell in Microsoft Excel
Create a CSV reader in Flask
Access the Twitter API in Python
An easy way to hit the Amazon Product API in Python
Create an alias for Route53 to CloudFront with the AWS API
How to get all the possible values in a regular expression
Grant an access token with the curl command and POST the API
Hit the New Relic API in Python to get the server status
How to get the vertex coordinates of a feature in ArcPy
Get the formula in an excel file as a string in Python
Create a REST API to operate dynamodb with the Django REST Framework
How to get rid of the "Tags must be an array of hashes." Error in the qiita api
I want to create a graph with wavy lines omitted in the middle with matplotlib (I want to manipulate the impression)
Get an access token by OAuth authentication
Get the longest character length contained in an interval in a segment tree
Create a graph using the Sympy module
[Linux] Command to get a list of commands executed in the past
How to get a stacktrace in python
Sample code to get the Twitter API oauth_token and oauth_token_secret in Python 2.7
Create an application using the Spotify API
Get a token for conoha in python
[Python] Quickly create an API with Flask
Create a simple app that incorporates the Fetch API of Ajax requests in Flask and explain it quickly
I tried to explain how to get the article content with MediaWiki API in an easy-to-understand manner with examples (Python 3)
In the Chainer tutorial, I get an error when importing a package. (mock)
Create a REST API using the model learned in Lobe and TensorFlow Serving.
Use libsixel to output Sixel in Python and output a Matplotlib graph to the terminal.
Use twitter API to get the number of tweets related to a certain keyword
How to get a list of files in the same directory with python
[Python] Get the files in a folder with Python
Create an executable file in a scripting language
Use the MediaWiki API to get Wiki information
Get the caller of a function in Python
I want to create a window in Python
Create a standard normal distribution graph in Python
How to create a JSON file in Python
How to get help in an interactive shell
How to get the files in the [Python] folder
Use pygogo to get the log in json.
Convert a path string that uses a symbolic link in the middle to an absolute path
A story about a Python beginner trying to get Google search results using the API
[For beginners] Web scraping with Python "Access the URL in the page to get the contents"
A story about trying to introduce Linter in the middle of a Python (Flask) project
Use Twitter API to reduce the time taken by Twitter (create a highlighting (like) timeline)
Read the Python-Markdown source: How to create a parser
How to create an article from the command line
I tried to graph the packages installed in Python
How to get the variable name itself in python
Create a function to visualize / evaluate the clustering result
The easiest way to set up Last-Modified in Flask
Get the file name in a folder using glob
How to get the number of digits in Python
I want to transition with a button in flask