GoogleログインでFlaskアプリケーションを作成する

GoogleログインでFlaskアプリケーションを作成する

おそらく、さまざまなウェブサイトで_Googleログイン_のオプションを見たことがあるでしょう。 一部のサイトには、_Facebook Login_や_GitHub Login_などのオプションもあります。 これらすべてのオプションにより、ユーザーは既存のアカウントを利用して新しいサービスを使用できます。

この記事では、https://realpython.com/tutorials/flask/[Flask] Webアプリケーションを作成します。 アプリケーションでは、ユーザーは新しいアカウントを作成する代わりに、Google IDを使用してログインできます。 このユーザー管理方法には、多くの利点があります。 従来のユーザー名とパスワードの組み合わせを管理するよりも安全でシンプルになります。

Pythonの基本を既に理解している場合、この記事はよりわかりやすくなります。 また、WebフレームワークとHTTPリクエストについて少し知っておくと役立ちますが、それは必ずしも必要ではありません。

この記事の終わりまでに、次のことができるようになります。

  • ユーザーがGoogleでログインできるFlask Webアプリケーションを作成します

  • Googleとやり取りするクライアント資格情報を作成します

  • Flaskアプリケーションでのユーザーセッション管理にFlask-Loginを使用する

  • OAuth 2およびOpenID Connect(OIDC)の理解を深める

以下のボックスをクリックして、この記事で作成するアプリケーションのコードを取得できます。

ユーザーにGoogleログインを使用する理由

個々のユーザーにプロファイルを持たせることができます。 または、特定のユーザーのみに機能を提供したい場合があります。 いずれの場合でも、アプリケーションと対話しているユーザーを知る必要があります。 言い換えると、ユーザーを認証し、独自の方法でユーザーを識別する必要があります。

従来の解決策は、一意のユーザー名と秘密のパスワードを使用することです。 アプリケーションはその情報を保存し、必要なときにそれを要求します。 ただし、このソリューションにはいくつかの欠点があります。

  • パスワードを安全に管理する必要があります。

  • アカウント関連の機能を実装する必要があります。

  • 二要素認証

  • パスワードのリセット

  • 悪意のあるログイン試行から保護する必要があります。

  • ユーザーはさらに別のユーザー名とパスワードを覚えておく必要があります。

ユーザーにGoogleログインを使用すると、そのすべての責任をユーザーにプッシュできます。 アプリケーションは、ユーザーが認証を受けるまで待機します。 次に、Googleはそのユーザーについてアプリケーションに通知します。 その時点で、アプリケーションに効果的にログインできます。

パスワードを保存する必要はありません。Googleはすべてのセキュリティを処理します。

アプリケーションがGoogleログインを使用する方法

OAuth 2およびhttps://openid.net/specs/openid-connect-core-1_0.html[OpenID Connect( OIDC)]。 OIDCはOAuth 2の上に構築されており、いくつかの新しいアイデアと概念が追加されています。

これらの仕様は、サードパーティアプリケーションが別のサービスから情報を取得する方法を定義します。 通常、これにはユーザーからの同意の取得が含まれます。 これを少し解凍するために、これがビルドしようとしているアプリケーションにどのように適用されるかを見てみましょう。

サードパーティのアプリケーションを作成しようとしています。ユーザーは_Google Login_ボタンを使用してログインできます。 そのためには、Googleがアプリケーションについて知る必要があります。 幸いなことに、アプリケーションをGoogleのクライアントとして登録できます。

ユーザーがアプリケーションにアクセスして_Googleログイン_ボタンを押すと、それらをGoogleに送信できます。 そこから、Googleはユーザーがアプリケーションにメールやその他の情報を渡すことに同意することを確認する必要があります。 ユーザーが同意すると、Googleはアプリケーションに情報を送り返します。 その後、その情報を保存し、後で参照して、ユーザーを効果的にログインさせることができます。

OpenID Connectの詳細

