Skip to content

Commit 671915b

Browse files
committed
ci: automatic deployment flow
1 parent cb8347b commit 671915b

8 files changed

Lines changed: 267 additions & 1267 deletions

File tree

packages/express/.changeset/README.md

Lines changed: 0 additions & 8 deletions
This file was deleted.

packages/express/.changeset/config.json

Lines changed: 0 additions & 11 deletions
This file was deleted.
File renamed without changes.
File renamed without changes.
File renamed without changes.

packages/express/README.md

Lines changed: 258 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,264 @@
11
# @seamless-auth/server-express
22

3-
Drop-in Express adapter for Seamless Auth “server mode” authentication.
3+
### Seamless Auth Express Adapter
44

5-
```js
5+
A secure, passwordless **server-side adapter** that connects your Express API to a private Seamless Auth Server.
6+
7+
It proxies all authentication flows, manages signed cookies, and gives you out-of-the-box middleware for verifying users and enforcing roles.
8+
9+
> **npm:** https://www.npmjs.com/package/@seamless-auth/express
10+
> **Docs:** https://docs.seamlessauth.com
11+
> **Repo:** https://github.com/fells-code/seamless-auth-server
12+
13+
14+
> Couple with https://github.com/fells-code/seamless-auth/react for an end to end seamless experience
15+
16+
> Or get a full starter application with https://github.com/fells-code/create-seamless
17+
18+
---
19+
20+
---
21+
22+
## Installation
23+
24+
```bash
25+
npm install @seamless-auth/server-express
26+
# or
27+
yarn add @seamless-auth/server-express
28+
```
29+
30+
31+
## Quick Example
32+
33+
```ts
634
import express from "express";
7-
import createSeamlessAuthServer from "@seamless-auth/server-express";
35+
import cookieParser from "cookie-parser";
36+
import createSeamlessAuthServer, { requireAuth, requireRole } from "@seamless-auth/server-express";
837

