Loading...
Loading...
Use when adding Auth0 login, logout, or token management to a WPF desktop application. Integrates Auth0.OidcClient.WPF — use even if the user says "add login to my WPF app" or "add Auth0 to my Windows desktop app".
npx skill4agent add auth0/agent-skills auth0-wpfAuth0.OidcClient.WPFAgent instruction: Before providing SDK setup instructions, fetch the latest release version by running:bashgh api repos/auth0/auth0-oidc-client-net/releases --jq '[.[] | select(.tag_name | startswith("wpf-")) | .tag_name | ltrimstr("wpf-")] | .[0]'Use the returned version in all dependency lines instead of any hardcoded version below.
| Use Case | Recommended Skill |
|---|---|
| .NET MAUI cross-platform app | |
| Windows Forms desktop app | |
| ASP.NET Core server-side web app | |
| ASP.NET Core Web API (JWT validation) | |
| iOS-only Swift app | |
| Android-only Kotlin app | |
Agent instruction: Before starting, examine the user's project:
- Identify the .NET version from the
file (.csproj)TargetFramework- Check if there is already an existing authentication provider in the codebase — search for existing
orAuth0Clientusage and reuse if foundWebViewBrowser- Note the project's namespace and directory conventions
dotnet add package Auth0.OidcClient.WPFAuth0Clientdotnet buildAgent instruction: When writing the Auth0Client configuration:
- Use the exact code patterns from this skill's integration guide.
- The SDK uses WebView2 to show the login page in a popup window — no custom browser setup needed.
- The default callback URL is
— this must be added to Auth0 Dashboard Allowed Callback URLs and Allowed Logout URLs.https://{yourDomain}/mobile- Unlike native mobile SDKs that use
or similar platform-specific patterns, WPF uses the simplerhttps://{domain}/ios/{bundleId}/callbackcallback format.https://{domain}/mobileAfter writing configuration and code, verify the build succeeds:bashdotnet buildIf the build fails, attempt to fix the issue. After 5-6 failed attempts, ask the user for help.
https://{yourDomain}/mobilehttps://{domain}/ios/{bundleId}/callbackhttps://{domain}/android/{packageName}/callbackhttps://{yourDomain}/mobileNavigationStartinghttps://{yourDomain}/mobilehttps://{yourDomain}/mobileAuth0.OidcClient.WPFAuth0Clienthttps://{yourDomain}/mobileAuth0ClientOptions| Mistake | Fix |
|---|---|
| App type not set to Native in Auth0 Dashboard | Change application type to "Native" in Dashboard settings |
| Missing callback URL in Auth0 Dashboard | Add |
Using | Domain should be hostname only (e.g., |
| WebView2 Runtime not installed | Install Microsoft Edge WebView2 Runtime on Windows 10 (included with Windows 11) |
Not requesting | Add |
| Storing ClientSecret in code | Native apps do NOT use a Client Secret — remove it |
| Trying to register URL scheme in registry/manifest | WPF uses WebView2 in-process — no URL scheme registration needed (unlike MAUI which needs AppxManifest) |
Agent instruction: Remind the user to test on a physical device. Some WebView2 behaviors (popup windows, certificate handling) may differ in remote desktop or virtual machine environments vs. physical Windows machines. Test the full login → WebView2 → callback → token flow on real hardware before shipping.
RefreshTokenAsyncUserCancelusing 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;
}<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>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();
}
}