認証用に Python Flask Web アプリを準備する

このチュートリアルは、Python Flask Web アプリを構築し、Microsoft ID プラットフォームを使ってサインインのサポートを追加する方法を示すシリーズのパート 2 です。 このシリーズのパート 1 では、Microsoft Entra ID テナントにアプリケーションを登録して構成しました。

このチュートリアルでは、次の作業を行いました。

  • 新しい Python Flask Web アプリ プロジェクトを作成する
  • アプリの依存関係をインストールする
  • アプリケーションの UI コンポーネントを追加する
  • 認証に Microsoft Entra ID を使用するよう、Flask Web アプリを構成します。

前提条件

新しい Python Web アプリ プロジェクトを作成する

このチュートリアルの残りの部分を完了するには、Python Flask Web アプリ プロジェクトを作成する必要があります。 学習のために完成したコード サンプルを使う方がよい場合は、GitHub から Python Flask Web アプリのサンプルをダウンロードしてください。

Python Flask Web アプリを一から作成するには、次の手順を実行します。

  1. アプリケーションをホストするフォルダーを作成し、flask-web-app という名前を付けます。
  2. プロジェクト ディレクトリに移動し、app.pyapp.config.pyrequirements.txt という名前の 3 つのファイルを作成します。
  3. プロジェクトのルート フォルダーに .env ファイルを作成します。
  4. プロジェクトのルート ディレクトリに templates という名前のフォルダーを作成します。 Flask は、このサブディレクトリにあるレンダリング テンプレートを探します。

これらのファイルを作成した後、プロジェクトのファイルとディレクトリの構造は次のようになるはずです。

python-webapp/
├── templates/
│     ├── display.html
│     ├── index.html
│     ├── login.html
├── .env.sample
├── app.py
├── app.config.py
│── requirements.txt

アプリの依存関係をインストールする

構築するアプリケーションでは、Python 用 Microsoft Authentication Library (MSAL) のラッパーである identity パッケージを使います。 また、Flask、Flask Session、要求、アプリに必要な他のすべての依存関係もインストールします。 これらの依存関係で requirements.txt を更新します。

Flask>=2.2
Flask-Session>=0.3.2,<0.6
werkzeug>=2
requests>=2,<3
identity>=0.5.1,<0.6
python-dotenv<0.22 

アプリケーションの UI コンポーネントを追加する

このセクションでは、アプリ内で定義する各ルートごとに HTML テンプレートを作成します (サインイン、サインアウト、API 呼び出し、エラーのテンプレートなど)。 以下の手順に従って、これらの各ページ用のテンプレートを作成します。

ログイン テンプレート

templates フォルダー内に login.html という名前の HTML ファイルを作成し、次の内容を追加します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: Login</title>
</head>
<body>
    <h1>Microsoft Identity Python Web App</h1>

    {% if user_code %}
    <ol>
      <li>To sign in, type <b>{{ user_code }}</b> into
        <a href='{{ auth_uri }}' target=_blank>{{ auth_uri }}</a>
        to authenticate.
      </li>
      <li>And then <a href="{{ url_for('auth_response') }}">proceed</a>.</li>
    </ol>
    {% else %}
    <ul><li><a href='{{ auth_uri }}'>Sign In</a></li></ul>
    {% endif %}

    <hr>
    <footer style="text-align: right">Microsoft identity platform Web App Sample {{ version }}</footer>
</body>
</html>

このテンプレートは、ユーザーがアプリケーションにサインインするためのログイン ページを表します。

インデックス テンプレート

templates フォルダー内に index.html という名前の HTML ファイルを作成し、次の内容を追加します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: Index</title>
</head>
<body>
    <h1>Microsoft Identity Python Web App</h1>
    <h2>Welcome {{ user.get("name") }}!</h2>

    <ul>
    {% if config.get("ENDPOINT") %}
      <li><a href='/call_downstream_api'>Call a downstream API</a></li>
    {% endif %}

    <li><a href="/logout">Logout</a></li>
    </ul>

    <hr>
    <footer style="text-align: right">Microsoft identity platform Web App Sample {{ version }}</footer>
</body>
</html>

インデックス テンプレートは、ユーザーがアプリのルート URL にアクセスしたときにレンダリングされる、Web アプリのホームページの役割を果たします。

表示ページ

このテンプレートは、ダウンストリーム API 呼び出しの結果を表示するために使用されます。 次のスニペットを display.html に追加してください。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: API</title>
</head>
<body>
    <a href="javascript:window.history.go(-1)">Back</a> <!-- Displayed on top of a potentially large JSON response, so it will remain visible -->
    <h1>Result of the downstream API Call</h1>
    <pre>{{ result |tojson(indent=4) }}</pre> <!-- Just a generic json viewer -->
</body>
</html>

エラー テンプレート

認証エラー テンプレート

templates フォルダーに、発生する可能性のあるエラー メッセージを表示する auth_error.html という名前の HTML ファイルを作成します。 次のコードを auth_error.html に追加します。

<!DOCTYPE html>*
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: Error</title>
</head>
<body>
    <h2>Login Failure</h2>
    <dl>
      {#
        Flask automatically escapes these unsafe input, so we do not have to.
        See also https://flask.palletsprojects.com/en/2.0.x/templating/#jinja-setup
      #}
      <dt>{{ result.get("error") }}</dt>
      <dd>{{ result.get("error_description") }}</dd>
    </dl>
    <hr>
    <a href="{{ url_for('index') }}">Homepage</a>
</body>
</html>

構成エラー テンプレート

templates フォルダーに、必要な構成が設定されていない場合にメッセージを表示する config_error.html という名前の HTML ファイルを作成します。 次のコードを config_error.html に追加します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: Error</title>
</head>
<body>
    <h2>Config Missing</h2>
    <p>
        Almost there. Did you forget to set up
<a target=_blank
href="https://video2.skills-academy.com/azure/active-directory/develop/web-app-quickstart?pivots=devlang-python#step-5-configure-the-sample-app">
necessary environment variables</a> for your deployment?
    </p>
    <hr>
    <a href="{{ url_for('index') }}">Homepage</a>
</body>
</html>

構成ファイルを作成します

コード エディターで、構成パラメーターを格納する app_config.py を開き、次のコードを追加します。

import os
AUTHORITY= os.getenv("AUTHORITY")

# Application (client) ID of app registration
CLIENT_ID = os.getenv("CLIENT_ID")
# Application's generated client secret: never check this into source control!
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
 
REDIRECT_PATH = "/getAToken"  # Used for forming an absolute URL to your redirect URI.

ENDPOINT = 'https://graph.microsoft.com/v1.0/me'  
SCOPE = ["User.Read"]

# Tells the Flask-session extension to store sessions in the filesystem
SESSION_TYPE = "filesystem"

構成設定を格納する .env ファイルを作成する

このサンプルでは、.env ファイルを使って、コードに埋め込むべきではないアプリケーションの構成設定、環境変数、資格情報の格納と管理を行います。 プロジェクト ディレクトリのルートに作成した .env ファイルを開き、次の値を追加します。

# The following variables are required for the app to run.
CLIENT_ID=<client id>
CLIENT_SECRET=<client secret>
AUTHORITY=<Enter_your_authority_url>

.env.sample ファイルで、

    • CLIENT_ID のプレースホルダーを、アプリ登録概要ページにあるアプリケーション (クライアント) ID に置換します。
    • CLIENT_SECRET のプレースホルダーを、[証明書とシークレット] で作成したクライアント シークレットに置換します。
    • AUTHORITYhttps://login.microsoftonline.com/<TENANT_GUID> にします ディレクトリ (テナント) ID は、アプリ登録の概要ページにあります。

次のステップ

このチュートリアル シリーズの次のパートでは、Python Flask Web アプリにサインインのサポートを追加する方法を説明します。