ユーザーに代わって情報を要求するには、プロバイダーとも呼ばれる認証サーバーの「クライアント」になる必要があります。 これらの仕様を掘り下げて理解する最初のことは、多くの重複する用語と概念があることです。

そのため、サードパーティアプリケーション(クライアントとも呼ばれます)として、ユーザーに代わってプロバイダーから情報を取得する必要があります。 それを可能にする一連の手順があり、それらの手順は特定の順序で実行する必要があります。 そのため、OAuth 2とOpenID Connectが*ハンドシェイク*、フロー、または*ダンス*と呼ばれることもあります。

これらの手順は、大まかに次のとおりです。

  1. サードパーティのアプリケーションをプロバイダーのクライアントとして登録します。

    • プロバイダーから一意のクライアント資格情報を受け取ります。

    • これらのクライアント認証情報を使用して、後でプロバイダーの認証(本人であることの証明)を行います。

  2. クライアントはリクエストをプロバイダーの + authorization + URLに送信します

  3. プロバイダーはユーザーに認証を要求します(本人であることを証明します)

  4. プロバイダーは、クライアントに代わって行動することに同意するようユーザーに要求します。

    • 通常、これには制限されたアクセスが含まれ、クライアントが何を求めているのかがユーザーに明らかにされます。

    • これは、場所や連絡先にアクセスするために携帯電話でアプリを承認する必要があるときのようなものです。

  5. プロバイダーはクライアントに一意の認証コードを送信します。

  6. クライアントは認証コードをプロバイダーの「+ token +」URLに送り返します。

  7. プロバイダーは、ユーザーに代わって他のプロバイダーURLで使用するクライアントトークンを送信します。

*注意:*上記の手順は、OAuth 2で定義されている承認コードフロー用です。

これらの手順には、これまでに述べた標準の両方が含まれます。 OpenID Connect(OIDC)はOA​​uth 2の上に構築されており、主に認証プロセスに関係するいくつかの追加機能と要件が追加されています。 上記のフローで説明した認証以外に、アプリケーションのOIDCの重要な概念は、 provider configuration および userinfo endpoint です。

*provider configuration* には、OAuth 2フローに使用する必要がある正確なURLなど、プロバイダーに関する情報が含まれています。 OIDCプロバイダーには、https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata [standardized fields]でドキュメントを取得するために使用できる標準URLがあります。
*https://openid.net/specs/openid-connect-core-1_0.html#UserInfo [userinfo endpoint]* は、OAuth 2フローを通過した後のユーザーに関する情報を返します。 これには、彼らのメールと、アプリケーションで使用する基本的なプロファイル情報が含まれます。 このユーザー情報を取得するには、上記のフローの最後のステップで説明されているように、プロバイダーからトークンが必要です。

プロバイダー設定とユーザー情報エンドポイントを後で利用する方法の詳細が表示されます。

Googleクライアントの作成

_Google Login_オプションを有効にする最初のステップは、アプリケーションをGoogleのクライアントとして登録することです。 それを行う手順を見ていきましょう。

まず、Googleアカウントが必要になることに注意してください。 Gmailを使用している場合は、すでに持っています。

次に、https://console.developers.google.com/apis/credentials [Googleデベロッパーの資格情報ページ]にアクセスします。

一度、あなたは彼らの利用規約に同意するように促されるかもしれません。 それらに同意する場合は、次のページの[資格情報の作成]ボタンを押します。 OAuthクライアントID のオプションを選択します。

Googleは資格情報のスクリーンショットを作成、幅= 1194、height = 580

上部の[+ Webアプリケーション+]オプションを選択します。 `+ Name +`フィールドでもクライアントの名前を提供できます。 提供する名前は、ユーザーに代わって動作するアプリケーションに同意するときにユーザーに表示されます。

今のところローカルでWebアプリケーションを実行しているので、 `+ Authorized JavaScript origins `を ` https://127.0.0.1:5000 `に、 ` Authorized redirect URIs `を ` https:/に設定できます/127.0.0.1:5000/login/callback + `。 これにより、ローカルのFlaskアプリケーションがGoogleと通信できるようになります。

