mcpField
A
auth0-winforms

auth0-winforms

github.com/auth0セキュリティ55225 回インストール1 日前に更新
リポジトリ

auth0-winforms について

.NET の Windows Forms アプリに Auth0 の OIDC ログインとログアウトを組み込むスキルです。コーディングエージェント向けに、WebView2 の連携、コールバック設定、ビルド検証を案内します。

主な機能

  1. 01WebView2 による Auth0 ログイン
  2. 02OIDC 認可コードフローと PKCE
  3. 03ログインとログアウトの実装
  4. 04コールバック URL 設定ガイド
  5. 05ビルドとテストのチェックリスト

活用シーン

  1. 01WinForms アプリへの Auth0 認証追加
  2. 02ログインとログアウトのハンドラー設定
  3. 03Auth0 ネイティブアプリのコールバック URL 設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/auth0/agent-skills --skill auth0-winforms

インストール後、Claude Code で/auth0-winformsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api.md
integration.md
setup.md

詳細

Auth0 WinForms 統合

Windows Forms(WinForms)デスクトップアプリケーションに Auth0 認証を追加します。このスキルでは、Auth0.OidcClient.WinForms NuGet パッケージを統合します。このパッケージは WebView2 を使用してポップアップフォームに Auth0 のログインページを表示し、PKCE を使用した安全な OIDC ベースのログインおよびログアウトフローを実現します。

SDK は、WinForms の Form にホストされた WebView2 コントロール内で Auth0 Universal Login ページを開くことにより、WebAuth(PKCE を使用した OIDC 認可コードフロー)を実行します。Info.plist や AndroidManifest.xml への URL スキーム登録が必要なネイティブモバイル SDK とは異なり、WinForms SDK は WebView2 のナビゲーションイベント内ですべてのコールバックを処理するため、カスタム URL タイプやプロトコルハンドラーは必要ありません。

エージェントへの指示: SDK のセットアップ手順を案内する前に、次のコマンドを実行して最新リリースのバージョンを取得してください。

gh api repos/auth0/auth0-oidc-client-net/releases --jq '[.[] | select(.tag_name | startswith("winforms-")) | .tag_name | ltrimstr("winforms-")] | .[0]'

返されたバージョンを、以下の依存関係の記述でハードコードされたバージョンの代わりに使用してください。

前提条件

  • .NET 6.0 SDK 以降(WinForms には Windows が必要です)
  • Visual Studio 2022 または .NET デスクトップ開発ワークロードを備えた JetBrains Rider
  • Windows 10 以降
  • Microsoft Edge WebView2 Runtime(Windows 11 に付属。Windows 10 ではインストールできます)
  • Native アプリケーションが設定された Auth0 アカウント
  • Node.js 20 以降(Auth0 CLI による自動セットアップ用)

使用しない場合

ユースケース推奨スキル
.NET MAUI クロスプラットフォームアプリauth0-maui
WPF デスクトップアプリauth0-wpf
ASP.NET Core サーバーサイド Web アプリauth0-aspnetcore-authentication
ASP.NET Core Web API(JWT 検証)auth0-aspnetcore-api
iOS 専用の Swift アプリauth0-swift
Android 専用の Kotlin アプリauth0-android

クイックスタートのワークフロー

エージェントへの指示: 作業を開始する前に、ユーザーのプロジェクトを調べてください。

  1. .csproj ファイルの TargetFramework から .NET のバージョンを特定します。
  2. コードベースに既存の認証プロバイダーがあるか確認します。既存の Auth0Client または WebViewBrowser の使用箇所を検索し、見つかった場合は再利用します。
  3. プロジェクトの名前空間とディレクトリの規約を確認します。
  1. SDK をインストールする:dotnet add package Auth0.OidcClient.WinForms
  2. Auth0 を設定する:自動または手動での設定については、セットアップガイドを参照してください。
  3. 認証を統合する:Auth0Client の初期化を追加し、ログイン/ログアウト処理をボタンのクリックハンドラーに関連付けます。
  4. ビルドして確認する:dotnet build

エージェントへの指示: Auth0Client の設定を記述する際は、次の点に従ってください。

  • このスキルの統合ガイドに記載されているコードパターンをそのまま使用します。
  • SDK は WebView2 を使用してポップアップフォームにログインページを表示するため、カスタムブラウザーのセットアップは不要です。
  • デフォルトのコールバック URL は https://{yourDomain}/mobile です。この URL を Auth0 Dashboard の Allowed Callback URLs と Allowed Logout URLs に追加する必要があります。
  • https://{domain}/ios/{bundleId}/callback などのプラットフォーム固有のパターンを使用するネイティブモバイル SDK とは異なり、WinForms ではよりシンプルな https://{domain}/mobile 形式のコールバックを使用します。

設定とコードを記述したら、ビルドが成功することを確認してください。

dotnet build

ビルドに失敗した場合は、問題の修正を試みてください。5~6 回試しても失敗する場合は、ユーザーに支援を求めてください。

コールバック URL の設定

WinForms SDK では、デフォルトのコールバック URL として https://{yourDomain}/mobile を使用します。これはモバイルネイティブ SDK とは異なります。

  • モバイル SDK では、https://{domain}/ios/{bundleId}/callback や https://{domain}/android/{packageName}/callback のようなプラットフォーム固有のコールバックを使用します
  • WPF/WinForms では、汎用の https://{yourDomain}/mobile コールバックを使用します

コールバックは WebView2 コントロールの NavigationStarting イベントによってインターセプトされるため、システムレベルの URL スキーム登録は不要です。Info.plist、AndroidManifest.xml、Windows プロトコルハンドラーを設定する必要はありません。

Auth0 Dashboard で次のように設定します。

  • Allowed Callback URLs:https://{yourDomain}/mobile
  • Allowed Logout URLs:https://{yourDomain}/mobile

完了条件

  • Auth0.OidcClient.WinForms パッケージをインストール済み
  • Auth0Client に Domain と ClientId を設定済み
  • ログイン/ログアウトのフローが動作する(認証用の WebView2 ポップアップが開く)
  • ログイン後にユーザープロファイルのクレームにアクセスできる
  • コールバック URL https://{yourDomain}/mobile を Auth0 Dashboard に登録済み
  • エラーなしでビルドが成功する
  • 実機でテスト済み(リモートデスクトップではなく、物理的な Windows マシン)

詳細なドキュメント

  • セットアップガイド — Auth0 テナントの設定、SDK のインストール、コールバック URL の設定
  • 統合パターン — ログイン/ログアウトのフロー、トークンの更新、ユーザープロファイル、エラー処理
  • API リファレンスとテスト — Auth0ClientOptions の完全なリファレンス、クレーム、テストチェックリスト、トラブルシューティング

よくある間違い

間違い修正方法
Auth0 Dashboard でアプリの種類が Native に設定されていないDashboard の設定でアプリケーションの種類を「Native」に変更します
Auth0 Dashboard にコールバック URL が設定されていないhttps://{yourDomain}/mobile を Allowed Callback URLs と Allowed Logout URLs の両方に追加します
Domain の設定に https:// のプレフィックスを使用しているDomain はホスト名のみを指定します(例:https://tenant.auth0.com ではなく tenant.auth0.com)
WebView2 Runtime がインストールされていないWindows 10 に Microsoft Edge WebView2 Runtime をインストールします(Windows 11 には含まれています)
トークン更新用の offline_access スコープを要求していないAuth0ClientOptions の Scope に offline_access を追加します
ClientSecret をコードに保存しているネイティブアプリでは Client Secret を使用しないため、削除します
レジストリ/マニフェストで URL スキームを登録しようとしているWinForms は WebView2 をプロセス内で使用するため、URL スキームの登録は不要です(AppxManifest が必要な MAUI とは異なります)

テストに関する注意事項

エージェントへの指示: ユーザーに実機でテストするよう伝えてください。一部の WebView2 の動作(ポップアップウィンドウ、証明書の処理)は、リモートデスクトップ環境や仮想マシン環境では、物理的な Windows マシンと異なる場合があります。リリース前に、実機でログイン → WebView2 → コールバック → トークンの一連のフローをテストしてください。

テストチェックリスト:

  • ログインフロー:ログインをクリック → WebView2 ポップアップが開く → 認証する → ポップアップが閉じる → ユーザー情報が表示される
  • ログアウトフロー:ログアウトをクリック → WebView2 ポップアップが開く → セッションがクリアされる → ポップアップが閉じる
  • トークンの更新:保存済みのリフレッシュトークンを使用した RefreshTokenAsync が動作する
  • キャンセル:ユーザーが WebView2 フォームを閉じる → アプリが UserCancel を適切に処理する
  • 実機:実際の Windows マシンでテストする(仮想環境だけではなく)
  • 複数回のログイン:ログアウト後もログインが動作することを確認する(古い状態が残っていない)

関連スキル

  • auth0-wpf — WPF デスクトップアプリ
  • auth0-maui — .NET MAUI クロスプラットフォームアプリ
  • auth0-aspnetcore-authentication — ASP.NET Core サーバーサイド Web アプリ
  • auth0-aspnetcore-api — JWT 検証を使用した ASP.NET Core Web API

クイックリファレンス

using Auth0.OidcClient;
using System.Diagnostics;

// Initialize client
var client = new Auth0Client(new Auth0ClientOptions
{
    Domain = "{yourDomain}",
    ClientId = "{yourClientId}",
    Scope = "openid profile email offline_access"
});

// Login — opens WebView2 popup form (WebAuth flow with PKCE)
var loginResult = await client.LoginAsync();
if (loginResult.IsError == false)
{
    var user = loginResult.User;
    var name = user.FindFirst(c => c.Type == "name")?.Value;
    var email = user.FindFirst(c => c.Type == "email")?.Value;
    var picture = user.FindFirst(c => c.Type == "picture")?.Value;

    Debug.WriteLine($"name: {name}");
    Debug.WriteLine($"email: {email}");

    foreach (var claim in loginResult.User.Claims)
    {
        Debug.WriteLine($"{claim.Type} = {claim.Value}");
    }
}

// Logout
await client.LogoutAsync();

// Refresh token (requires offline_access scope)
var refreshToken = loginResult.RefreshToken;
var refreshResult = await client.RefreshTokenAsync(refreshToken);
if (refreshResult.IsError == false)
{
    var newAccessToken = refreshResult.AccessToken;
}
Form1.cs(WinForms の完全な例)
using Auth0.OidcClient;
using System.Diagnostics;

namespace MyApp;

public partial class Form1 : Form
{
    private Auth0Client _client;
    private Button loginButton;
    private Button logoutButton;

    public Form1()
    {
        InitializeComponent();

        _client = new Auth0Client(new Auth0ClientOptions
        {
            Domain = "{yourDomain}",
            ClientId = "{yourClientId}",
            Scope = "openid profile email offline_access"
        });

        loginButton = new Button
        {
            Text = "Log In",
            Width = 120,
            Height = 40,
            Left = (ClientSize.Width - 120) / 2,
            Top = (ClientSize.Height - 40) / 2
        };
        loginButton.Click += loginButton_Click;
        Controls.Add(loginButton);

        logoutButton = new Button
        {
            Text = "Log Out",
            Width = 120,
            Height = 40,
            Left = (ClientSize.Width - 120) / 2,
            Top = (ClientSize.Height - 40) / 2 + 50
        };
        logoutButton.Click += logoutButton_Click;
        Controls.Add(logoutButton);
    }

    private async void loginButton_Click(object sender, EventArgs e)
    {
        var loginResult = await _client.LoginAsync();

        if (loginResult.IsError)
        {
            Debug.WriteLine($"Error: {loginResult.Error}");
            Debug.WriteLine($"Description: {loginResult.ErrorDescription}");
            return;
        }

        var user = loginResult.User;
        var name = user.FindFirst(c => c.Type == "name")?.Value;
        var email = user.FindFirst(c => c.Type == "email")?.Value;
        var picture = user.FindFirst(c => c.Type == "picture")?.Value;

        Debug.WriteLine($"name: {name}");
        Debug.WriteLine($"email: {email}");

        foreach (var claim in loginResult.User.Claims)
        {
            Debug.WriteLine($"{claim.Type} = {claim.Value}");
        }
    }

    private async void logoutButton_Click(object sender, EventArgs e)
    {
        await _client.LogoutAsync();
    }
}

References

コメント