MSAL Pythonを使用してネイティブ Linux で SSO を有効にする

Microsoft Authentication Library (MSAL) はソフトウェア開発キット (SDK) です。これにより、アプリは Linux ディストリビューションとは独立して配布される Linux コンポーネントである Microsoft シングル サインオンを Linux ブローカーに呼び出しますが、sudo apt install microsoft-identity-brokerまたはsudo dnf install microsoft-identity-brokerを使用してパッケージ マネージャーを使用してインストールされます。

このコンポーネントは認証ブローカーとして機能し、アプリのユーザーは、Linux に知られているアカウント (ブローカーから使用するアプリの Linux セッションにサインインしたアカウントなど) との統合の恩恵を受けることができます。

ブローカーは、Microsoft (ポータル サイト など) によって開発されたアプリケーションの依存関係としてもバンドルされています。 インストールされているブローカーのインストールの例として、Linux コンピューターが、Microsoft Intuneなどのエンドポイント管理ソリューションを介して会社のデバイスフリートに登録されている場合があります。

ブローカーとは

認証ブローカーは、接続されているアカウントの認証ハンドシェイクとトークンメンテナンスを管理するユーザーのマシン上で実行されるアプリケーションです。 Linux オペレーティング システムでは、認証ブローカーとして Linux 用の Microsoft シングル サインオンが使用されます。 開発者と顧客にとって、次のような多くの利点があります。

  • シングル サインオンを有効にする: アプリを使用すると、ユーザーがMicrosoft Entra IDで認証する方法を簡略化し、Microsoft Entra ID更新トークンを流出や誤用から保護できます
  • セキュリティの強化。 多くのセキュリティ強化は、アプリケーション ロジックを更新する必要なく、ブローカーと共に提供されます。
  • 機能のサポート。 ブローカー開発者の助けを借りて、豊富な OS とサービス機能にアクセスできます。
  • システム統合。 組み込みのアカウント ピッカーでブローカー のプラグ アンド プレイを使用するアプリケーションにより、ユーザーは同じ資格情報を何度も再入力する代わりに、既存のアカウントをすばやく選択できます。
  • トークン保護。 Linux 向け Microsoft シングル サインオンでは、リフレッシュ トークンがデバイスにバインドされるようにします。

ブローカーの使用をオプトインする方法

  1. MSAL Python ライブラリでは、WSL とスタンドアロン Linux の両方でブローカーを有効にするenable_broker_on_linux フラグを導入しました。
    • Azure CLIの WSL でのみブローカー サポートを有効にすることが目的の場合は、WSL でのみ enable_broker_on_wsl フラグをアクティブ化するように Azure CLI アプリ コードを変更することを検討できます。
    • クロスプラットフォーム アプリケーションを作成する場合は、「enable_broker_on_windows」の記事で説明されているように、も使用する必要があります。
    • 次のオプトイン パラメーターの任意の組み合わせを true に設定できます。
オプトイン フラグ アプリが~上で実行される場合 アプリでこれをデスクトップ プラットフォームリダイレクト URI として登録Azure portal
Windows でブローカーを有効にする Windows 10+ ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id
enable_broker_on_wsl WSL ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id
enable_broker_on_mac ポータル サイトがインストールされている Mac msauth.com.msauth.unsignedapp://auth
enable_broker_on_linux Intune がインストールされている Linux https://login.microsoftonline.com/common/oauth2/nativeclient (有効にする必要があります)
  1. アプリケーションでは、ブローカー固有のリダイレクト URI をサポートする必要があります。 Linux具体的には、リダイレクト URI の URL は次のようにする必要があります。

    https://login.microsoftonline.com/common/oauth2/nativeclient
    
  2. ブローカーを使用するには、PyPI のコア MSAL に加えて、ブローカー関連のパッケージをインストールする必要があります。

    pip install "msal[broker]>=1.33.0b1,<2"
    
  3. 構成したら、 acquire_token_interactive を呼び出してトークンを取得できます。

    result = app.acquire_token_interactive(["User.ReadBasic.All"],
                        parent_window_handle=app.CONSOLE_WINDOW_HANDLE)
    

ブローカー サポートのパラメーター

MSAL Pythonでブローカー サポートを構成するには、次のパラメーターを使用できます。 これらのパラメーターは、 PublicClientApplication コンストラクターまたは acquire_token_interactive メソッドに渡すことができます。

Parameters: タイプ 説明
Windows でブローカーを有効にする boolean この設定は、アプリが Windows 10 以降で実行されている場合にのみ有効です。 このパラメーターの既定値は None です。つまり、MSAL はブローカーを使用しません。

New in MSAL Python 1.25.0.
enable_broker_on_wsl boolean この設定は、アプリが WSL で実行されている場合にのみ有効です。 このパラメーターの既定値は None です。つまり、MSAL はブローカーを使用しません。

New in MSAL Python 1.25.0.
enable_broker_on_mac boolean この設定は、ポータル サイトがインストールされている Mac でアプリが実行されている場合にのみ有効です。 このパラメーターの既定値は None です。つまり、MSAL はブローカーを使用しません。

New in MSAL Python 1.31.0.
enable_broker_on_linux boolean この設定は、アプリが Intune がインストールされた Linux 上で実行されている場合にのみ有効です。 このパラメーターの既定値は None です。つまり、MSAL はブローカーを使用しません。

New in MSAL Python 1.33.0.
parent_window_handle int オプション

parent_window_handleに関する注意事項

linux では使用されていない場合でも、 parent_window_handle パラメーターが必要です。 GUI アプリケーションの場合、ログイン プロンプトの場所はアドホックで決定され、現在は特定のウィンドウにバインドできません。 今後の更新では、このパラメーターを使用して 実際 の親ウィンドウが決定されます。