938
const app = express();
10-
app.use("/auth", createSeamlessAuthServer({
11-
authServerUrl: process.env.AUTH_SERVER_URL,
12-
cookieDomain: ".myapp.com"
13-
}));
39+
app.use(cookieParser());
40+
41+
// Public Seamless Auth endpoints
42+
app.use("/auth", createSeamlessAuthServer({ authServerUrl: process.env.AUTH_SERVER_URL! }));
43+
44+
// Everything after this line requires authentication
45+
app.use(requireAuth());
46+
47+
app.get("/api/me", (req, res) => res.json({ user: (req as any).user }));
48+
app.get("/admin", requireRole("admin"), (req, res) => res.json({ message: "Welcome admin!" }));
49+
50+
app.listen(5000, () => console.log("Portal API running on :5000"));
51+
```
52+
53+
---
54+
55+
# Full Documentation
56+
57+
## Overview
58+
59+
`@seamless-auth/express` lets your backend API act as an authentication and authorization server using Seamless Auth.
60+
61+
It transparently proxies and validates authentication flows so your frontend can use a single API endpoint for:
62+
63+
- Login / Registration / Logout
64+
- User introspection (`/auth/me`)
65+
- Session cookies (signed JWTs)
66+
- Role & permission guards
67+
- Internal Auth Server communication (JWKS + service tokens)
68+
69+
Everything happens securely between your API and a private Seamless Auth Server.
70+
71+
72+
73+
---
74+
75+
## Architecture
76+
77+
```
78+
[Frontend App]
79+
80+
81+
[Your Express API]
82+
├─ createSeamlessAuthServer() ← mounts /auth routes
83+
├─ requireAuth() ← verifies signed cookie JWT
84+
├─ requireRole('admin') ← role-based guard
85+
└─ getSeamlessUser() ← calls Auth Server
86+
87+
88+
[Private Seamless Auth Server]
89+
```
90+
91+
---
92+
93+
## Environment Variables
94+
95+
| Variable | Description | Example |
96+
|-----------|--------------|----------|
97+
| `AUTH_SERVER_URL` | Base URL of your Seamless Auth Server | `https://auth.client.com` |
98+
| `SEAMLESS_COOKIE_SIGNING_KEY` | Secret key for signing JWT cookies | `base64:...` |
99+
| `SERVICE_JWT_PRIVATE_KEY` | Private key for API → Auth Server JWTs | RSA PEM |
100+
| `SERVICE_JWT_KEYID` | Key ID for JWKS | `service-main` |
101+
| `COOKIE_DOMAIN` | Domain for cookies | `.client.com` |
102+
103+
---
104+
105+
## API Reference
106+
107+
### `createSeamlessAuthServer(options)`
108+
109+
Mounts an Express router exposing the full Seamless Auth flow:
110+
111+
- `/auth/login/start`
112+
- `/auth/login/finish`
113+
- `/auth/webauthn/...`
114+
- `/auth/registration/...`
115+
- `/auth/me`
116+
- `/auth/logout`
117+
118+
**Options**
119+
120+
```ts
121+
{
122+
authServerUrl: string; // required
123+
cookieDomain?: string;
124+
cookieNameOverrides?: {
125+
preauth?: string;
126+
registration?: string;
127+
access?: string;
128+
};
129+
}
130+
```
131+
132+
---
133+
134+
### `requireAuth(cookieName?: string)`
135+
136+
Middleware that validates the signed access cookie (`seamless_auth_access` by default)
137+
and attaches the decoded user payload to `req.user`.
138+
139+
```ts
140+
app.get("/api/profile", requireAuth(), (req, res) => {
141+
res.json({ user: req.user });
142+
});
143+
```
144+
145+
---
146+
147+
### `requireRole(role: string, cookieName?: string)`
148+
149+
Role-based authorization guard.
150+
Blocks non-matching roles with HTTP 403.
151+
152+
```ts
153+
app.get("/admin", requireRole("admin"), (req, res) => {
154+
res.json({ message: "Welcome admin!" });
155+
});
156+
```
157+
158+
---
159+
160+
### `getSeamlessUser(req, authServerUrl, cookieName?)`
161+
162+
Calls the Auth Server’s `/internal/session/introspect` endpoint using a signed service JWT
163+
and returns the Seamless user object.
164+
165+
```ts
166+
const user = await getSeamlessUser(req, process.env.AUTH_SERVER_URL!);
167+
```
168+
169+
User shape
170+
```ts
171+
{
172+
id: string;
173+
email: string;
174+
phone: string;
175+
roles: string[]
176+
}
177+
```
178+
179+
## End-to-End Flow
180+
181+
1. **Frontend**`/auth/login/start`
182+
→ API proxies to Seamless Auth Server
183+
→ sets short-lived pre-auth cookie.
184+
185+
2. **Frontend**`/auth/webauthn/finish`
186+
→ API proxies, validates, sets access cookie (`seamless_auth_access`).
187+
188+
3. **Subsequent API calls**`/api/...`
189+
`requireAuth()` verifies cookie and attaches user.
190+
→ Role routes use `requireRole()`.
191+
192+
---
193+
194+
## Local Development
195+
196+
In order to develop with your Seamless Auth server instance, you will need to have:
197+
198+
- Created an account @ https://dashboard.seamlessauth.com
199+
- Created a new Seamless Auth application
200+
201+
Example env:
202+
203+
```bash
204+
AUTH_SERVER_URL=http://https://<identifier>.seamlessauth.com # Found in the portal
205+
COOKIE_DOMAIN=localhost # Or frontend domain in prod
206+
SEAMLESS_COOKIE_SIGNING_KEY=local-secret-key # Found in the portal
207+
```
208+
209+
---
210+
211+
## Example Middleware Stack
212+
213+
```ts
214+
const AUTH_SERVER_URL = process.env.AUTH_SERVER_URL!;
215+
app.use(cors({ origin: "https://localhost:5001", credentials: true }));
216+
app.use(express.json());
217+
app.use(cookieParser());
218+
app.use("/auth", createSeamlessAuthServer({ authServerUrl: AUTH_SERVER_URL }));
219+
app.use(requireAuth());
220+
```
221+
222+
---
223+
224+
## Security Model
225+
226+
| Layer | Auth Mechanism | Signed By |
227+
|--------|----------------|------------|
228+
| **Frontend ↔ API** | Signed JWT in HttpOnly cookie (HS256) | Client API |
229+
| **API ↔ Auth Server** | Bearer Service JWT (RS256) | API’s private key |
230+
| **Auth Server** | Validates service tokens via JWKS | Seamless Auth JWKS |
231+
232+
All tokens and cookies are stateless and cryptographically verifiable.
233+
234+
---
235+
236+
## Testing
237+
238+
You can mock `requireAuth` and test Express routes via `supertest`.
239+
240+
Example:
241+
242+
```ts
243+
import { requireAuth } from "@seamless-auth/server-express";
244+
app.get("/api/test", requireAuth(), (req, res) => res.json({ ok: true }));
245+
```
246+
247+
---
248+
249+
## Roadmap
250+
251+
| Feature | Status |
252+
|----------|---------|
253+
| JWKS-verified response signing ||
254+
| OIDC discovery & SSO readiness | planned |
255+
| Federation (Google / Okta) | future |
256+
| Multi-framework adapters (Next.js / Fastify) | coming soon |
257+
258+
---
259+
260+
## License
261+
262+
MIT © 2025 Fells Code LLC
263+
Part of the **Seamless Auth** ecosystem.
264+

0 commit comments

Comments
 (0)