1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flaskを使用したFacebook ログイン連携 メモ

Posted at

大まかな処理の流れ

  1. Facebookへ認可リクエスト(Authorization Request)を行う。

  2. ユーザー認証/同意を行い、認可レスポンスを受け取る。

  3. 認可レスポンスを使ってトークンリクエストを行う。

  4. アプリアクセストークンの生成を行う。※Googleと違うところ。

  5. アクセストークンを検査する。※Googleと違うところ。

事前準備

  • Facebookデベロッパーコンソールからアプリケーションを登録する。
    • クライアントID(アプリID)/app secret 取得(アプリダッシュボード -> 設定 -> ベーシックから確認)
    • クライアントトークン取得(アプリダッシュボード -> 設定 -> 詳細設定から確認)
    • Facebookログイン設定
      * 「アプリに製品を追加」→「Facebookログイン」設定→「ウェブ」選択→サイトURL入力(例:http://localhost:5000) →残りの項目はすべて「次へ」を選択。
      * Facebookログイン -> 設定 -> 「有効なOAuthリダイレクトURI」にhttp://localhost:5000/callbackを入力する。※開発中の場合は、localhostも設定可能。
  • Pythonライブラリインストール
    • flask
      • ウェブアプリ開発用フレームワーク

実装

  • 認可リクエスト ~ アクセストークン検査までのコード
import hashlib
from flask import Flask, request as r, redirect, session
from urllib import request, parse, error
from http import HTTPStatus
import json
import base64
from pprint import pprint
import os

# クライアント情報(ダッシュボードから確認)
client_id = <YOUR_CLIENT_ID>
client_secret = <YOUR_CLIENT_SECRET>
client_token = <YOUR_CLIENT_TOKEN>
redirect_uri = 'http://localhost:5000/callback'

# Facebook エンドポイント
authorization_base_url = 'https://www.facebook.com/v10.0/dialog/oauth'
token_url = 'https://graph.facebook.com/v10.0/oauth/access_token'
app_token_url = 'https://graph.facebook.com/oauth/access_token'
token_validation_url = 'https://graph.facebook.com/debug_token'

app = Flask(__name__)
app.secret_key = 'session_key'


# 1. Facebookへ認可リクエスト(Authorization Request)を行う。
@app.route("/login")
def login():
    # ステート生成+保存
    state = hashlib.sha256(os.urandom(32)).hexdigest()
    session['state'] = state
    # 認可リクエスト
    return redirect(authorization_base_url+'?{}'.format(parse.urlencode({
        'client_id': client_id,
        'scope': 'email public_profile',
        'redirect_uri': redirect_uri,
        'state': state,
        'response_type': 'code'
    })))


# Authoriztion Redirection and Token Request Endpoint
# 2.ユーザー認証/同意を行い、認可レスポンスを受け取る。
@app.route("/callback")
def callback():
    # ステート検証
    state = r.args.get('state')
    if state != session['state']:
        print("invalid_redirect")
    code = r.args.get('code')

    req, res, body, err_str = '', '', '', ''

    # 3. 認可レスポンスを使ってトークンリクエストを行う。
    token_req_url = token_url+'?{}'.format(parse.urlencode({
        'client_id': client_id,
        'client_secret': client_secret,
        'redirect_uri': redirect_uri,
        'code': code
    }))

    try:
        req = request.Request(token_req_url, method='GET')
        with request.urlopen(req) as res:
            body = res.read()
    except error.HTTPError as err:
        err_str = str(err.code) + ':' + err.reason + ':' + str(err.read())
    except error.URLError as err:
        err_str = err.reason
    access_token = json.loads(body)['access_token']

    # 4. アプリアクセストークンの生成を行う。
    # https://developers.facebook.com/docs/facebook-login/access-tokens/#apptokens
    req_url = app_token_url+'?{}'.format(parse.urlencode({
        'client_id': client_id,
        'client_secret': client_secret,
        'grant_type': 'client_credentials'
    }))
    try:
        req = request.Request(req_url, method='GET')
        with request.urlopen(req) as res:
            body = res.read()
    except error.HTTPError as err:
        err_str = str(err.code) + ':' + err.reason + ':' + str(err.read())
    except error.URLError as err:
        err_str = err.reason
    app_token = json.loads(body)['access_token']

    # 5.アクセストークンを検査する。
    req_url = token_validation_url+'?{}'.format(parse.urlencode({
        'input_token': access_token,
        'access_token': app_token
    }))
    try:
        req = request.Request(req_url, method='GET')
        with request.urlopen(req) as res:
            body = res.read()
    except error.HTTPError as err:
        err_str = str(err.code) + ':' + err.reason + ':' + str(err.read())
    except error.URLError as err:
        err_str = err.reason

    return json.loads(body)


if __name__ == "__main__":
    app.run(debug=True)

参考情報

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?