Help us understand the problem. What is going on with this article?

FlaskアプリにFirebase Authを利用したログイン機能を実装する

はじめに

Firebase Authを利用してFlaskアプリにログイン機能を導入します。
メールアドレスとパスワードによる認証をサンプルアプリに実装していきます。

Firebaseの設定

はじめに、Firebaseのコンソール上でログインユーザーを登録します。

プロジェクト/アプリの作成

Firebaseのコンソールにログインし、新しいプロジェクトを作ります。
スクリーンショット 2019-12-26 14.17.24.png

作成したプロジェクトに新しいWEBアプリケーションを追加します。
スクリーンショット 2019-12-21 17.44.25.png
アプリを追加すると以下のように設定情報が表示されるので、jsonファイルfirebaseConfig.jsonに転記します(今回はサンプルアプリであり、記事投稿後にプロジェクトごと削除するので、クリティカルな情報をそのまま載せています^^;)。

スクリーンショット 2019-12-24 19.27.20.png

firebaseConfig.json
{
    "apiKey": "AIzaSyAMotj5BYoi8HQbYdw_HqsOTy1NitUTzm8",
    "authDomain": "example-fd5bd.firebaseapp.com",
    "databaseURL": "https://example-fd5bd.firebaseio.com",
    "projectId": "example-fd5bd",
    "storageBucket": "example-fd5bd.appspot.com",
    "messagingSenderId": "203038233678",
    "appId": "1:203038233678:web:86a73fe39a252f8300df1f",
    "measurementId": "G-Y6Q7XMDM2V"
}

ユーザーの登録

ログイン用のユーザーを追加します。まず、コンソールのAuthentification > ログイン方法からメール/パスワードを有効にします。
スクリーンショット 2019-12-24 19.34.53.png

次に、Authentification > ユーザーから認証を行うアカウントを追加します。メールアドレスはuser@gmail.com、パスワードはpasswordとしています。
スクリーンショット 2019-12-24 19.35.26.png
これでFirebaseでの作業は完了です。

Flaskアプリの実装

Firebase側の設定は完了したので、Flaskアプリのコーディングを行います。

インストール

パッケージとしてflaskpyrebaseをインストールします。pyrebaseはFirebase APIのpythonラッパーです。

pip install flask pyrebase

コード

短いので完成品のコードをそのまま載せます。

ディレクトリ構造

ディレクトリ構造は以下の通りです。app.pyはFlaskアプリで、ログイン画面とインデックス画面があります。認証が行われていない状態ではインデックス画面にアクセスできず、ログイン画面にリダイレクトされます。firebaseConfig.jsonは前の手順で作ったもので、app.pyから読み込まれます。

$ tree . -I venv
.
├── app.py
├── firebaseConfig.json
└── templates
    ├── index.html
    └── login.html

1 directory, 4 files

ログイン画面

ログイン画面login.htmlは以下の通りです。
フォームからメールアドレスとパスワードを入力しPOSTします。
ログインに失敗しリダイレクトされた場合は、オレンジ色で「メールアドレスまたはパスワードが間違っています」とメッセージが表示されます。

templates/login.html
<html>
<head>
  <meta charset="utf-8">
  <title>Flask app with Firebase authentification</title>
</head>
<body>

<div>
    <h1>メールアドレスとパスワードを入力してください</h1>
    <form action='login' method='POST'>
        <input type='text' name='email' id='email' placeholder='email'/>
        <br/>
        <input type='password' name='password' id='password' placeholder='password'/>
        <br/>
        <input type='submit' name='submit'/>
    </form>
    <h2 style="color:orangered;">{{msg}}</h2>
</div>

</body>
</html>

ブラウザでは以下のように表示されます。
スクリーンショット 2019-12-26 14.14.07.png

インデックス画面

index.htmlはログイン状態でのみアクセスできます。ユーザーのメールアドレスを表示しています。ログアウトを押すと、ログイン画面にリダイレクトされます。

templates/index.html
<html>
<head>
  <meta charset="utf-8">
  <title>Flask app with Firebase authentification</title>
</head>
<body>

<div>
  <h1>{{usr}}さん、こんにちは!</h1>
  <a href="/logout">ログアウト</a>
</div>

</body>
</html>

ブラウザでは以下のように表示されます。
スクリーンショット 2019-12-26 14.13.55.png

Flaskアプリ

アプリ本体のコードの説明です。はじめにfirebaseConfig.jsonを読み込み、初期化を行います。アクセス可能なルートとしてloginindexlogoutの3つがあります。それぞれの機能は以下の通りです。

login()では、メソッドがGETだった場合にはlogin.htmlを表示し、メソッドがPOSTだった場合にはリクエストフォームのパラメタemailpasswordを取り出しsign_in_with_email_and_passwordによりFirebase認証を行います。失敗した場合はエラーとなるので、例外処理でログイン画面にリダイレクトします。成功した場合は、セッション変数にユーザーのメールアドレスを格納し、インデックス画面にリダイレクトします。

index()では、セッション変数が存在するかどうかでログインしているかどうかを判定しています。存在していない場合はログイン画面にリダイレクトし、存在する場合はindex.htmlを表示させます。

logout()では、セッション変数を削除してログイン画面にリダイレクトします。

app.py
from flask import Flask, request, jsonify, render_template, redirect, url_for, session
import pyrebase
import json, os

with open("firebaseConfig.json") as f:
    firebaseConfig = json.loads(f.read())
firebase = pyrebase.initialize_app(firebaseConfig)
auth = firebase.auth()

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template("login.html",msg="")

    email = request.form['email']
    password = request.form['password']
    try:
        user = auth.sign_in_with_email_and_password(email, password)
        session['usr'] = email
        return redirect(url_for('index'))
    except:
        return render_template("login.html", msg="メールアドレスまたはパスワードが間違っています。")

@app.route("/", methods=['GET'])
def index():
    usr = session.get('usr')
    if usr == None:
        return redirect(url_for('login'))
    return render_template("index.html", usr=usr)

@app.route('/logout')
def logout():
    del session['usr']
    return redirect(url_for('login'))

# run the app.
if __name__ == "__main__":
    app.debug = True
    app.run(port=5000)

まとめ

Firebase認証を使ってメールアドレスとパスワードによるログイン機能をFlaskアプリに導入することが出来ました。ログイン機能が必要になったときに手軽に導入できるのでおすすめです。アカウントの追加・停止、パスワード再発行などの操作をプラットフォーム上で行えるので、管理のコストも抑えられます。

ただし、Firebaseはモバイルアプリのプラットフォームなので、今回紹介したようにFlaskのセッション管理機能と組み合わせて使うことは珍しいかもしれません。

ousia
”賢い”コンピュータを実現するための自然言語処理や質問応答に関する研究及び製品開発を行っています。
http://ousia.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした