mcpField
A
auth0-wpf

auth0-wpf

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

auth0-wpf について

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

主な機能

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

活用シーン

  1. 01WPF アプリへの Auth0 認証追加
  2. 02ログインとログアウトのハンドラー設定
  3. 03Auth0 ネイティブアプリのコールバック URL 設定
  4. 04トークン更新とプロフィール取得の計画

インストール

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

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

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

同梱ファイル

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

references/
api.md
integration.md
setup.md

詳細

Auth0 WPF 統合

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

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

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

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

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

前提条件

  • .NET 6.0 SDK 以降(WPF には Windows が必要です)
  • Visual Studio 2022 または JetBrains Rider と .NET デスクトップ開発ワークロード
  • Windows 10 以降
  • Microsoft Edge WebView2 Runtime(Windows 11 に含まれています。Windows 10 ではインストール可能です)
  • ネイティブアプリケーションが設定された Auth0 アカウント
  • Node.js 20 以降(Auth0 CLI による自動セットアップ用)

使用しないケース

ユースケース推奨スキル
.NET MAUI クロスプラットフォームアプリauth0-maui
Windows Forms デスクトップアプリauth0-winforms
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.WPF
  2. Auth0 を設定:自動または手動で設定する方法については、セットアップガイドを参照してください。
  3. 認証を統合:Auth0Client の初期化を追加し、ログイン/ログアウトを XAML ボタンのクリックハンドラーに接続します。
  4. ビルドして検証:dotnet build

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

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

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

dotnet build

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

コールバック URL の設定

WPF 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 ダッシュボードで設定します。

  • 許可されたコールバック URL:https://{yourDomain}/mobile
  • 許可されたログアウト URL:https://{yourDomain}/mobile

完了条件

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

詳細なドキュメント

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

よくある間違い

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

テストに関する注意

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

テストチェックリスト:

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

関連スキル

  • auth0-winforms — Windows Forms デスクトップアプリ
  • 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 window (WebAuth flow with PKCE)
var loginResult = await client.LoginAsync();
if (!loginResult.IsError)
{
    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}");
    }
}

// Store the refresh token from login for later use
var refreshToken = loginResult.RefreshToken;

// Logout
await client.LogoutAsync();

// Refresh token (requires offline_access scope)
var refreshResult = await client.RefreshTokenAsync(refreshToken);
if (refreshResult.IsError == false)
{
    var newAccessToken = refreshResult.AccessToken;
}
MainWindow.xaml(WPF UI)
<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Auth0 WPF App" Height="450" Width="800">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button x:Name="LoginButton" Content="Login" Width="200" Height="40"
                    Margin="10" Click="LoginButton_Click" FontSize="16"/>
            <Button x:Name="LogoutButton" Content="Logout" Width="200" Height="40"
                    Margin="10" Click="LogoutButton_Click" FontSize="16"/>
        </StackPanel>
    </Grid>
</Window>
MainWindow.xaml.cs(WPF コードビハインド)
using Auth0.OidcClient;
using System.Diagnostics;

namespace MyApp;

public partial class MainWindow : Window
{
    private Auth0Client _client;

    public MainWindow()
    {
        InitializeComponent();

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

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

        if (loginResult.IsError)
        {
            Debug.WriteLine($"An error occurred during login: {loginResult.Error}");
            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, RoutedEventArgs e)
    {
        await _client.LogoutAsync();
    }
}

References

コメント