auth0-wpf について
.NET の WPF デスクトップアプリに Auth0 の OIDC ログインとログアウトを組み込むスキルです。コーディングエージェント向けに、WebView2、コールバック、トークンの設定とビルド検証を案内します。
主な機能
- 01WebView2 による Auth0 ログイン
- 02OIDC 認可コードフローと PKCE
- 03ログインとログアウトの実装
- 04コールバック URL 設定ガイド
- 05トークン更新とプロフィールのガイド
- 06ビルドとテストのチェックリスト
活用シーン
- 01WPF アプリへの Auth0 認証追加
- 02ログインとログアウトのハンドラー設定
- 03Auth0 ネイティブアプリのコールバック URL 設定
- 04トークン更新とプロフィール取得の計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ auth0/ agent-skills --skill auth0-wpfインストール後、Claude Code で/auth0-wpfを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api.mdintegration.mdsetup.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 |
クイックスタートのワークフロー
エージェントへの指示: 開始する前に、ユーザーのプロジェクトを調べてください。
.csprojファイルのTargetFrameworkから .NET のバージョンを特定します- コードベースに既存の認証プロバイダーがあるか確認します。既存の
Auth0ClientまたはWebViewBrowserの使用箇所を検索し、見つかった場合は再利用します- プロジェクトの名前空間とディレクトリの規則を確認します
- SDK をインストール:
dotnet add package Auth0.OidcClient.WPF - Auth0 を設定:自動または手動で設定する方法については、セットアップガイドを参照してください。
- 認証を統合:
Auth0Clientの初期化を追加し、ログイン/ログアウトを XAML ボタンのクリックハンドラーに接続します。 - ビルドして検証:
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();
}
}