> ## Documentation Index
> Fetch the complete documentation index at: https://auth0.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Add Login to Your WPF or WinForms Application

> Add Auth0 login, logout, and user profile to a WPF or WinForms application using the Auth0 OIDC Client for .NET

export const HowToSchema = () => <script type="application/ld+json">
    {'{"@context":"https://schema.org","@type":"HowTo"}'}
  </script>;

<HowToSchema />

<Accordion title="Use AI to integrate Auth0" icon="microchip-ai" iconType="solid" defaultOpen>
  If you use an AI coding assistant like Claude Code, Cursor, or GitHub Copilot, you can add Auth0 authentication automatically in minutes using [agent skills](https://agentskills.io/home).

  **Install:**

  ```bash theme={null}
  npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-wpf --skill auth0-winforms
  ```

  **Then ask your AI assistant:**

  ```text theme={null}
  Add Auth0 authentication to my WPF or WinForms app
  ```

  Your AI assistant will automatically create your Auth0 application, fetch credentials, install the Auth0 OidcClient SDK, configure callback URLs, and implement login/logout flows. [Full agent skills documentation →](/docs/quickstart/agent-skills)
</Accordion>

<Note>
  **Prerequisites:** Before you begin, ensure you have the following:

  * **[.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)** or higher (or .NET Framework 4.6.2 for legacy projects)
  * **[Visual Studio 2022](https://visualstudio.microsoft.com/)** or VS Code with the C# Dev Kit

  **.NET Version Compatibility:** This quickstart works with **.NET 8.0**, **.NET 9.0**, and **.NET Framework 4.6.2**.
</Note>

## Get Started

This quickstart demonstrates how to add Auth0 authentication to a WPF or WinForms desktop application. You'll configure Auth0, install the SDK, and add login, logout, and user profile display using the Auth0 OIDC Client for [WPF](https://www.nuget.org/packages/Auth0.OidcClient.WPF/) and [WinForms](https://www.nuget.org/packages/Auth0.OidcClient.WinForms/).

<Steps>
  <Step title="Create your application" stepNumber={1}>
    If you already have a WPF or WinForms project, skip to the next step.

    <Tabs>
      <Tab title=".NET CLI">
        Create a new project and open its directory:

        <Tabs>
          <Tab title="WPF">
            ```bash theme={null}
            dotnet new wpf -n MyApp
            cd MyApp
            ```
          </Tab>

          <Tab title="WinForms">
            ```bash theme={null}
            dotnet new winforms -n MyApp
            cd MyApp
            ```
          </Tab>
        </Tabs>
      </Tab>

      <Tab title="Visual Studio">
        1. Open Visual Studio 2022 and click **Create a new project**
        2. Search for **WPF Application** or **Windows Forms App**
        3. Select the C# template and click **Next**
        4. Enter a project name and choose a location, then click **Next**
        5. Select **.NET 8.0** (or higher) as the target framework and click **Create**
      </Tab>
    </Tabs>
  </Step>

  <Step title="Configure Auth0" stepNumber={2}>
    To use Auth0 services, you need to have an application set up in the Auth0 Dashboard. The Auth0 application is where you configure how authentication works for your project.

    ### Configure an application

    Go to [Auth0 Dashboard](https://manage.auth0.com) → **Applications** → **Applications** and create a new application:

    1. Click **Create Application**
    2. Enter a name for your application
    3. Select **Native** as the application type
    4. Click **Create**

    From the **Settings** tab, note your **Domain** and **Client ID** — you'll need these to initialize the SDK.

    ### Configure Callback URLs

    A callback URL is a URL in your application where Auth0 redirects users after they have authenticated. If not set, users will not be returned to your application after they log in.

    In your Application Settings, add the following to **Allowed Callback URLs**:

    ```
    https://{yourDomain}/mobile
    ```

    ### Configure Logout URLs

    A logout URL is a URL in your application where Auth0 redirects users after they have logged out. If not set, users will not be able to log out from your application and will receive an error.

    In your Application Settings, add the following to **Allowed Logout URLs**:

    ```
    https://{yourDomain}/mobile
    ```
  </Step>

  <Step title="Install the Auth0 SDK" stepNumber={3}>
    Auth0 provides separate NuGet packages for WPF and WinForms. Install the one that matches your project type.

    <Tabs>
      <Tab title="NuGet Package Manager">
        Open the **Package Manager Console** (Tools → NuGet Package Manager → Package Manager Console) and run:

        ```powershell theme={null}
        # WPF
        Install-Package Auth0.OidcClient.WPF

        # WinForms
        Install-Package Auth0.OidcClient.WinForms
        ```
      </Tab>

      <Tab title=".NET CLI">
        ```bash theme={null}
        # WPF
        dotnet add package Auth0.OidcClient.WPF

        # WinForms
        dotnet add package Auth0.OidcClient.WinForms
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Instantiate the Auth0Client" stepNumber={4}>
    To integrate Auth0 into your application, instantiate an `Auth0Client` with your Auth0 **Domain** and **Client ID**. Add a private field and initialize it inside the existing constructor in your main window or form.

    <Tabs>
      <Tab title="WPF">
        Open `MainWindow.xaml.cs` and update it as follows:

        ```csharp MainWindow.xaml.cs lines theme={null}
        using Auth0.OidcClient;

        // In case you have chosen a different name for your application,
        // ensure to update the namespace accordingly.
        namespace MyApp; 

        public partial class MainWindow : Window
        {
            private Auth0Client _client;

            public MainWindow()
            {
                InitializeComponent();

                _client = new Auth0Client(new Auth0ClientOptions
                {
                    Domain = "{yourDomain}",
                    ClientId = "{yourClientId}"
                });
            }
        }
        ```
      </Tab>

      <Tab title="WinForms">
        Open `Form1.cs` (or your main form file) and update it as follows:

        ```csharp Form1.cs lines theme={null}
        using Auth0.OidcClient;

        // In case you have chosen a different name for your application,
        // ensure to update the namespace accordingly.
        namespace MyApp;

        public partial class Form1 : Form
        {
            private Auth0Client _client;

            public Form1()
            {
                InitializeComponent();

                _client = new Auth0Client(new Auth0ClientOptions
                {
                    Domain = "{yourDomain}",
                    ClientId = "{yourClientId}"
                });
            }
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Add login to your application" stepNumber={5}>
    Use the SDK's `LoginAsync()` method to log users in. When called, it opens a popup window with the Auth0 Universal Login page. After successful authentication, Auth0 redirects to the callback URL, and the SDK returns a `LoginResult`.

    First, add a login button to your UI:

    <Tabs>
      <Tab title="WPF">
        Open `MainWindow.xaml` and add a `Button` inside the `<Grid>`:

        ```xml MainWindow.xaml lines theme={null}
        <Grid>
            <Button x:Name="LoginButton"
                    Content="Log In"
                    Width="120" Height="40"
                    HorizontalAlignment="Center" VerticalAlignment="Center"
                    Click="LoginButton_Click" />
        </Grid>
        ```

        Then add the click handler in `MainWindow.xaml.cs`:

        ```csharp MainWindow.xaml.cs lines theme={null}
        private async void LoginButton_Click(object sender, RoutedEventArgs e)
        {
            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;
            }
        }
        ```
      </Tab>

      <Tab title="WinForms">
        Open `Form1.cs` and add the login button programmatically in the constructor, then add the click handler:

        ```csharp Form1.cs lines theme={null}
        using Auth0.OidcClient;

        namespace MyApp;

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

            public Form1()
            {
                InitializeComponent();

                _client = new Auth0Client(new Auth0ClientOptions
                {
                    Domain = "{yourDomain}",
                    ClientId = "{yourClientId}"
                });

                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);
            }

            private async void loginButton_Click(object sender, EventArgs e)
            {
                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;
                }
            }
        }
        ```
      </Tab>
    </Tabs>

    If there is no error, you can access `LoginResult.User`, `LoginResult.IdentityToken`, `LoginResult.AccessToken`, and `LoginResult.RefreshToken` on the result.
  </Step>

  <Step title="Add logout to your application" stepNumber={6}>
    Use the SDK's `LogoutAsync()` method to log users out. This opens a popup window, redirects to Auth0's logout endpoint to clear the session, then redirects back to the logout URL you configured.

    First, add a logout button to your UI:

    <Tabs>
      <Tab title="WPF">
        Open `MainWindow.xaml` and add a logout `Button` next to the login button:

        ```xml MainWindow.xaml lines theme={null}
            <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>
        ```

        Then add the click handler in `MainWindow.xaml.cs`:

        ```csharp MainWindow.xaml.cs lines theme={null}
        private async void LogoutButton_Click(object sender, RoutedEventArgs e)
        {
            await _client.LogoutAsync();
        }
        ```
      </Tab>

      <Tab title="WinForms">
        Open `Form1.cs` and add the logout button in the constructor, then add its click handler:

        ```csharp Form1.cs lines theme={null}
        private Button logoutButton;

        public Form1()
        {
            // ... existing constructor code ...

            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 logoutButton_Click(object sender, EventArgs e)
        {
            await _client.LogoutAsync();
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Show user profile information" stepNumber={7}>
    The `LoginResult.User` property is a [ClaimsPrincipal](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsprincipal) containing the authenticated user's profile. Query the claims to display user information in your application.

    ```csharp lines theme={null}
    if (loginResult.IsError == false)
    {
        Debug.WriteLine($"name: {loginResult.User.FindFirst(c => c.Type == "name")?.Value}");
        Debug.WriteLine($"email: {loginResult.User.FindFirst(c => c.Type == "email")?.Value}");
    }
    ```

    To see all claims returned in the ID token:

    ```csharp lines theme={null}
    if (loginResult.IsError == false)
    {
        foreach (var claim in loginResult.User.Claims)
        {
            Debug.WriteLine($"{claim.Type} = {claim.Value}");
        }
    }
    ```
  </Step>
</Steps>

<Check>
  **Checkpoint**

  You should now have a working Auth0-integrated WPF or WinForms application. Run your application and verify that:

  * Clicking the login button opens the Auth0 Universal Login page in a popup window.
  * You can log in or sign up.
  * After authentication, you can access user information from `LoginResult.User`.
  * Clicking the logout button clears the session and redirects to your logout URL.
</Check>

***

## Advanced Usage

<Accordion title="Handle login errors">
  Check `LoginResult.IsError` before accessing tokens or user properties. The `Error` and `ErrorDescription` properties contain details when authentication fails.

  ```csharp lines theme={null}
  var loginResult = await _client.LoginAsync();

  if (loginResult.IsError)
  {
      Debug.WriteLine($"An error occurred during login: {loginResult.Error}");
      // loginResult.ErrorDescription contains the full error message
      return;
  }

  // Safe to access tokens and user here
  Debug.WriteLine($"id_token: {loginResult.IdentityToken}");
  Debug.WriteLine($"access_token: {loginResult.AccessToken}");
  ```

  If the user closes the login popup without authenticating, `LoginAsync()` returns a result with `BrowserResultType.UserCancel`. This is expected behavior — do not treat it as an error.
</Accordion>

<Accordion title="Refresh tokens">
  To get a new access token without requiring the user to log in again, use `RefreshTokenAsync()` with the refresh token from the initial `LoginResult`.

  ```csharp lines theme={null}
  // Request offline_access scope to receive a refresh token
  _client = new Auth0Client(new Auth0ClientOptions
  {
      Domain = "{yourDomain}",
      ClientId = "{yourClientId}",
      Scope = "openid profile email offline_access"
  });

  // Store refresh token from initial login
  var refreshToken = loginResult.RefreshToken;

  // Exchange for new tokens later
  var refreshResult = await _client.RefreshTokenAsync(refreshToken);

  if (refreshResult.IsError == false)
  {
      var newAccessToken = refreshResult.AccessToken;
  }
  ```

  <Info>
    Refresh tokens require the `offline_access` scope and must be enabled in your Auth0 Application Settings under **Refresh Token Rotation**.
  </Info>
</Accordion>

***

## Additional Resources

<CardGroup cols={3}>
  <Card title="SDK Repository" icon="github" href="https://github.com/auth0/auth0-oidc-client-net">
    Source code, release notes, and issue tracker for the Auth0 OIDC Client for .NET
  </Card>

  <Card title="User Profiles" icon="user" href="/docs/manage-users/user-accounts/user-profiles">
    Learn about user profile claims and the /userinfo endpoint
  </Card>

  <Card title="Community Forum" icon="comments" href="https://community.auth0.com/">
    Get help from the Auth0 community
  </Card>
</CardGroup>

***

## Common Issues

<AccordionGroup>
  <Accordion title="Login popup opens but authentication never completes">
    **Problem:** The WebView2 popup window opens and shows the login page, but after entering credentials nothing happens.

    **Solution:** The Microsoft Edge WebView2 Runtime is not installed on the machine. Install it from the [Microsoft WebView2 download page](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). WebView2 ships with Windows 11 and recent Windows 10 builds, but must be separately installed on older systems.
  </Accordion>

  <Accordion title="Callback URL mismatch error">
    **Problem:** After logging in, Auth0 returns a `callback URL mismatch` error.

    **Solution:** The redirect URI used by the SDK does not match any value in your **Allowed Callback URLs** in the Auth0 Dashboard. Add `https://{yourDomain}/mobile` to Allowed Callback URLs in your Application Settings. The SDK uses this URL by default.
  </Accordion>

  <Accordion title="Logout URL mismatch error">
    **Problem:** After logging out, Auth0 returns an error about an unrecognized logout URL.

    **Solution:** Add `https://{yourDomain}/mobile` to **Allowed Logout URLs** in your Application Settings.
  </Accordion>

  <Accordion title="LoginResult.IsError is true after login">
    **Problem:** `LoginResult.IsError` is `true` but there is no clear indication of the cause.

    **Solution:** Check `LoginResult.Error` and `LoginResult.ErrorDescription` for details:

    ```csharp lines theme={null}
    if (loginResult.IsError)
    {
        Debug.WriteLine($"Error: {loginResult.Error}");
        Debug.WriteLine($"Description: {loginResult.ErrorDescription}");
    }
    ```

    Common causes:

    * The application type in the Auth0 Dashboard is not set to **Native**
    * **OIDC Conformant** is not enabled under Advanced Settings → OAuth
    * The **JSON Web Token Signature Algorithm** is not set to **RS256**
  </Accordion>

  <Accordion title="RefreshToken is null after login">
    **Problem:** `LoginResult.RefreshToken` is `null`.

    **Solution:** The `offline_access` scope is required to receive a refresh token. Add it to the `Scope` option:

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

    Also ensure **Refresh Token Rotation** is enabled in your Application Settings in the Auth0 Dashboard.
  </Accordion>
</AccordionGroup>
