# Express.js

## [Overview](/content/docs/sdk-examples/expressjs#overview/index.html)

[Express.js](https://expressjs.com/) is a fast, unopinionated, minimalist web framework for [Node.js](https://nodejs.org/) that provides a robust set of features for building web and mobile applications. This example demonstrates how to integrate **Zitadel** using the **[OAuth 2.0 PKCE flow](https://oauth.net/2/pkce/)** to authenticate users securely and maintain sessions across your Express application.

#### [Auth library](/content/docs/sdk-examples/expressjs#auth-library/index.html)

This example uses **[@auth/express](https://www.npmjs.com/package/@auth/express)** ( [GitHub](https://github.com/nextauthjs/next-auth)), the Express.js adapter for [Auth.js](https://authjs.dev/). This library implements the [OpenID Connect (OIDC)](/content/docs/apis/openidoauth/endpoints/index.html) protocol with [PKCE](https://oauth.net/2/pkce/) support, manages [token exchange](/content/docs/apis/openidoauth/grant-types/index.html), performs automatic [token refresh](/content/docs/apis/openidoauth/grant-types#refresh-token/index.html), and provides session management with secure cookie-based storage.

* * *

## [What this example demonstrates](/content/docs/sdk-examples/expressjs#what-this-example-demonstrates/index.html)

This Express.js example provides a complete authentication implementation using [Zitadel](/content/docs/index.html) as the identity provider. The application starts with a public landing page featuring a login button that initiates the [PKCE authentication flow](https://oauth.net/2/pkce/). When users click login, [@auth/express](https://www.npmjs.com/package/@auth/express) generates a cryptographic code verifier and challenge, then redirects to Zitadel's authorization endpoint. After successful authentication at Zitadel, users return to the application's [callback URL](/content/docs/guides/integrate/login/oidc/login-users/index.html) where the authorization code is exchanged for [access tokens](/content/docs/apis/openidoauth/endpoints/index.html) and an [ID token](/content/docs/apis/openidoauth/claims/index.html).

The example includes protected routes using [Express middleware](https://expressjs.com/en/guide/using-middleware.html) that automatically verify session state and redirect unauthenticated users to the sign-in page. Authenticated users can access their profile page displaying user information including email, name, and custom [metadata claims](/content/docs/apis/openidoauth/claims/index.html) from Zitadel. The application maintains long-lived sessions through automatic [token refresh](/content/docs/apis/openidoauth/grant-types#refresh-token/index.html) using [refresh tokens](/content/docs/apis/openidoauth/endpoints#token_endpoint/index.html), ensuring users remain authenticated without repeated logins.

Sign-out functionality implements **[federated logout](/content/docs/guides/integrate/login/oidc/logout/index.html)** by redirecting to Zitadel's end-session endpoint with the ID token hint, terminating both the local session and the Zitadel session. The logout flow includes [CSRF protection](https://authjs.dev/guides/basics/securing-pages-and-api-routes) through state parameter validation, and users are redirected to a success page after logout completion. All authentication flows use secure HTTP-only cookies for [session storage](https://authjs.dev/concepts/session-strategies) and implement proper security headers.

* * *

## [Getting started](/content/docs/sdk-examples/expressjs#getting-started/index.html)

### [Prerequisites](/content/docs/sdk-examples/expressjs#prerequisites/index.html)

Before running this example, you need to create and configure a PKCE application in the [ZITADEL Management Console](/content/docs/guides/manage/console/console-overview/index.html). Follow the PKCE application setup guide to:

1. Create a new Web application in your [Zitadel project](/content/docs/guides/manage/console/projects-overview/index.html)
2. Configure it to use the PKCE authentication method
3. Set up your redirect URIs (e.g., `http://localhost:3000/auth/callback/zitadel` for development)
4. Configure post-logout redirect URIs (e.g., `http://localhost:3000/auth/logout/callback`)
5. Copy your **Client ID** for use in the next steps

> **Note:** Make sure to enable **Dev Mode** in the [ZITADEL Management Console](/content/docs/guides/manage/console/console-overview/index.html) if you're using HTTP URLs during local development. For production, always use HTTPS URLs and disable Dev Mode.

### [Run the example](/content/docs/sdk-examples/expressjs#run-the-example/index.html)

Once you have your [Zitadel application configured](/content/docs/guides/integrate/login/oidc/login-users/index.html):

1. Clone the [repository](https://github.com/zitadel/example-auth-expressjs).
2. Create a `.env.local` file and configure it with the values from your [Zitadel application](/content/docs/guides/manage/console/applications-overview/index.html). Use the exact environment variable names from the repository:

```
NODE_ENV=development
PORT=3000
SESSION_SECRET=your-very-secret-and-strong-session-key
SESSION_DURATION=3600
ZITADEL_DOMAIN=https://your-instance.zitadel.cloud
ZITADEL_CLIENT_ID=your_client_id_from_console
ZITADEL_CLIENT_SECRET=your-randomly-generated-client-secret
ZITADEL_CALLBACK_URL=http://localhost:3000/auth/callback/zitadel
ZITADEL_POST_LOGIN_URL=/profile
ZITADEL_POST_LOGOUT_URL=http://localhost:3000/auth/logout/callback
```

Replace these values with:
   - Your actual Zitadel instance URL (the **Issuer** from the PKCE setup guide)
   - The **Client ID** you copied when creating the application
   - A randomly generated client secret (generate using: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`)
   - The **redirect URI** you configured in the PKCE setup (must match exactly)
   - A strong session secret (generate using: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`)
3. Install dependencies using [npm](https://www.npmjs.com/) and start the development server:

```
npm install
npm run dev
```

The application will be running at `http://localhost:3000`.

* * *

## [Learn more and resources](/content/docs/sdk-examples/expressjs#learn-more-and-resources/index.html)

- [PKCE concept](https://oauth.net/2/pkce/)
- [Federated logout](/content/docs/guides/integrate/login/oidc/logout/index.html)
- [OIDC integration guide](/content/docs/guides/integrate/login/oidc/login-users/index.html)
- [Framework docs](https://expressjs.com/)
- [Auth library](https://www.npmjs.com/package/@auth/express)
- [Auth.js documentation](https://authjs.dev/)
- [Example repository](https://github.com/zitadel/example-auth-expressjs)