状態 説明
アプリはブローカーを利用したくない parent_window_handleを指定する必要はありません
アプリがブローカーを使用することを選択する parent_window_handleが必要です
アプリは、Windowsまたは Mac システムで実行されている GUI アプリです サインイン ウィンドウがアプリケーションのウィンドウの前面に表示されるように、そのウィンドウ ハンドルを指定する必要があります
アプリは、Windowsまたは Mac システムで実行されているコンソール アプリです プレースホルダーを使用できます PublicClientApplication.CONSOLE_WINDOW_HANDLE
アプリはクロスプラットフォーム アプリケーションを意図しています アプリは、enable_broker_on_windowsに関する記事で説明されているように、を使用する必要があります。

MSAL Pythonのブローカー サポートのフォールバック動作

MSAL はエラーアウトするか、非ブローカー フローにサイレント フォールバックします。

  1. MSAL はenable_broker_を無視します... ブローカーでサポートされていないことがわかっている認証フローでブローカーをバイパスします。 これには、ADFS、B2C などが含まれます。 その他の「could-use-broker」シナリオについては、以下を参照してください。

  2. アプリ開発者がブローカーを使用することをオプトインしたが、直接依存関係 "中間層" パッケージがインストールされていない場合、MSAL エラーが発生します。 エラー メッセージは、アプリ開発者が正しい依存関係 msal[broker] を宣言するように指示します。 このエラーはアプリ開発者が対処できるものなので、ここではエラーを返します。

  3. MSAL は、オプトインされており、依存関係がインストールされているものの初期化に失敗した場合、ブローカーを自動的に無効化し、非ブローカー方式にフォールバックします。 これは、OS が古すぎるか、基になるブローカー コンポーネントが何らかの方法で使用できないデバイスで発生する可能性があります。 アプリ開発者やエンド ユーザーがここでできることはあまりありません。 最終的に、条件付きアクセス ポリシーによって、ユーザーは別のデバイスに切り替える必要があります。

  4. ブローカーがオプトイン、インストール、初期化されたが、後続のトークン要求が失敗した場合、MSAL エラーが発生します。

Important

ブローカー関連のパッケージがインストールされておらず、認証ブローカーを使用しようとすると、 ImportError: You need to install dependency by: pip install "msal[broker]>=1.xx,<2"というエラーが表示されます。

Note

linux では使用されていない場合でも、 parent_window_handle パラメーターが必要です。 GUI アプリケーションの場合、ログイン プロンプトの場所はアドホックで決定され、現在は特定のウィンドウにバインドできません。 今後の更新では、このパラメーターを使用して 実際 の親ウィンドウが決定されます。

トークンのキャッシュ

認証ブローカーは、更新とアクセス トークンのキャッシュを処理します。 カスタム キャッシュを設定する必要はありません。

サンプル アプリのビルド

MSAL Python GitHub リポジトリ内の Linux 上の認証ブローカーで MSAL Pythonを使用する方法を示すサンプル アプリを見つけることができます。 サンプル アプリは samples/console_app ディレクトリにあり、認証にブローカーを使用する方法の例が含まれています。

アプリの登録

Azure ポータルでアプリの登録を更新し、Linux 用のブローカー固有のリダイレクト URI を含めます。

https://login.microsoftonline.com/common/oauth2/nativeclient

Linux の依存関係

まず、Linux ディストリビューションに python3 がインストールされているかどうかを確認します。

python3 --version

そうでない場合は、ディストリビューションのパッケージ マネージャーを使用してインストールします。

debian/Ubuntu ベースの Linux ディストリビューションにインストールするには:

sudo add-apt-repository -y universe
sudo apt update
sudo apt install python3 python3-pip libwebkit2gtk-4.1-dev -y

Python依存関係

ブローカーを使用するには、PyPI のコア MSAL に加えて、ブローカー関連のパッケージをインストールする必要があります。

pip install "msal[broker]>=1.33.0b1,<2"

プロジェクトを作成

構成したら、 acquire_token_interactive を呼び出してトークンを取得できます。

import sys  # For simplicity, we'll read config file from 1st CLI param sys.argv[1]
import json
import logging
import requests
import msal

# Optional logging
# logging.basicConfig(level=logging.DEBUG)

var_authority = "https://login.microsoftonline.com/common"
var_client_id = "your-client-id-here"  # Replace with your app's client ID
var_username = "your-username-here"  # Replace with your username, e.g., "
var_scope = ["User.ReadBasic.All"]
# Removed unused variable to avoid confusion


# Create a preferably long-lived app instance which maintains a token cache (Default cache is in memory only).
app = msal.PublicClientApplication(
    var_client_id, 
    authority=var_authority,
    enable_broker_on_windows=True,
    enable_broker_on_wsl=True
    )

# The pattern to acquire a token looks like this.
result = None

# Firstly, check the cache to see if this end user has signed in before
accounts = app.get_accounts(username=var_username)
if accounts:
    logging.info("Account(s) exists in cache, probably with token too. Let's try.")
    result = app.acquire_token_silent(var_scope, account=accounts[0])

if not result:
    logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
    
    result = app.acquire_token_interactive(var_scope,parent_window_handle=app.CONSOLE_WINDOW_HANDLE)
    
if "access_token" in result:
    print("Access token is: %s" % result['access_token'])

else:
    print(result.get("error"))
    print(result.get("error_description"))
    print(result.get("correlation_id"))  # You may need this when reporting a bug
    if 65001 in result.get("error_codes", []):  # Not mean to be coded programatically, but...
        # AAD requires user consent for U/P flow
        print("Visit this to consent:", app.get_authorization_request_url(config["scope"]))