最後に、「+ Create 」を押して「 client ID 」と「 client secret +」を書き留めます。 後で両方が必要になります。

独自のWebアプリケーションを作成する

ここで、学んだ知識を実際のWebアプリケーションを作成するために適用する楽しい部分について説明します。

目標を念頭に置いて始めましょう。 ユーザーが自分のGoogleアカウントでログインできるようにするアプリケーションを作成します。 そのアプリケーションは、メールアドレスなど、ユーザーに関する基本的な情報をGoogleから取得できる必要があります。 次に、アプリケーションは基本的なユーザー情報をデータベースに保存する必要があります。

ただし、最初に、使用するフレームワークとライブラリを見てみましょう。

フラスコ

Flaskは自称「マイクロフレームワーク」である軽量のWebフレームワークです。 URLのルーティングやHTTPリクエストの処理など、Webアプリケーションが実行する基本タスク用の組み込みツールが付属しています。

人気とシンプルさの両方の例としてFlaskを使用することにしました。 ただし、OAuth 2とOIDCについて学んだことはFlaskに固有のものではありません。 実際、OAuth 2とOIDCを簡単にするために使用するライブラリも、あらゆるPythonコードで使用できます。 言い換えると、いくつかの小さな変更を加えることで、ここで学んだことを選択して、選択した別のフレームワークに適用できます。

フラスコログイン

ユーザーの処理を容易にするために使用できるもう1つのツールは、https://flask-login.readthedocs.io/en/latest/[flask_login]で、これは*ユーザーセッション管理*を提供します。

このライブラリは、舞台裏でいくつかのことを行い、ユーザーを支援するツールを提供します。 つまり、ユーザーがログインしたときとログアウトしたときを知るためのユーティリティを提供します。 これは、ブラウザーCookie内のユーザーセッションを管理することにより行われます。

また、ユーザーのデータベースエントリの作成など、ユーザーのログインとログアウトも処理します。 ただし、コードの観点からは、すべてが非常に単純になります(すぐにわかります)。

OAuthLib

セキュリティ関連および標準準拠のコードに非常に当てはまる一般的なフレーズがあります。「車輪を再発明しないでください。」

OAuth 2とOpenID Connectの標準は複雑です。 RFCと仕様をご覧ください。 密集しています。 1つの間違いは、アプリケーションの脆弱性を開く可能性があることを意味します。

そのため、これらの標準を実装するためのコードを書くつもりはありません。 いくつかの非常に具体的な基準で選択されたPythonパッケージを使用します。

  1. 人気のある一般的に推奨されるライブラリです。 他の多くのパッケージがこのライブラリを内部的に使用しています。

  2. 非常にアクティブで、頻繁にバグにパッチを当てています。

  3. これは戦闘に強く、2012年から続いています。

このライブラリを使用して、Flask、Django、Pyramidなどにより密接に統合するWebフレームワーク固有のパッケージがあります。 ただし、ここで学習したコードをフレームワークに依存しないようにするには、このライブラリを派手なラッパーなしで直接使用します。

依存関係のインストール

