diff --git a/apps/docs/components/framework_selector.tsx b/apps/docs/components/framework_selector.tsx
index fca729894..814c0dcbc 100644
--- a/apps/docs/components/framework_selector.tsx
+++ b/apps/docs/components/framework_selector.tsx
@@ -4,8 +4,8 @@ import { useSearchParams } from 'next/navigation';
import { Tabs } from 'fumadocs-ui/components/tabs';
import { ReactNode, Suspense, useMemo } from 'react';
-const FRAMEWORKS = ['angular', 'astro', 'django', 'expressjs', 'fastapi', 'fastify', 'flask', 'flutter', 'go', 'hono', 'laravel', 'nestjs', 'nextjs', 'nuxt', 'qwik', 'react', 'solidstart', 'spring', 'symfony', 'svelte', 'vue'];
-const DISPLAY_NAMES = ['Angular', 'Astro', 'Django', 'Express.js', 'FastAPI', 'Fastify', 'Flask', 'Flutter', 'Go', 'Hono', 'Laravel', 'NestJS', 'Next.js', 'Nuxt', 'Qwik', 'React', 'SolidStart', 'Spring', 'Symfony', 'Svelte', 'Vue.js'];
+const FRAMEWORKS = ['angular', 'dotnet', 'astro', 'django', 'expressjs', 'fastapi', 'fastify', 'flask', 'flutter', 'go', 'hono', 'laravel', 'nestjs', 'nextjs', 'nuxt', 'qwik', 'react', 'solidstart', 'spring', 'symfony', 'svelte', 'vue'];
+const DISPLAY_NAMES = ['Angular', 'ASP.NET Core', 'Astro', 'Django', 'Express.js', 'FastAPI', 'Fastify', 'Flask', 'Flutter', 'Go', 'Hono', 'Laravel', 'NestJS', 'Next.js', 'Nuxt', 'Qwik', 'React', 'SolidStart', 'Spring', 'Symfony', 'Svelte', 'Vue.js'];
function FrameworkSelectorInner({ children }: { children: ReactNode }) {
const searchParams = useSearchParams();
diff --git a/apps/docs/content/guides/start/quickstart.mdx b/apps/docs/content/guides/start/quickstart.mdx
index 8bdc2de8d..9869d45d7 100644
--- a/apps/docs/content/guides/start/quickstart.mdx
+++ b/apps/docs/content/guides/start/quickstart.mdx
@@ -83,6 +83,12 @@ ZITADEL automatically configures the best security settings for your selected fr
postLogoutRedirectUrl="http://localhost:3000/api/auth/logout/callback">
+
+
+
+
+
+
+
@@ -292,6 +301,9 @@ ZITADEL handles the complexity of the OIDC handshake so your app stays secure wi
- [Node.js](https://nodejs.org/)
- [npm](https://www.npmjs.com/)
+
+ - [.NET SDK 8 or later](https://dotnet.microsoft.com/download)
+
- [Python](https://www.python.org/)
- [Poetry](https://python-poetry.org/)
@@ -383,6 +395,12 @@ ZITADEL handles the complexity of the OIDC handshake so your app stays secure wi
cd example-auth-astro
```
+
+ ```bash
+ git clone https://github.com/zitadel/example-auth-dotnet.git
+ cd example-auth-dotnet
+ ```
+
```bash
git clone https://github.com/zitadel/example-auth-django.git
@@ -534,6 +552,19 @@ ZITADEL handles the complexity of the OIDC handshake so your app stays secure wi
NEXTAUTH_URL="http://localhost:3000"
```
+
+ 1. Copy+paste the .env.example to .env
+ 2. Update the ZITADEL_CLIENT_ID, ZITADEL_CLIENT_SECRET and ZITADEL_DOMAIN with the client id and issuer you collected in Step 5.
+
+ ```bash
+ PORT=3000
+ SESSION_DURATION=3600
+ ZITADEL_DOMAIN="https://your-zitadel-domain"
+ ZITADEL_CLIENT_ID="your-zitadel-application-client-id"
+ ZITADEL_CLIENT_SECRET="your-randomly-generated-client-secret"
+ ZITADEL_POST_LOGOUT_URL="http://localhost:3000/auth/logout/callback"
+ ```
+
1. Copy+paste the .env.example to .env
2. Update the ZITADEL_CLIENT_ID and ZITADEL_DOMAIN with the client id and issuer you collected in Step 5.
@@ -854,6 +885,14 @@ ZITADEL handles the complexity of the OIDC handshake so your app stays secure wi

+
+ ```bash
+ make start
+ ```
+
+ Your app will be live at `http://localhost:3000`.
+
+
```bash
make start
diff --git a/apps/docs/content/sdk-examples/dotnet.mdx b/apps/docs/content/sdk-examples/dotnet.mdx
new file mode 100644
index 000000000..52fcd9a68
--- /dev/null
+++ b/apps/docs/content/sdk-examples/dotnet.mdx
@@ -0,0 +1,78 @@
+---
+title: ASP.NET Core
+sidebar_label: ASP.NET Core
+framework_url: https://learn.microsoft.com/aspnet/core/
+auth_library: "Microsoft.AspNetCore.Authentication.OpenIdConnect"
+auth_library_url: https://learn.microsoft.com/aspnet/core/security/authentication/openid-connect
+example_repo: https://github.com/zitadel/example-auth-dotnet
+auth_flow: pkce
+status: stable
+---
+
+## Overview
+
+[ASP.NET Core](https://learn.microsoft.com/aspnet/core/) is a production-ready framework for building web applications. This example integrates **Zitadel** with the built-in **OpenID Connect handler** using the **Authorization Code Flow + PKCE** to authenticate users securely and manage sessions.
+
+#### Auth library
+
+This example uses **[Microsoft.AspNetCore.Authentication.OpenIdConnect](https://learn.microsoft.com/aspnet/core/security/authentication/openid-connect)**. The middleware handles the PKCE dance, exchanges authorization codes for tokens, keeps tokens available on the request, and plugs into the standard ASP.NET Core authentication/authorization pipeline.
+
+---
+
+## What this example demonstrates
+
+- Public landing page with “Sign in with Zitadel”.
+- PKCE login handled by the ASP.NET Core OIDC middleware.
+- Route protection via the auth/authorization middleware; profile page renders OIDC claims.
+- Cookie-based session management with configurable idle timeout.
+- Federated logout that clears the local session and redirects through Zitadel’s RP-initiated logout.
+
+---
+
+## Getting started
+
+### Prerequisites
+
+- .NET SDK 8 or later
+
+### Account setup
+
+Create a Web application in Zitadel configured for Authorization Code + PKCE, then set:
+
+> **Redirect URIs:** `http://localhost:3000/auth/callback`
+> **Post Logout Redirect URIs:** `http://localhost:3000/auth/logout/callback`
+
+These values must match the sample configuration.
+
+### Run the example
+
+1. Clone the repository:
+ ```bash
+ git clone https://github.com/zitadel/example-auth-dotnet.git
+ cd example-auth-dotnet
+ ```
+2. Copy `.env.example` to `.env` and fill in your values:
+ ```dotenv
+ PORT=3000
+ SESSION_DURATION=3600
+ ZITADEL_DOMAIN="https://your-zitadel-domain"
+ ZITADEL_CLIENT_ID="your-zitadel-application-client-id"
+ ZITADEL_CLIENT_SECRET="your-randomly-generated-client-secret"
+ ZITADEL_POST_LOGOUT_URL="http://localhost:3000/auth/logout/callback"
+ ```
+3. Start the dev server (restores dependencies automatically):
+ ```bash
+ make start
+ ```
+
+The app will be available at `http://localhost:3000`.
+
+---
+
+## Learn more and resources
+
+* [PKCE concept](https://oauth.net/2/pkce/)
+* [ASP.NET Core OIDC handler](https://learn.microsoft.com/aspnet/core/security/authentication/openid-connect)
+* [Zitadel OIDC guide](https://zitadel.com/docs/guides/integrate/login/oidc/login-users)
+* [Federated logout](https://zitadel.com/docs/guides/integrate/login/oidc/logout)
+* [Example repository](https://github.com/zitadel/example-auth-dotnet)
diff --git a/apps/docs/frameworks.json b/apps/docs/frameworks.json
index 49ad2e1df..728350e0f 100644
--- a/apps/docs/frameworks.json
+++ b/apps/docs/frameworks.json
@@ -19,6 +19,12 @@
"imgSrcDark": "/docs/img/tech/django.svg",
"docsLink": "/docs/guides/start/quickstart?framework=django"
},
+ {
+ "id": "dotnet",
+ "title": ".NET",
+ "imgSrcDark": "/docs/img/tech/dotnet.svg",
+ "docsLink": "/docs/sdk-examples/dotnet"
+ },
{
"id": "expressjs",
"title": "Express.js",
diff --git a/apps/docs/lib/sidebar-data.ts b/apps/docs/lib/sidebar-data.ts
index 8d310a060..0d4f2cbde 100644
--- a/apps/docs/lib/sidebar-data.ts
+++ b/apps/docs/lib/sidebar-data.ts
@@ -384,6 +384,11 @@ export const guidesSidebar: readonly SidebarItem[] = [
"sdk-examples/client-libraries/php",
],
},
+ {
+ type: "category",
+ label: ".NET",
+ items: ["sdk-examples/dotnet"],
+ },
{
type: "category",
label: "Other Languages",
diff --git a/console/src/app/utils/framework.ts b/console/src/app/utils/framework.ts
index 638e24da4..25b61760b 100644
--- a/console/src/app/utils/framework.ts
+++ b/console/src/app/utils/framework.ts
@@ -106,6 +106,13 @@ export const OIDC_CONFIGURATIONS: OidcAppConfigurations = {
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
.setRedirectUrisList(['http://localhost:3000/auth/callback'])
.setPostLogoutRedirectUrisList(['http://localhost:3000/auth/logout/callback']),
+ ['dotnet']: new AddOIDCAppRequest()
+ .setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
+ .setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC)
+ .setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
+ .setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
+ .setRedirectUrisList(['http://localhost:3000/auth/callback'])
+ .setPostLogoutRedirectUrisList(['http://localhost:3000/auth/logout/callback']),
['astro']: new AddOIDCAppRequest()
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC)