自作のChatGPTプラグインにAzure AD認証機能を実装する方法

ChatGPTのプラグイン作成方法については、前回のブログに記載しました。
https://blog.jbs.co.jp/entry/2023/06/08/121455

今回は、ChatGPTのプラグインにAzure AD認証機能を実装して、Azure Web AppsのようなPublicのWebサーバーに展開する方法について調べてみました。

システム構成イメージ

システムの構成イメージは下記になります。

ChatGPTのプラグイン実装だけを考慮すればAzure Web Appsに対するユーザーのAzure AD認証は必須ではありません。
ただ、Publicにデプロイした場合、不特定多数のユーザーに無制限に権限を与えるわけにもいかないので、Azure AD認証・認可されたユーザーのみにプラグインが利用できるようにAzure ADによる認証・認可を実装しています。

図に記載されている通り、ChatGPTはAzure AD認証を直接サポートしています。

プラグインの設定ファイル(ai-plugin.json)にAzure AD認証の詳細を記述することで、ChatGPTはAzure ADを通じて認証を行います。

認証機能の実装方法については、下記のサイトを参考にしました。

platform.openai.com

作業概要

ChatGPTのプラグインを自作し、それにAzure ADの認証機能を追加する流れは下記です。

1.Blazor Serverアプリケーションの作成
Visual Studioを使用してBlazor Serverアプリケーションを作成します。
2.Azure Web Appsへのデプロイ
作成したアプリケーションをAzure Web Appsにデプロイします。
3.Program.csのCORS設定の修正
Program.csのCORS設定を修正します。
これにより、異なるオリジンからのリクエストを許可します。
4.ai-plugin.jsonの修正
ai-plugin.jsonを修正し、APIやロゴのURL、auth設定を追記します。
これにより、プラグインの基本情報と認証方法が定義されます。
5.Azure Web Appsに再デプロイ
上記の変更を反映させるために、アプリケーションを再デプロイします。
6.ChatGPT Pluginsでの読み込み
ChatGPT PluginsでデプロイしたURLを指定してプラグインを読み込みます。
7.クライアントIDとシークレットの入力
Azure ADから取得したクライアントIDとシークレットを入力します。
8.OpenAIのIDの取得と追記
OpenAIのIDが取得できたら、それをai-plugin.jsonのverification_tokensに追記します。
9.Azure Web Appsに再デプロイ
ai-plugin.jsonをVisual Studioから再デプロイします。
10.別ユーザーでのChatGPT Pluginの読み込み
上記の認証が通ったら、別ユーザーでChatGPT Pluginを読み込みます。
Azure AD認証が失敗した場合、Azure ADアプリにリダイレクトURIを追記します。
11.再度の読み込みと認証
再度読み込みを実施し、認証が通れば成功です。

作業手順

Visual StudioでBlazor Serverアプリを作成

  • Visual Studio 2022を使用してBlazor Serverアプリを作成
    作業内容は概ね下記ブログに掲載した内容と同じです。 下記ブログの作業手順を参照して下さい。
    blog.jbs.co.jp .NETのバージョンは7を指定して下さい。
    ブログで紹介しているMicrosoft.AspNetCore.OpenApiが.NET 7以前には対応していません。 Image Description 今回はPublicのWeb Appsにデプロイするので、下記に記載する追加作業が必要です。
  • Visual Studioで認証の種類を設定
    Azure AD認証を行う為、Microsoft ID プラットフォームを選択します。
    フレームワークは、今回は.NET 7を選択します。 Image Description
  • Azure ADアプリケーションを新規作成
    画面右側の新規作成ボタンでAzure ADアプリケーションを新規に作成できます。
    Azure ADアプリケーションを作成済みであれば、所有しているアプリケーション欄に表示されるAzure ADアプリケーションを選択してください。
  • Microsoft ID プラットフォームの構成を確認
    Microsoft Graphや別のAPIへのアクセスは今回は不要なので、チェックしません。 Image Description
  • Visual StudioでMicrosoft IDを確認
    接続されましたと表示されていれば、Azure ADアプリケーションは作成できています。 Image Description

Azure Web Appsをデプロイ

  • デバッグ実行してAzure AD認証機能を確認
    デプロイする前に、Azure AD認証が設定できているか確認します。
    Image Description
    画面右上にログインユーザー名やLog Outボタンが表示されていれば、Azure AD認証は設定できています。 Image Description
  • Azure PortalでWeb Appsを作成
    Image Description
    ランタイムスタックは、上記までに作成したBlazor Serverアプリケーションと同じ.NET 7を選択します。
    オペレーティングシステムはWindowsを使用しました。
    Image Description
    Azure Portalで、Web Appsがデプロイされたことを確認します。 Image Description
  • Azure Web Appsの環境変数を設定
    Visual Studioで作成したアプリケーションのappsettings.jsonに記載されている内容を、Web Appsの環境変数に設定します。
    Web Appsの環境変数の設定が完了したら、appsettings.jsonに記載されているAzure ADについての情報は削除して下さい。(削除しないままデプロイするのは、セキュリティ上の問題があります。) Image Description Image Description
  • Visual StudioからWeb Appsをデプロイ
    ソリューション名を右クリックして、発行を選択します。
    Image Description
  • 発行プロファイルの追加を選択
    Azureを選択し、次へボタンを押します。
    Image Description
  • Azure App Serviceを選択
    Windowsを選択し、次へボタンを押します。 Image Description
  • デプロイ先のWeb Appsを選択
    Azure Portalで作成したWeb Appsを選択し、次へボタンを押します。
  • API Managementの設定
    今回は不要なので、左下にある「この手順をスキップする」をチェックして完了ボタンを押します。
  • Web Appsを発行
    発行ボタンを押して、Web Appsにデプロイします。 Image Description
  • 認証エラーの表示を確認
    Azure ADアプリケーションにredirect URIを設定していないので、エラーが表示されます。
    表示されているsignin-oidcのリンクをコピーします。 Image Description
  • Azure ADアプリケーションにリンクを設定
    リダイレクトURIに上記のsignin-oidcのリンクを追加します。 Image Description
  • アプリケーションIDの確認とクライアントシークレットを作成
    この後の作業で使用するので、アプリケーションIDの確認とクライアントシークレットの作成を行います。
    Image Description
    クライアントシークレットの値は保存されてしまうと後から確認できないので、保存する前にメモ帳などにコピーして下さい。(取り扱いにはご注意下さい)
    Image Description
    再度、デプロイしたWeb Appsのリンクをクリックしてログインできれば問題ありません。
    Image Description

Program.csを修正

  • Web AppsのURLを追記
    今回はWeb Appsを使用するので、CORSにWeb AppsのURLを追記します。 Image Description
  • .well-known配下のファイルをAzure AD認証から除外
    ai-plugin.jsonとfavicon.pngファイルは、Azure AD認証が必須の状態だと、ChatGPT側でマニフェストファイルとして読み込むことができません。(後述のChatGPTでのマニフェストファイル読み込みに必要)
    その為、下記の設定を追加してai-plugin.jsonとfavicon.pngをAzure AD認証がなくてもアクセス可能にします。
    また、swagger.yamlについてもChatGPT側で読み込むことができないので、Azure AD認証がなくてもアクセス可能にします。
app.UseRouting();

app.MapGet("/.well-known/ai-plugin.json", async context =>
{
    var fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), ".well-known"));
    var fileInfo = fileProvider.GetFileInfo("ai-plugin.json");
    if (fileInfo.Exists)
    {
        context.Response.ContentType = "application/json";
        await context.Response.SendFileAsync(fileInfo);
    }
    else
    {
        context.Response.StatusCode = 404;
    }
}).WithMetadata(new AllowAnonymousAttribute());

app.MapGet("/.well-known/favicon.png", async context =>
{
    var fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), ".well-known"));
    var fileInfo = fileProvider.GetFileInfo("favicon.png");
    if (fileInfo.Exists)
    {
        context.Response.ContentType = "image/png";
        await context.Response.SendFileAsync(fileInfo);
    }
    else
    {
        context.Response.StatusCode = 404;
    }
}).WithMetadata(new AllowAnonymousAttribute());

app.MapGet("/swagger/v1/swagger.yaml", async context =>
{
    var fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "swagger/v1"));
    var fileInfo = fileProvider.GetFileInfo("swagger.yaml");
    if (fileInfo.Exists)
    {
        context.Response.ContentType = "text/yaml";
        await context.Response.SendFileAsync(fileInfo);
    }
    else
    {
        context.Response.StatusCode = 404;
    }
}).WithMetadata(new AllowAnonymousAttribute());

app.UseAuthentication();
app.UseAuthorization();

ai-plugin.jsonを修正

  • 接続先の情報を追記
    Azure Web AppsのURLとAzure ADアプリケーションのテナントIDを追記します。
    Azure Web AppsのURLとAzure ADアプリケーションのテナントIDは、Azure Portalで確認して下さい。
{
  "schema_version": "v1",
  "name_for_human": "Connect to Cognitive Search",
  "name_for_model": "blazoracs",
  "description_for_human": "Plugin for conducting searches on Azure Cognitive Search",
  "description_for_model": "Plugin for conducting searches on Azure Cognitive Search",
  "auth": {
    "type": "oauth",
    "client_url": "https://login.microsoftonline.com/Azure ADアプリケーションのテナントID/oauth2/v2.0/authorize",
    "scope": "https://graph.microsoft.com/.default",
    "authorization_url": "https://login.microsoftonline.com/Azure ADアプリケーションのテナントID/oauth2/v2.0/token",
    "authorization_content_type": "application/x-www-form-urlencoded",
    "verification_tokens": {
      "openai": "OpenAIから取得するtokensを設定する(後述)"
    }
  },
    "api": {
      "type": "openapi",
      "url": "https://Azure Web AppsのURL.azurewebsites.net/swagger/v1/swagger.yaml",
      "is_user_authenticated": false
    },
    "logo_url": "https://Azure Web AppsのURL.azurewebsites.net/.well-known/favicon.png",
    "contact_email": "contact@email.com",
    "legal_info_url": "http://example.com/legal"
  }

Web Appsに再デプロイ

  • Web Appsの動作確認
    発行ボタンを押して、Web Appsに再度デプロイして動作を確認します。
    Image Description
    .well-knownフォルダ配下のファイルは、デフォルトではWeb Apps側にデプロイされないようです。
    デプロイしてもhttps://AzureWebAppsのURL.azurewebsites.net/.well-known/ai-plugin.jsonやfavicon.pngにアクセスできない場合は、ファイル名を右クリックして発行して下さい。
    Image Description

ChatGPT Pluginsで読み込み

  • Develop your own pluginを選択
    前回のブログに掲載しましたが、今回もDevelop your own pluginを選択してプラグインを設定します。
    Image Description
  • Web AppsのURLをDomainに記載
    前回はlocalhostでしたが、今回は作成したWeb AppsのURLを記載します。 Image Description
  • Azure ADアプリケーションのアプリケーションIDとクライアントシークレットを登録
    上段にアプリケーションID、下段にクライアントシークレットを登録してNextボタンを押します。 Image Description
  • OpenAIからtokenを受領
    OpenAIからtokenが発行されるので、この値をai-plugin.jsonに記載します。 Image Description
  • ai-plugin.jsonに記載
    ai-plugin.jsonのopenaiの箇所に、発行されたtokenを記載します。
    Image Description
    ai-plugin.jsonを更新したら、発行してクラウドに再度デプロイします。
    Image Description
    もう一度、この画面に戻って、Verify tokensボタンを押します。
    Image Description
    このReady to installの画面が表示されれば、プラグインの登録はできています。
    Install laterを選択します。(Install for meを選択しても問題ありません) Image Description

Web Appsのプラグインが使用できる事を確認

  • Plugin storeの画面を表示
    Install an unverified pluginを選択して、Web Appsで作成したプラグインをインストールします。 Image Description
  • Web AppsのURLを登録
    Web AppsのURLを記載して、Find pluginボタンを押します。
    Image Description
  • OpenAIの注意文を確認
    OpenAIからの注意文が表示されます。
    問題なければContinueボタンを押します。
    Image Description
  • ログイン画面の表示を確認
    プラグインを利用する為のログイン画面が表示されます。
    Log in with Connect to Cognitive Searchボタンを押します。
    Image Description
  • サインインのエラー画面を確認
    サインインエラーが表示されます。
    表示されるredirect URIをAzure ADアプリケーションに登録します。
    Image Description
  • Azure ADアプリケーションにリンクを設定
    リダイレクトURIに上記のエラーで表示されたcallbackのリンクを追加します。
  • 再度ログインを実行
    ログイン画面が表示されます。
  • プラグインの表示を確認
    ログインに成功し、プラグインが表示されれば作業完了です。

まとめ

私の進め方に問題があったのか、プラグインの登録は結構面倒な作業でした。

.well-knownフォルダがデフォルトではデプロイされなかったり、Azure AD認証でなんでも認証設定してしまうとai-plugin.jsonをChatGTP側から参照できなかったりと、いろいろハマりました。

.well-knownフォルダについては、Visual Studioの.csprojを編集すればデプロイ対象にすることもできると思います。

ai-plugin.jsonについては、公開用のWebサーバーを別途作成して管理する方法もあると思いました。
プラグインは初期登録さえ行えば、後はURLの登録とログインだけで利用できるので、利用するユーザーにはそんなに負担はかからないと思います。

プラグインをPublic用とPrivate用のどちらでも作成できる方法を学んでおけば、Microsoft 365 CopilotやSemantic Kernelを活用できるので今後も注力していきます。

執筆担当者プロフィール
株木 誠

株木 誠

先端技術部の株木です。 Azure OpenAI Service を活用するアプリ開発を担当しています。

担当記事一覧