Skip to content

Commit 0366a80

Browse files
committed
initial commit
1 parent 4c18486 commit 0366a80

33 files changed

+1932
-2503
lines changed

README.md

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
# Express.js with ZITADEL
1+
# Express with ZITADEL
22

3-
[Express.js](https://expressjs.com/) is a popular and powerful framework for building the backend of web applications. In a traditional setup, often called a "Backend for Frontend" (BFF), your Express server manages both your application's logic and renders the web pages that users see.
3+
[Express](https://expressjs.com/) is a fast, unopinionated, minimalist web framework for Node.js. It provides a robust set of features for web and mobile applications, making it one of the most popular choices for building server-side applications. In a modern setup, your Express application manages both your application's frontend and backend logic through server-side routes and middleware.
44

5-
To secure such an application, you need a reliable way to handle user logins. For the Express ecosystem, [Passport.js](http://www.passportjs.org/) is the standard and recommended middleware for authentication. Think of it as a flexible security guard for your app. This guide demonstrates how to use Passport.js with an Express v5 application to implement a secure login with ZITADEL.
5+
To secure such an application, you need a reliable way to handle user logins. For the Express ecosystem, [Auth.js](https://authjs.dev/) (formerly NextAuth.js) is the standard and recommended library for authentication. Think of it as a flexible security guard for your app. This guide demonstrates how to use Auth.js with an Express application to implement a secure login with ZITADEL.
66

77
We'll be using the **OpenID Connect (OIDC)** protocol with the **Authorization Code Flow + PKCE**. This is the industry-best practice for security, ensuring that the login process is safe from start to finish. You can learn more in our [guide to OAuth 2.0 recommended flows](https://zitadel.com/docs/guides/integrate/login/oidc/oauth-recommended-flows).
88

9-
This example uses **Passport.js**, the standard for Express.js authentication. While ZITADEL doesn't offer a specific SDK, Passport.js is highly modular. It works with a "strategy" that handles the communication with ZITADEL. Under the hood, this example uses the powerful [`openid-client`](https://github.com/panva/node-openid-client) library to manage the secure OIDC PKCE flow.
9+
This example uses **Auth.js**, the standard for Express authentication. While ZITADEL doesn't offer a specific SDK, Auth.js is highly modular. It works with a "provider" that handles the communication with ZITADEL. Under the hood, this example uses the powerful OIDC standard to manage the secure PKCE flow.
1010

1111
Check out our Example Application to see it in action.
1212

1313
## Example Application
1414

15-
The example repository includes a complete Express.js application, ready to run, that demonstrates how to integrate ZITADEL for user authentication.
15+
The example repository includes a complete Express application, ready to run, that demonstrates how to integrate ZITADEL for user authentication.
1616

17-
This example application showcases a typical web app authentication pattern: users start on a public landing page, click a login button to authenticate with ZITADEL, and are then redirected to a protected profile page displaying their user information. The app also includes secure logout functionality that clears the session and redirects users back to ZITADEL's logout endpoint. All protected routes are automatically secured using Passport.js middleware, ensuring only authenticated users can access sensitive areas of your application.
17+
This example application showcases a typical web app authentication pattern: users start on a public landing page, click a login button to authenticate with ZITADEL, and are then redirected to a protected profile page displaying their user information. The app also includes secure logout functionality that clears the session and redirects users back to ZITADEL's logout endpoint. All protected routes are automatically secured using Auth.js middleware and session management, ensuring only authenticated users can access sensitive areas of your application.
1818

1919
### Prerequisites
2020

@@ -23,6 +23,7 @@ Before you begin, ensure you have the following:
2323
#### System Requirements
2424

2525
- Node.js (v20 or later is recommended)
26+
- npm, yarn, or pnpm package manager
2627

2728
#### Account Setup
2829

@@ -31,13 +32,13 @@ You'll need a ZITADEL account and application configured. Follow the [ZITADEL do
3132
> **Important:** Configure the following URLs in your ZITADEL application settings:
3233
>
3334
> - **Redirect URIs:** Add `http://localhost:3000/auth/callback` (for development)
34-
> - **Post Logout Redirect URIs:** Add `http://localhost:3000` (for development)
35+
> - **Post Logout Redirect URIs:** Add `http://localhost:3000/auth/logout/callback` (for development)
3536
>
3637
> These URLs must exactly match what your Express application uses. For production, add your production URLs.
3738
3839
### Configuration
3940

40-
To run the application, you first need to copy the `.env.example` file to a new file named `.env` and fill in your ZITADEL application credentials.
41+
To run the application, you first need to copy the `.env.example` file to a new file named `.env.local` and fill in your ZITADEL application credentials.
4142

4243
```dotenv
4344
# Port number where your Express server will listen for incoming HTTP requests.
@@ -63,21 +64,25 @@ ZITADEL_DOMAIN="https://your-zitadel-domain"
6364
# request.
6465
ZITADEL_CLIENT_ID="your-client-id"
6566
66-
# Client Secret for confidential applications. Leave empty for public clients.
67-
# Only required if you selected "Confidential" when creating your ZITADEL app.
68-
ZITADEL_CLIENT_SECRET=""
67+
# While the Authorization Code Flow with PKCE for public clients
68+
# does not strictly require a client secret for OIDC specification compliance,
69+
# AuthJS will still require a value for its internal configuration.
70+
# Therefore, please provide a randomly generated string here.
71+
# You can generate a secure key using:
72+
# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
73+
ZITADEL_CLIENT_SECRET="your-randomly-generated-client-secret"
6974
7075
# OAuth callback URL where ZITADEL redirects after user authentication. This
7176
# MUST exactly match a Redirect URI configured in your ZITADEL application.
7277
ZITADEL_CALLBACK_URL="http://localhost:3000/auth/callback"
7378
7479
# URL where users are redirected after logout. This should match a Post Logout
7580
# Redirect URI configured in your ZITADEL application settings.
76-
ZITADEL_POST_LOGOUT_URL="http://localhost:3000"
81+
ZITADEL_POST_LOGOUT_URL="http://localhost:3000/auth/logout/callback"
7782
78-
# Internal redirect destination after successful login. This is where your app
79-
# sends users after ZITADEL confirms authentication. Defaults to "/profile".
80-
ZITADEL_POST_LOGIN_URL="/profile"
83+
# Auth.js base URL for your application. In development, this is typically
84+
# http://localhost:3000. In production, use your actual domain.
85+
NEXTAUTH_URL="http://localhost:3000"
8186
```
8287

8388
### Installation and Running
@@ -86,9 +91,9 @@ Follow these steps to get the application running:
8691

8792
```bash
8893
# 1. Clone the repository
89-
git clone [email protected]:zitadel/example-auth-expressjs.git
94+
git clone [email protected]:zitadel/example-auth-express.git
9095

91-
cd example-auth-expressjs
96+
cd example-auth-express
9297

9398
# 2. Install the project dependencies
9499
npm install
@@ -99,11 +104,42 @@ npm run dev
99104

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

107+
## Key Features
108+
109+
### PKCE Authentication Flow
110+
111+
The application implements the secure Authorization Code Flow with PKCE (Proof Key for Code Exchange), which is the recommended approach for modern web applications.
112+
113+
### Session Management
114+
115+
Built-in session management with Auth.js handles user authentication state across your application, with automatic token refresh and secure session storage.
116+
117+
### Route Protection
118+
119+
Protected routes automatically redirect unauthenticated users to the login flow, ensuring sensitive areas of your application remain secure.
120+
121+
### Logout Flow
122+
123+
Complete logout implementation that properly terminates both the local session and the ZITADEL session, with proper redirect handling.
124+
102125
## TODOs
103126

104-
### 1. Security headers (Helmet)
127+
### 1. Security headers (Express middleware)
128+
129+
**Not enabled.** Consider adding security headers middleware in your Express application:
105130

106-
**Not enabled yet.** Add [`helmet`](https://www.npmjs.com/package/helmet) before production:
131+
```javascript
132+
import helmet from 'helmet';
133+
134+
app.use(helmet({
135+
contentSecurityPolicy: {
136+
directives: {
137+
defaultSrc: ["'self'"],
138+
scriptSrc: ["'self'", "'unsafe-eval'", "'unsafe-inline'"],
139+
},
140+
},
141+
}));
142+
```
107143

108144
At minimum, configure:
109145

@@ -112,21 +148,8 @@ At minimum, configure:
112148
- `Referrer-Policy`
113149
- `Permissions-Policy`
114150

115-
### 2. No CSRF protection yet
116-
117-
State‑changing routes (logout, future POST/PUT/DELETE) are currently vulnerable.
118-
Add CSRF protection using [`csrf-csrf`](https://www.npmjs.com/package/csrf-csrf)
119-
120-
Remember to:
121-
122-
- Make logout a **POST**.
123-
- Embed the CSRF token in a hidden form field or send it via `X-CSRF-Token` header.
124-
- Set cookies with `SameSite=Lax` or stricter.
125-
126-
> OWASP reference: <https://owasp.org/www-community/attacks/csrf>
127-
128151
## Resources
129152

130-
- **Express.js Documentation:** <https://expressjs.com/>
131-
- **Passport.js Documentation:** <http://www.passportjs.org/>
132-
- **Express Session Middleware:** <https://expressjs.com/en/resources/middleware/session.html>
153+
- **Express Documentation:** <https://expressjs.com/>
154+
- **Auth.js Documentation:** <https://authjs.dev/>
155+
- **ZITADEL Documentation:** <https://zitadel.com/docs>

knip.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
ignoreDependencies: ['handlebars'],
3+
};

0 commit comments

Comments
 (0)