Skip to content

Commit 2645f3c

Browse files
committed
refactor: drop toolkit framing, be honest about architecture
- Remove 'toolkit' language from all documentation - Frame AuthService as public API, not 'one option' - Label Core + Operations as 'internal layers' (advanced use only) - Update package.json description to be accurate - Reorder exports: AuthService first, internals last - Acknowledge what this is: framework-agnostic library with adapter pattern - Stop pretending Core + Operations are composable primitives
1 parent 19497e2 commit 2645f3c

File tree

5 files changed

+457
-118
lines changed

5 files changed

+457
-118
lines changed

README.md

Lines changed: 64 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3,108 +3,89 @@
33
> [!WARNING]
44
> This is prerelease software. APIs may change without notice.
55
6-
**A toolkit library for building WorkOS AuthKit integrations.**
6+
**Framework-agnostic authentication library for WorkOS.**
77

8-
This library extracts the complex business logic (JWT verification, session encryption, token refresh orchestration) that WorkOS SDK authors need when building framework-specific authentication packages like `@workos-inc/authkit-nextjs`, `@workos-inc/authkit-tanstack-start`, and `@workos-inc/authkit-sveltekit`.
8+
Provides the business logic for WorkOS authentication (JWT verification, session encryption, token refresh orchestration) with a pluggable storage adapter pattern. Build framework-specific packages like `@workos-inc/authkit-nextjs` or `@workos-inc/authkit-tanstack-start` by implementing the storage interface.
99

10-
## Philosophy
10+
## What This Library Provides
1111

12-
**We provide the hard stuff:**
12+
**Authentication business logic:**
13+
- JWT verification against JWKS (with caching)
14+
- Session encryption/decryption (iron-webcrypto, AES-256-CBC)
15+
- Token refresh orchestration (automatic expiry detection, org context preservation)
16+
- WorkOS API operations (signOut, refreshSession, authorization URLs)
1317

14-
- Token verification with JWKS and caching
15-
- Session encryption/decryption (iron-webcrypto)
16-
- Token refresh orchestration (when to refresh, how to preserve org context)
17-
- WorkOS API integration helpers (signOut, refreshSession, authorization URLs)
18-
- Cookie building with secure defaults
18+
**Framework integration helpers:**
19+
- `CookieSessionStorage` base class with secure defaults
20+
- Storage adapter pattern via `SessionStorage<TRequest, TResponse>` interface
1921
- Configuration management (environment variables, validation)
2022

21-
**You own the integration:**
22-
23-
- Implement `updateSession/withAuth` patterns that fit your framework
24-
- Handle request context (headers, locals, WeakMap) your way
25-
- Add framework-specific features (callbacks, debug logging, eager auth)
26-
- Control middleware and route handler patterns
27-
28-
**Result:** Share 80% of the complexity, keep 100% control over framework integration.
23+
**What frameworks implement:**
24+
- Storage adapter for their request/response objects
25+
- Middleware pattern for auth validation and token refresh
26+
- Request context handling (headers, locals, WeakMap - whatever fits)
27+
- Framework-specific features (callbacks, debug logging, route helpers)
2928

3029
## Features
3130

32-
- **Business Logic Extraction**: JWT, crypto, and refresh logic in one place
33-
- **Framework-Agnostic Primitives**: Works in any JavaScript environment (Node.js, edge, Deno)
34-
- **Toolkit, Not Framework**: Use what you need, implement patterns your way
35-
- **Type-Safe**: Full TypeScript support with custom claims and generics
31+
- **Framework-Agnostic**: Works with any server-side JavaScript framework
32+
- **Pluggable Storage**: Implement storage adapter for your framework's request/response objects
33+
- **Type-Safe**: Full TypeScript support with discriminated unions and custom claims
3634
- **Production-Ready**: 80%+ test coverage, comprehensive error handling
37-
- **Zero Framework Opinions**: No prescribed middleware/route patterns
35+
- **Secure by Default**: AES-256-CBC encryption, HttpOnly cookies, JWKS verification
3836

3937
## Architecture
4038

41-
This library provides a **three-layer toolkit** for building authentication:
42-
43-
### Layer 1: Core Business Logic (`AuthKitCore`)
44-
45-
Pure functions for the hard stuff - no framework dependencies:
39+
The library uses a clean internal architecture with three layers:
4640

47-
- **Token Operations**
48-
- `verifyToken()` - JWT verification against JWKS (with caching)
49-
- `isTokenExpiring()` - Check if token needs refresh soon
50-
- `parseTokenClaims()` - Extract and decode JWT claims
41+
### AuthService (Public API)
5142

52-
- **Session Encryption**
53-
- `encryptSession()` - AES-256-CBC encryption for cookies
54-
- `decryptSession()` - Decrypt and validate session data
43+
The main interface frameworks interact with. Provides methods for:
5544

56-
- **Refresh Orchestration**
57-
- `refreshTokens()` - Call WorkOS API to refresh tokens
58-
- `validateAndRefresh()` - **Core orchestration**: validate token → refresh if expiring
45+
- **Session Management**: `withAuth()` - Validate and auto-refresh sessions
46+
- **OAuth Flow**: `handleCallback()` - Process authentication callbacks
47+
- **User Actions**: `signOut()`, `switchOrganization()`, `refreshSession()`
48+
- **URL Generation**: `getSignInUrl()`, `getSignUpUrl()`, `getAuthorizationUrl()`
5949

6050
```typescript
61-
import { AuthKitCore } from '@workos/authkit-session';
51+
import { createAuthService } from '@workos/authkit-session';
6252

63-
const core = new AuthKitCore(config, client, encryption);
53+
const authService = createAuthService({
54+
sessionStorageFactory: (config) => new MyFrameworkStorage(config),
55+
});
6456

65-
// Validate and potentially refresh in one call
66-
const { valid, refreshed, session, claims } =
67-
await core.validateAndRefresh(session);
57+
const { auth, refreshedSessionData } = await authService.withAuth(request);
6858
```
6959

70-
### Layer 2: WorkOS Operations (`AuthOperations`)
71-
72-
High-level operations combining core logic with WorkOS API calls:
73-
74-
- **Sign Out**: `signOut()` - Generate logout URL + cookie clear header
75-
- **Refresh Session**: `refreshSession()` - Refresh tokens with org context preservation
76-
- **Switch Organization**: `switchOrganization()` - Refresh with new org ID
77-
- **URL Generation**: `getAuthorizationUrl()`, `getSignInUrl()`, `getSignUpUrl()`
78-
79-
```typescript
80-
import { AuthOperations } from '@workos/authkit-session';
81-
82-
const operations = new AuthOperations(core, client, config);
60+
### Internal Implementation
8361

84-
// Sign out returns everything you need
85-
const { logoutUrl, clearCookieHeader } = await operations.signOut(sessionId, {
86-
returnTo: '/',
87-
});
88-
```
62+
AuthService delegates to internal layers (you don't need to interact with these directly):
8963

90-
### Layer 3: Helpers
64+
- **`AuthKitCore`** - JWT verification, session encryption, token refresh logic
65+
- **`AuthOperations`** - WorkOS API calls with proper error handling
9166

92-
- **`CookieSessionStorage`** - Base class with secure cookie defaults
93-
- **`ConfigurationProvider`** - Environment variable mapping and validation
67+
These are exported for advanced use cases, but most frameworks only need AuthService.
9468

95-
### Orchestration (Your Choice)
69+
### Storage Adapter Pattern
9670

97-
- **`AuthService`** - One orchestration pattern (used by `@workos/authkit-tanstack-start`)
98-
- **Build your own** - Use Core + Operations directly with custom orchestration
71+
Frameworks implement the `SessionStorage<TRequest, TResponse>` interface:
9972

100-
**Key Design Decision:** We don't force context methods (`getSessionFromContext`) into interfaces. Each framework handles request context differently:
73+
```typescript
74+
class MyFrameworkStorage extends CookieSessionStorage<Request, Response> {
75+
async getSession(request: Request): Promise<string | null> {
76+
// Extract encrypted session from cookies
77+
}
10178

102-
- Next.js: Mutable headers (`request.headers.set()`)
103-
- TanStack Start: WeakMap (immutable requests)
104-
- SvelteKit: `event.locals`
105-
- Remix: Context objects
79+
protected async applyHeaders(
80+
response: Response | undefined,
81+
headers: Record<string, string>,
82+
): Promise<{ response: Response }> {
83+
// Apply Set-Cookie headers to response
84+
}
85+
}
86+
```
10687

107-
Let frameworks implement context passing idiomatically.
88+
The library handles everything else: encryption, JWT validation, refresh logic, WorkOS API calls.
10889

10990
## Installation
11091

@@ -315,9 +296,9 @@ const result = await authService.switchOrganization(session, 'org_123');
315296

316297
If you're building a framework-specific package (like `@workos/authkit-tanstack-start`), this library provides all the business logic you need. You just add framework-specific glue.
317298

318-
### Option 1: Use AuthService
299+
### Standard Approach: Use AuthService
319300

320-
One orchestration approach is `createAuthService()` with a storage adapter (used by `@workos/authkit-tanstack-start`):
301+
Create an AuthService instance with your storage adapter:
321302

322303
```typescript
323304
// src/storage.ts - Your framework's storage adapter
@@ -443,9 +424,9 @@ export const authMiddleware = () => {
443424

444425
**Why this matters:** If you don't apply the `Set-Cookie` header, refreshed tokens stay in memory but never persist to the cookie. This causes infinite refresh loops because the next request has the old (expired) token.
445426

446-
### Option 2: Use Core + Operations Directly
427+
### Advanced: Use Core + Operations Directly
447428

448-
Build your own orchestration using the toolkit primitives:
429+
For specialized use cases, you can use the internal layers directly:
449430

450431
```typescript
451432
import {
@@ -727,18 +708,15 @@ configure({
727708
- `getConfig(key)`: Get a specific configuration value
728709
- `getConfigurationProvider()`: Get the ConfigurationProvider instance
729710

730-
#### Toolkit Classes
731-
732-
**Core primitives:**
733-
734-
- **`AuthKitCore`** - Pure business logic (JWT, crypto, refresh orchestration)
735-
- **`AuthOperations`** - WorkOS API operations (signOut, refreshSession, authorization URLs)
736-
- **`CookieSessionStorage`** - Base class for cookie-based session storage
711+
#### Main API
737712

738-
**Orchestration (optional):**
713+
- **`createAuthService(options)`** - Create an AuthService instance with your storage adapter
714+
- **`AuthService`** - Main authentication interface (session validation, OAuth, sign out, URLs)
715+
- **`CookieSessionStorage`** - Base class for implementing storage adapters
739716

740-
- **`AuthService`** - One orchestration pattern (used by `@workos/authkit-tanstack-start`)
741-
- **`createAuthService(options)`** - Factory for creating AuthService instances
717+
**Advanced (internal layers):**
718+
- **`AuthKitCore`** - Internal: JWT verification, session encryption, refresh logic
719+
- **`AuthOperations`** - Internal: WorkOS API operations
742720

743721
See the [Architecture](#architecture) section for detailed usage.
744722

0 commit comments

Comments
 (0)