生活を楽にするために使用するサードパーティの依存関係がいくつかあります。 これらの依存関係の概要は次のとおりです。

  • 典型的なWebアプリケーションのタスクを簡単にするWebフレームワーク(Flask)

  • ユーザーセッションを管理する頭痛のない方法(Flask-Login)

  • 戦闘に強いOIDCライブラリ( + oauthlib +

さらに、次のものを使用します。

  • ログインするユーザーに関する情報を保存するデータベース(SQLite)

  • HTTPリクエストをGoogleに送信するユーザーフレンドリーな方法( + requests +

  • ローカルで `+ https +`で安全に実行できるようにする簡単な方法(pyOpenSSL)

SQLiteは標準のPythonライブラリの一部ですが、他のパッケージはそうではありません。 そのため、インストールする依存関係がいくつかあります。 とりあえず、このアプリケーションの作成を順を追って見ていきましょう。

まず、上記のサードパーティの依存関係をインストールする必要があります。 これを行うには、次の内容の `+ requirements.txt +`ファイルを作成します。

requests==2.21.0
Flask==1.0.2
oauthlib==3.0.1
pyOpenSSL==19.0.0
Flask-Login==0.4.1

*注意:*パッケージの他のバージョンも機能する可能性がありますが、これらはこの記事の執筆およびテスト中に使用されたバージョンです。

次に、Pythonのパッケージインストーラーである `+ pip +`を使用して、これらの依存関係をインストールできます。

*注:*さまざまなPythonアプリケーションの依存関係をコンピューターにインストールする場合は、一般に仮想環境を使用することをお勧めします。 詳細については、https://realpython.com/python-virtual-environments-a-primer/[Python Virtual Environments:A Primer]を参照してください。

`+ requirements.txt +`ファイルからインストールするには、ターミナルで次のコマンドを実行します:

$ pip install -r requirements.txt

これでロックンロールの準備が整いました! コードを詳しく見てみましょう。

インポート、構成、およびセットアップ

いくつかの基本的なデータベース機能とユーザー管理をサポートするいくつかのファイルを追加することから始めます。 主にhttps://realpython.com/tutorials/databases/[Pythonデータベース]実装の詳細に飛び込むことは、私たちの目標から気を散らすウサギの穴だからです。

`+ schema.sql +`ファイルは、データベースにユーザーテーブルを作成する単なるSQLです。 このファイルには、ユーザーごとに保存するフィールドが表示されます。

この次のファイルには、データベースの情報を保存および取得する「+ User +」クラスが含まれています。 名前、メール、プロフィール写真はすべてGoogleから取得されます。これについては、記事の後半で説明します。

上記のコードから + db.py ++ schema.sql +、および `+ user.py `ファイルを作成したら、新しい ` app.py +`ファイルを作成できます。 次のインポートを追加します。

# Python standard libraries
import json
import os
import sqlite3

# Third-party libraries
from flask import Flask, redirect, request, url_for
from flask_login import (
    LoginManager,
    current_user,
    login_required,
    login_user,
    logout_user,
)
from oauthlib.oauth2 import WebApplicationClient
import requests

# Internal imports
from db import init_db_command
from user import User

これらはすべて後で使用するため、現時点でそれぞれを理解することはそれほど重要ではありません。 `+ app.py +`の次の部分は設定です:

# Configuration
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", None)
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", None)
GOOGLE_DISCOVERY_URL = (
    "https://accounts.google.com/.well-known/openid-configuration"
)

GoogleクライアントIDとクライアントシークレットを保存する方法は次のとおりです。これらは記事の前半で作成する必要があります。 これらはOIDCフローの後半で使用されます。

アプリケーションは、環境変数を読み取ってクライアントの資格情報を取得しようとします。 これには2つの理由があります。

  1. 別の認証情報を使用する場合、後でコードを変更する必要はありません。環境を更新するだけです。

  2. 誤って秘密の資格情報をGitHub(または別の公開リポジトリ)にコミットすることはできません。

多くの人が誤って秘密を公開リポジトリにコミットしており、かなり深刻なセキュリティリスクをもたらしています。 環境変数を使用して、それから保護することをお勧めします。

*ヒント: *+ export GOOGLE_CLIENT_ID = your_client_id +( `+ GOOGLE_CLIENT_SECRET +`と同様)を使用して、Linux bashターミナルおよびMac OS Xターミナルでクライアント認証情報を環境変数として設定できます。

Windowsを使用している場合は、コマンドプロンプトで「+ set GOOGLE_CLIENT_ID = your_client_id +」を使用できます。

または、ここに文字列を直接貼り付けて、これらの変数に保存することもできます。* ただし*、クライアントシークレットはパブリックリポジトリと共有またはコミットしないでください。 つまり、実際のクライアント資格情報をここに貼り付ける場合は、このファイルをチェックインしないように非常に注意してください。

最後に、グローバル変数と素朴なデータベース初期化ロジックを含むコードを以下に示します。 データベースの初期化以外のほとんどは、前述のFlask、Flask-Login、およびOAuthLibをセットアップする標準的な方法です。

# Flask app setup
app = Flask(__name__)
app.secret_key = os.environ.get("SECRET_KEY") or os.urandom(24)

# User session management setup
# https://flask-login.readthedocs.io/en/latest
login_manager = LoginManager()
login_manager.init_app(app)

# Naive database setup
try:
    init_db_command()
except sqlite3.OperationalError:
    # Assume it's already been created
    pass

# OAuth 2 client setup
client = WebApplicationClient(GOOGLE_CLIENT_ID)

# Flask-Login helper to retrieve a user from our db
@login_manager.user_loader
def load_user(user_id):
    return User.get(user_id)

すでにGoogleのクライアントIDを使用して、 `+ WebApplicationClient `で ` oauthlib +`クライアントを初期化しています。

FlaskおよびFlask-Loginが使用する別の環境変数 `+ SECRET_KEY +`を作成して、Cookieやその他のアイテムに暗号で署名できます。

Webアプリケーションエンドポイント

今、楽しいもののために。 Webアプリケーションの4つのエンドポイントを作成します。

  1. ホームページ用

  2. ユーザーログインプロセスを開始するための1つ

  3. ユーザーがログインした後にGoogleがリダイレクトするコールバック用

  4. ログアウト用

これらのエンドポイントは、アプリケーション上のさまざまなURLによって非常に創造的な名前で定義されます。

  1. ホームページ: */ . ログイン: +/login + . ログインコールバック: +/login/callback + . ログアウト:* +/logout +

もちろん、後でページと機能を追加することもできます。 このアプリケーションの最終結果は、必要なものを追加するために完全に拡張可能になります。

これらのエンドポイント用の以下のすべてのコードを `+ app.py +`ファイルに追加します。 これらのエンドポイントの各コードを1つずつ見ていきましょう。

ホームページ

これは視覚的には派手なものではありませんが、ユーザーがログインしている場合に別の何かを表示するためのきちんとしたロジックを追加します ユーザーがログインしていない場合、_Google Login_というリンクが表示されます。

リンクを押すと、「+/login +」エンドポイントにリダイレクトされ、ログインフローが開始されます。 ログインに成功すると、ホームページにユーザーのGoogleメールとGoogleの公開プロフィール写真の両方が表示されます。

さらに苦労せずに、 `+ app.py +`ファイルにコードを追加し始めることができます:

@app.route("/")
def index():
    if current_user.is_authenticated:
        return (
            "<p>Hello, {}! You're logged in! Email: {}</p>"
            "<div><p>Google Profile Picture:</p>"
            '<img src="{}" alt="Google profile pic"></img></div>'
            '<a class="button" href="/logout">Logout</a>'.format(
                current_user.name, current_user.email, current_user.profile_pic
            )
        )
    else:
        return '<a class="button" href="/login">Google Login</a>'

HTMLを文字列として返していることに注意してください。Flaskはこれを提供できます。 `+ current_user.is_authenticated `は ` Flask-Login +`ライブラリの素敵な追加です。 これは、アプリケーションを操作している現在のユーザーがログインしているかどうかを判断する簡単な方法です。 これにより、条件付きロジックを適用できます。 この場合、ユーザーがログインしている場合、ユーザーについて保存した情報が表示されます。

`+ current_user.email `などの ` current_user `オブジェクトの属性としてフィールドにアクセスするだけで、ユーザーのデータベースエントリからフィールドを取得できます。 これは、 ` Flask-Login +`のもう1つの追加です。

ログイン

それでは、OAuth 2フローを見てみましょう。 上記の_Google Login_ボタンは、このエンドポイントにリダイレクトします。 フローの最初のステップは、GoogleのOAuth 2認証エンドポイントがどこにあるかを把握することです。

OAuth 2とOpenID Connect(OIDC)によって定義されているものの間の境界線は、ここから曖昧になります。 前に説明したように、OIDCには* provider設定*の標準エンドポイントがあり、OAuth 2およびOIDC情報の束が含まれています。 その情報を含むドキュメントは、どこでも標準のエンドポイント「+ .well-known/openid-configuration +」から提供されます。

「+ GOOGLE_DISCOVERY_URL +」を定義した以前のコードをコピーしたと仮定すると、Googleのプロバイダー設定を取得するための簡単で素朴な機能は次のとおりです。

def get_google_provider_cfg():
    return requests.get(GOOGLE_DISCOVERY_URL).json()

*ヒント:*これをより堅牢にするには、GoogleのAPIが有効なプロバイダー構成ドキュメントではなく失敗を返す場合に備えて、Google API呼び出しにエラー処理を追加する必要があります。

必要なプロバイダー構成ドキュメントのフィールドは、「+ authorization_endpoint +」と呼ばれます。 これには、クライアントアプリケーションからGoogleでOAuth 2フローを開始するために使用する必要があるURLが含まれます。

次のコードを使用して、すべてのロジックをまとめることができます。

@app.route("/login")
def login():
    # Find out what URL to hit for Google login
    google_provider_cfg = get_google_provider_cfg()
    authorization_endpoint = google_provider_cfg["authorization_endpoint"]

    # Use library to construct the request for Google login and provide
    # scopes that let you retrieve user's profile from Google
    request_uri = client.prepare_request_uri(
        authorization_endpoint,
        redirect_uri=request.base_url + "/callback",
        scope=["openid", "email", "profile"],
    )
    return redirect(request_uri)

幸いなことに、 `+ oauthlib `は実際のGoogleへのリクエストを簡単にします。 既にGoogleクライアントIDを付与した事前設定済みの「 client 」を使用しました。 次に、Googleで使用するリダイレクトを指定しました。 最後に、GoogleにいくつかのOAuth 2 ` scopes +`を要求しました。

各スコープは、個別のユーザー情報と考えることができます。 あなたの場合、ユーザーのメールとGoogleからの基本的なプロフィール情報を求めています。 もちろん、ユーザーはこの情報を提供することに同意する必要があります。

注意:「+ openid +」は、GoogleにOIDCフローを開始するために必要なスコープです。OIDCフローは、ログインさせることでユーザーを認証します。 OAuth 2は実際に認証の方法を標準化していないため、この場合のフローにはこれが必要です。

ログインコールバック

前のいくつかのエンドポイントよりも少し複雑なので、これを少しずつやってみましょう。

Googleの認証エンドポイントにリダイレクトすると、Google側で多くのことが起こります。

アプリケーションのログインエンドポイントは、ユーザーを認証して同意を求めるGoogleのすべての作業のジャンプポイントです。 ユーザーがGoogleにログインし、電子メールと基本プロファイル情報をアプリケーションと共有することに同意すると、Googleは固有のコードを生成してアプリケーションに送り返します。

念のため、前に読んだOIDCの手順を以下に示します。

  1. サードパーティのアプリケーションをプロバイダーのクライアントとして登録します。

  2. クライアントはリクエストをプロバイダーの + authorization + URLに送信します。

  3. プロバイダーはユーザーに認証を要求します(本人であることを証明します)。

  4. プロバイダーは、クライアントに代わって行動することに同意するようユーザーに求めます。

  5. プロバイダーはクライアントに一意の認証コードを送信します

  6. クライアントは認証コードをプロバイダーの「+ token +」URLに送り返します

  7. プロバイダーは、ユーザーに代わって他のURLで使用するクライアントトークンを送信します

Googleがその一意のコードを送信すると、アプリケーションのこのログインコールバックエンドポイントに送信されます。 したがって、最初のステップは、エンドポイントを定義し、 `+ code +`を取得することです:

@app.route("/login/callback")
def callback():
    # Get authorization code Google sent back to you
    code = request.args.get("code")

次に行うことは、そのコードをGoogleの「+ token 」エンドポイントに送り返すことです。 Googleはクライアントの資格情報を確認した後、ユーザーに代わって他のGoogleエンドポイント(以前に読んだ ` userinfo +`エンドポイントを含む)を認証できるトークンを送り返します。 あなたの場合、基本的なプロファイル情報を表示するように要求しただけなので、トークンでできるのはそれだけです。

まず、Googleの「+ token +」エンドポイントが何であるかを把握する必要があります。 プロバイダー構成ドキュメントを再度使用します。

# Find out what URL to hit to get tokens that allow you to ask for
# things on behalf of a user
google_provider_cfg = get_google_provider_cfg()
token_endpoint = google_provider_cfg["token_endpoint"]

次のコードブロックで、 `+ oauthlib `が数回助けになります。 まず、トークン要求を作成する必要があります。 リクエストが作成されると、 ` requests `ライブラリを使用して実際に送信します。 次に、 ` oauthlib +`を使用して、応答からトークンを解析します。

# Prepare and send a request to get tokens! Yay tokens!
token_url, headers, body = client.prepare_token_request(
    token_endpoint,
    authorization_response=request.url,
    redirect_url=request.base_url,
    code=code
)
token_response = requests.post(
    token_url,
    headers=headers,
    data=body,
    auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET),
)

# Parse the tokens!
client.parse_request_body_response(json.dumps(token_response.json()))

ユーザーのプロフィール情報を取得するために必要なツールが用意できたので、Googleに問い合わせる必要があります。 幸い、OIDCはユーザー情報エンドポイントを定義し、特定のプロバイダーのURLはプロバイダー構成で標準化されています。 プロバイダー設定文書の `+ userinfo_endpoint `フィールドをチェックすることで場所を取得できます。 次に、 ` oauthlib `を使用してリクエストにトークンを追加し、 ` requests +`を使用して送信できます。

# Now that you have tokens (yay) let's find and hit the URL
# from Google that gives you the user's profile information,
# including their Google profile image and email
userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
uri, headers, body = client.add_token(userinfo_endpoint)
userinfo_response = requests.get(uri, headers=headers, data=body)

あなたの旅の次のステップは、 `+ userinfo `エンドポイントからの応答を解析することです。 Googleはオプションのフィールド「 email_verified +」を使用して、ユーザーがアカウントを作成しただけでなく、アカウントの作成を完了するためにメールアドレスを確認したことを確認します。 Googleが提供するセキュリティのもう1つのレイヤーであるため、この検証を条件付きでチェックすることは一般に安全です。

そうは言っても、それを確認し、ユーザーが検証されたとGoogleが言った場合、ユーザーの情報を解析します。 使用する4つの基本プロファイル情報は次のとおりです。

  1. * + sub +:*件名、Googleのユーザーの一意の識別子

  2. * + email +:*ユーザーのGoogleメールアドレス

  3. * + picture +Googleでのユーザーの公開プロフィール写真 . + given_name +:* Googleでのユーザーの姓名

その解析はすべて、次のコードになります。

# You want to make sure their email is verified.
# The user authenticated with Google, authorized your
# app, and now you've verified their email through Google!
if userinfo_response.json().get("email_verified"):
    unique_id = userinfo_response.json()["sub"]
    users_email = userinfo_response.json()["email"]
    picture = userinfo_response.json()["picture"]
    users_name = userinfo_response.json()["given_name"]
else:
    return "User email not available or not verified by Google.", 400

このコールバックの最終手順は次のとおりです。

  1. Googleから取得した情報を使用してデータベースにユーザーを作成します

  2. ユーザーをログインしてユーザーセッションを開始します

  3. ユーザーをホームページに戻します(ここで、パブリックプロファイル情報を表示します)

これらの手順を実行するコードは次のとおりです。

# Create a user in your db with the information provided
# by Google
user = User(
    id_=unique_id, name=users_name, email=users_email, profile_pic=picture
)

# Doesn't exist? Add it to the database.
if not User.get(unique_id):
    User.create(unique_id, users_name, users_email, picture)

# Begin user session by logging the user in
login_user(user)

# Send user back to homepage
return redirect(url_for("index"))

そのため、ここで行っているのは、ユーザーがまだ存在しない場合に、ユーザーのデータベースに新しい行を作成することです。 次に、Flask-Loginを使用してセッションを開始します。

ログアウト

ログアウトエンドポイントは、最後のいくつかのエンドポイントよりもはるかに少ないコードです。 ログアウト機能を呼び出してホームページにリダイレクトするだけです。 完了しました。 ここにあります:

@app.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect(url_for("index"))

+ @ login_required + decoratorは、ここで言及することが重要です。 これは、「+ Flask-Login +」ツールボックスの別のツールであり、ログインしたユーザーのみがこのエンドポイントにアクセスできるようにします。 ログインしたユーザーのみが何かにアクセスする必要がある場合、これを使用できます。 この場合、ログインしているユーザーのみがログアウトできます。

アプリケーションをローカルでテストする

`+ app.py +`に最終コードを追加することで、ローカルコンピューターでFlaskアプリケーションを実行してログインフローをテストできます。

if __name__ == "__main__":
    app.run(ssl_context="adhoc")

ターミナルで次のコマンドを使用して、Flaskアプリケーションを実行できます。

$ python app.py

*注意:*単純なデータベース初期化ロジックのため、このコマンドを初めて実行すると、データベースが作成されます。 アプリを起動するには、同じコマンド_again_を実行する必要があります。

Flaskは、開発サーバーを実行している端末に印刷する必要があります。 `+ https://127.0.0.1:5000/+`でなければなりません。

Flaskの開発サーバーは、Googleとの暗号化された接続を確保するために「+ https 」を使用してローカルで実行されていることに注意してください。 これは、上記のコードの ` app.run `への ` ssl_context =" adhoc "`引数によって実現されます。 これには、パッケージ ` PyOpenSSL +`がインストールされている必要があります。

欠点は、使用される証明書がオンザフライで生成されるため、ブラウザで「+ https://127.0.0.1:5000/+」にアクセスすると、おそらく接続が安全でないという大きな警告画面が表示されますまたは非公開。 これらの警告は事実上無視できます。

警告画面を過ぎると、_Google Login_というボタンが1つ表示されます。 押すと、公式のGoogleログインに移動します。 ログインすると、「サードパーティアプリケーション」があなたのメールとプロフィール情報にアクセスすることに同意するように求められます。

同意すると、Flaskアプリケーションにリダイレクトされ、ページにGoogleメールと公開プロフィール写真が表示されます。 最後に、_Logout_ボタンを使用すると、ログアウトできます。

結論

ユーザーが既存のアカウントを使用してWebアプリケーションにログインできるようにすることには、多くの利点があります。 最も重要なことは、アカウント管理のセキュリティと複雑さをあなたの肩にかける必要がないことです。 これにより、2要素認証などの細かい点について心配することなく、空想の新しいWebアプリケーションを自由に作成できます。

この記事で作成したアプリケーションは、出発点として最適です。 以下のボックスをクリックして、コードを取得できます。

次のステップは次のことです。

  • データベースの初期化をやり直して、アプリケーションの実行とは別に実行する

  • 管理を容易にするために、PythonコードからHTML/CSSを分離します。

  • templatesを使用できます。

  • 静的ファイル(JSやCSSなど)http://flask.pocoo.org/docs/1.0/quickstart/#static-files [他から]を読み込むこともできます。

  • クラウドでアプリケーションをホストする

  • ドメイン名を購入する

  • 実際のSSL証明書を使用して、その厄介な警告を取り除きます

この記事では、OAuth 2とOpenID Connectの基本について説明しました。 よく知られているPythonパッケージを使用して、ユーザーが既存のGoogleアカウントでログインできるWebアプリケーションを作成する方法を見てきました。 最も重要なことは、次のWebアプリケーションの優れた出発点として役立つサンプルコードがあることです。