@owox/idp-protocol 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +298 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +1 -0
- package/dist/middleware/protocol-middleware.d.ts +99 -0
- package/dist/middleware/protocol-middleware.d.ts.map +1 -0
- package/dist/middleware/protocol-middleware.js +131 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +1 -0
- package/dist/providers/null-provider.d.ts +24 -0
- package/dist/providers/null-provider.d.ts.map +1 -0
- package/dist/providers/null-provider.js +58 -0
- package/dist/types/cli.d.ts +27 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +1 -0
- package/dist/types/config.d.ts +14 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +1 -0
- package/dist/types/errors.d.ts +33 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +45 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +13 -0
- package/dist/types/models.d.ts +24 -0
- package/dist/types/models.d.ts.map +1 -0
- package/dist/types/models.js +1 -0
- package/dist/types/provider.d.ts +63 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/provider.js +1 -0
- package/package.json +52 -0
- package/src/index.ts +8 -0
- package/src/middleware/index.ts +1 -0
- package/src/middleware/protocol-middleware.ts +178 -0
- package/src/providers/index.ts +1 -0
- package/src/providers/null-provider.ts +71 -0
- package/src/types/cli.ts +30 -0
- package/src/types/config.ts +14 -0
- package/src/types/errors.ts +49 -0
- package/src/types/index.ts +18 -0
- package/src/types/models.ts +28 -0
- package/src/types/provider.ts +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# @owox/idp-protocol
|
|
2
|
+
|
|
3
|
+
Identity Provider protocol package for OWOX Data Marts. Provides core types, middleware, and provider implementations for authentication and authorization.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔧 Core IDP interfaces and types
|
|
8
|
+
- 🔀 Express middleware for authentication routes
|
|
9
|
+
- 🚫 NULL IDP provider for single-user deployments
|
|
10
|
+
- 🛡️ Built-in error handling
|
|
11
|
+
- ⚙️ Configurable routing
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @owox/idp-protocol
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
@owox/idp-protocol
|
|
23
|
+
├── types/ # Core interfaces and models
|
|
24
|
+
│ ├── provider.ts # IdpProvider interface
|
|
25
|
+
│ ├── models.ts # Payload, AuthResult, Role types
|
|
26
|
+
│ ├── config.ts # Configuration types
|
|
27
|
+
│ ├── errors.ts # Error classes
|
|
28
|
+
│ └── cli.ts # CLI command interfaces
|
|
29
|
+
├── providers/ # Provider implementations
|
|
30
|
+
│ └── null-provider.ts # NULL provider for development
|
|
31
|
+
└── middleware/ # Express middleware
|
|
32
|
+
└── protocol-middleware.ts # Route handling middleware
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Core Types
|
|
36
|
+
|
|
37
|
+
### IdpProvider Interface
|
|
38
|
+
|
|
39
|
+
The main provider interface that all IDP implementations must follow:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { IdpProvider } from '@owox/idp-protocol';
|
|
43
|
+
|
|
44
|
+
interface IdpProvider {
|
|
45
|
+
// Middleware handlers
|
|
46
|
+
signInMiddleware(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
|
|
47
|
+
signOutMiddleware(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
|
|
48
|
+
accessTokenMiddleware(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
|
|
49
|
+
|
|
50
|
+
// Token management
|
|
51
|
+
introspectToken(token: string): Promise<Payload | null>;
|
|
52
|
+
refreshToken(refreshToken: string): Promise<AuthResult>;
|
|
53
|
+
revokeToken(token: string): Promise<void>;
|
|
54
|
+
|
|
55
|
+
// Lifecycle
|
|
56
|
+
initialize(): Promise<void>;
|
|
57
|
+
shutdown(): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Domain Models
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { Payload, AuthResult, Role } from '@owox/idp-protocol';
|
|
65
|
+
|
|
66
|
+
type Role = 'admin' | 'editor' | 'viewer';
|
|
67
|
+
|
|
68
|
+
interface Payload {
|
|
69
|
+
userId: string;
|
|
70
|
+
projectId: string;
|
|
71
|
+
email?: string;
|
|
72
|
+
fullName?: string;
|
|
73
|
+
roles?: Role[];
|
|
74
|
+
projectTitle?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface AuthResult {
|
|
78
|
+
accessToken: string;
|
|
79
|
+
refreshToken?: string;
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Error Classes
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import {
|
|
87
|
+
IdpError,
|
|
88
|
+
AuthenticationError,
|
|
89
|
+
AuthorizationError,
|
|
90
|
+
TokenExpiredError,
|
|
91
|
+
InvalidTokenError,
|
|
92
|
+
} from '@owox/idp-protocol';
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Middleware
|
|
96
|
+
|
|
97
|
+
The protocol middleware handles authentication routes automatically:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import express from 'express';
|
|
101
|
+
import { IdpProtocolMiddleware, NullIdpProvider } from '@owox/idp-protocol';
|
|
102
|
+
|
|
103
|
+
const app = express();
|
|
104
|
+
const provider = new NullIdpProvider();
|
|
105
|
+
|
|
106
|
+
// Basic usage with default routes (/auth/sign-in, /auth/sign-out, /auth/access-token)
|
|
107
|
+
const middleware = new IdpProtocolMiddleware(provider);
|
|
108
|
+
middleware.register(app);
|
|
109
|
+
|
|
110
|
+
// Custom configuration
|
|
111
|
+
const middleware = new IdpProtocolMiddleware(provider, {
|
|
112
|
+
basePath: '/api/v1/auth',
|
|
113
|
+
routes: {
|
|
114
|
+
signIn: '/login',
|
|
115
|
+
signOut: '/logout',
|
|
116
|
+
accessToken: '/token',
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
middleware.register(app);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Middleware Features
|
|
123
|
+
|
|
124
|
+
- ✅ Configurable base path and route names
|
|
125
|
+
- ✅ Automatic error handling with try-catch
|
|
126
|
+
- ✅ Support for all HTTP methods (GET, POST, etc.)
|
|
127
|
+
- ✅ Route collision detection
|
|
128
|
+
- ✅ Path validation
|
|
129
|
+
- ✅ TypeScript support
|
|
130
|
+
|
|
131
|
+
## NULL Provider
|
|
132
|
+
|
|
133
|
+
The included NULL provider is perfect for development and single-user deployments:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { NullIdpProvider } from '@owox/idp-protocol';
|
|
137
|
+
|
|
138
|
+
const provider = new NullIdpProvider();
|
|
139
|
+
|
|
140
|
+
// Default user payload
|
|
141
|
+
const defaultPayload = {
|
|
142
|
+
userId: '0',
|
|
143
|
+
email: 'admin@localhost',
|
|
144
|
+
roles: ['admin'],
|
|
145
|
+
fullName: 'Admin',
|
|
146
|
+
projectId: '0',
|
|
147
|
+
};
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### NULL Provider Features
|
|
151
|
+
|
|
152
|
+
- ✅ Implements all IdpProvider methods
|
|
153
|
+
- 🔄 Returns consistent default user payload
|
|
154
|
+
- 🚫 No actual authentication (always succeeds)
|
|
155
|
+
- ⚡ Zero configuration required
|
|
156
|
+
- 🛠️ Perfect for testing and development
|
|
157
|
+
|
|
158
|
+
## Usage Examples
|
|
159
|
+
|
|
160
|
+
### Basic Setup
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import express from 'express';
|
|
164
|
+
import { IdpProtocolMiddleware, NullIdpProvider } from '@owox/idp-protocol';
|
|
165
|
+
|
|
166
|
+
const app = express();
|
|
167
|
+
const provider = new NullIdpProvider();
|
|
168
|
+
|
|
169
|
+
// Initialize provider
|
|
170
|
+
await provider.initialize();
|
|
171
|
+
|
|
172
|
+
// Setup middleware
|
|
173
|
+
const middleware = new IdpProtocolMiddleware(provider);
|
|
174
|
+
middleware.register(app);
|
|
175
|
+
|
|
176
|
+
// Server will handle:
|
|
177
|
+
// POST /auth/sign-in
|
|
178
|
+
// POST /auth/sign-out
|
|
179
|
+
// POST /auth/access-token
|
|
180
|
+
|
|
181
|
+
app.listen(3000);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Custom Provider Implementation
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import { IdpProvider, Payload, AuthResult } from '@owox/idp-protocol';
|
|
188
|
+
import { Request, Response, NextFunction } from 'express';
|
|
189
|
+
|
|
190
|
+
class CustomIdpProvider implements IdpProvider {
|
|
191
|
+
async signInMiddleware(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
|
192
|
+
// Handle OAuth redirect, validate credentials, etc.
|
|
193
|
+
return res.json({ success: true, redirectUrl: '/dashboard' });
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async signOutMiddleware(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
|
197
|
+
// Clear session, revoke tokens
|
|
198
|
+
return res.json({ success: true });
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async accessTokenMiddleware(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
|
202
|
+
// Return user info or token
|
|
203
|
+
const payload = await this.introspectToken(req.headers.authorization);
|
|
204
|
+
return res.json(payload);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async introspectToken(token: string): Promise<Payload | null> {
|
|
208
|
+
// Validate JWT or call external IDP
|
|
209
|
+
return {
|
|
210
|
+
userId: 'user123',
|
|
211
|
+
projectId: 'proj456',
|
|
212
|
+
email: 'user@company.com',
|
|
213
|
+
roles: ['editor'],
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async refreshToken(refreshToken: string): Promise<AuthResult> {
|
|
218
|
+
// Exchange refresh token for new access token
|
|
219
|
+
return { accessToken: 'new-jwt-token' };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async revokeToken(token: string): Promise<void> {
|
|
223
|
+
// Invalidate token
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async initialize(): Promise<void> {
|
|
227
|
+
// Setup external connections, validate config
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async shutdown(): Promise<void> {
|
|
231
|
+
// Cleanup resources
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Advanced Middleware Configuration
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { IdpProtocolMiddleware, ProtocolRoute } from '@owox/idp-protocol';
|
|
240
|
+
|
|
241
|
+
const middleware = new IdpProtocolMiddleware(provider, {
|
|
242
|
+
basePath: '/api/v1/auth',
|
|
243
|
+
routes: {
|
|
244
|
+
signIn: ProtocolRoute.SIGN_IN, // '/sign-in'
|
|
245
|
+
signOut: ProtocolRoute.SIGN_OUT, // '/sign-out'
|
|
246
|
+
accessToken: '/me', // Custom route
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Results in:
|
|
251
|
+
// ALL /api/v1/auth/sign-in
|
|
252
|
+
// ALL /api/v1/auth/sign-out
|
|
253
|
+
// ALL /api/v1/auth/me
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Error Handling
|
|
257
|
+
|
|
258
|
+
Use provided error classes for consistent error handling:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { AuthenticationError, InvalidTokenError } from '@owox/idp-protocol';
|
|
262
|
+
|
|
263
|
+
class MyProvider implements IdpProvider {
|
|
264
|
+
async introspectToken(token: string): Promise<Payload | null> {
|
|
265
|
+
if (!token) {
|
|
266
|
+
throw new InvalidTokenError('Token is required');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
// Validate token
|
|
271
|
+
return payload;
|
|
272
|
+
} catch (error) {
|
|
273
|
+
throw new AuthenticationError('Token validation failed');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Development
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# Install dependencies
|
|
283
|
+
npm install
|
|
284
|
+
|
|
285
|
+
# Build
|
|
286
|
+
npm run build
|
|
287
|
+
|
|
288
|
+
# Type checking
|
|
289
|
+
npm run typecheck
|
|
290
|
+
|
|
291
|
+
# Linting
|
|
292
|
+
npm run lint
|
|
293
|
+
npm run lint:fix
|
|
294
|
+
|
|
295
|
+
# Formatting
|
|
296
|
+
npm run format
|
|
297
|
+
npm run format:check
|
|
298
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AAGjC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,uBAAuB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './protocol-middleware.js';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { IdpProvider } from '../types/provider.js';
|
|
2
|
+
import { Express } from 'express';
|
|
3
|
+
/**
|
|
4
|
+
* The routes that are supported by the protocol middleware.
|
|
5
|
+
*/
|
|
6
|
+
export declare enum ProtocolRoute {
|
|
7
|
+
SIGN_IN = "/sign-in",
|
|
8
|
+
SIGN_OUT = "/sign-out",
|
|
9
|
+
ACCESS_TOKEN = "/access-token",
|
|
10
|
+
USER = "/api/user"
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The options for the protocol middleware.
|
|
14
|
+
* @property basePath - The base path for the protoc ol middleware.
|
|
15
|
+
* @property routes - The routes that are supported by the protocol middleware.
|
|
16
|
+
* @example
|
|
17
|
+
* {
|
|
18
|
+
* basePath: '/',
|
|
19
|
+
* routes: {
|
|
20
|
+
* signIn: '/signin', // override the default sign in route
|
|
21
|
+
* signOut: '/signout', // override the default sign out route
|
|
22
|
+
* accessToken: '/accesstoken', // override the default access token route
|
|
23
|
+
* user: '/api/userinfo', // override the default user route
|
|
24
|
+
* },
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
export interface IdpProtocolMiddlewareOptions {
|
|
28
|
+
basePath?: string;
|
|
29
|
+
routes?: {
|
|
30
|
+
signIn?: string;
|
|
31
|
+
signOut?: string;
|
|
32
|
+
accessToken?: string;
|
|
33
|
+
user?: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The protocol middleware for the IDP.
|
|
38
|
+
* @param provider - The provider to use for the middleware.
|
|
39
|
+
* @param options - The options for the middleware.
|
|
40
|
+
* @example // Register the middleware with the default routes
|
|
41
|
+
* const idpProtocolMiddleware = new IdpProtocolMiddleware(provider);
|
|
42
|
+
* idpProtocolMiddleware.register(app);
|
|
43
|
+
*
|
|
44
|
+
* @example // Override the default routes
|
|
45
|
+
* const app = express();
|
|
46
|
+
* const middlewareOptions: IdpProtocolMiddlewareOptions = {
|
|
47
|
+
* basePath: '/',
|
|
48
|
+
* routes: {
|
|
49
|
+
* signIn: '/signin',
|
|
50
|
+
* signOut: '/signout',
|
|
51
|
+
* accessToken: '/accesstoken',
|
|
52
|
+
* user: '/api/userinfo',
|
|
53
|
+
* }
|
|
54
|
+
* };
|
|
55
|
+
* const idpProtocolMiddleware = new IdpProtocolMiddleware(provider, middlewareOptions);
|
|
56
|
+
* idpProtocolMiddleware.register(app);
|
|
57
|
+
*/
|
|
58
|
+
export declare class IdpProtocolMiddleware {
|
|
59
|
+
private readonly provider;
|
|
60
|
+
/**
|
|
61
|
+
* The default base path for the protocol middleware.
|
|
62
|
+
*/
|
|
63
|
+
readonly DEFAULT_BASE_PATH = "/auth";
|
|
64
|
+
private readonly basePath;
|
|
65
|
+
private readonly routes;
|
|
66
|
+
/**
|
|
67
|
+
* The constructor for the protocol middleware.
|
|
68
|
+
* @param provider - The provider to use for the middleware.
|
|
69
|
+
* @param options - The options for the middleware.
|
|
70
|
+
*/
|
|
71
|
+
constructor(provider: IdpProvider, options?: IdpProtocolMiddlewareOptions);
|
|
72
|
+
/**
|
|
73
|
+
* Normalize the base path.
|
|
74
|
+
* @param path - The path to normalize.
|
|
75
|
+
* @returns The normalized path.
|
|
76
|
+
*/
|
|
77
|
+
private normalizeBasePath;
|
|
78
|
+
/**
|
|
79
|
+
* Validate the configuration.
|
|
80
|
+
*/
|
|
81
|
+
private validateConfiguration;
|
|
82
|
+
/**
|
|
83
|
+
* Create a route handler.
|
|
84
|
+
* @param handler - The handler to create.
|
|
85
|
+
* @returns The created handler.
|
|
86
|
+
*/
|
|
87
|
+
private createRouteHandler;
|
|
88
|
+
/**
|
|
89
|
+
* Register the protocol middleware routes with the express app.
|
|
90
|
+
* @param app - The express app to register the routes with.
|
|
91
|
+
* @example
|
|
92
|
+
* const app = express();
|
|
93
|
+
* const idpProtocolMiddleware = new IdpProtocolMiddleware(provider);
|
|
94
|
+
* idpProtocolMiddleware.register(app);
|
|
95
|
+
* app.listen(3000);
|
|
96
|
+
*/
|
|
97
|
+
register(app: Express): void;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=protocol-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-middleware.d.ts","sourceRoot":"","sources":["../../src/middleware/protocol-middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAmC,MAAM,SAAS,CAAC;AAEnE;;GAEG;AACH,oBAAY,aAAa;IACvB,OAAO,aAAa;IACpB,QAAQ,cAAc;IACtB,YAAY,kBAAkB;IAC9B,IAAI,cAAc;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAQD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,qBAAqB;IAc9B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAb3B;;OAEG;IACH,SAAgB,iBAAiB,WAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgE;IAEvF;;;;OAIG;gBAEgB,QAAQ,EAAE,WAAW,EACtC,OAAO,GAAE,4BAAiC;IAa5C;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAe7B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;;;;;;;OAQG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;CA6B7B"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The routes that are supported by the protocol middleware.
|
|
3
|
+
*/
|
|
4
|
+
export var ProtocolRoute;
|
|
5
|
+
(function (ProtocolRoute) {
|
|
6
|
+
ProtocolRoute["SIGN_IN"] = "/sign-in";
|
|
7
|
+
ProtocolRoute["SIGN_OUT"] = "/sign-out";
|
|
8
|
+
ProtocolRoute["ACCESS_TOKEN"] = "/access-token";
|
|
9
|
+
ProtocolRoute["USER"] = "/api/user";
|
|
10
|
+
})(ProtocolRoute || (ProtocolRoute = {}));
|
|
11
|
+
/**
|
|
12
|
+
* The protocol middleware for the IDP.
|
|
13
|
+
* @param provider - The provider to use for the middleware.
|
|
14
|
+
* @param options - The options for the middleware.
|
|
15
|
+
* @example // Register the middleware with the default routes
|
|
16
|
+
* const idpProtocolMiddleware = new IdpProtocolMiddleware(provider);
|
|
17
|
+
* idpProtocolMiddleware.register(app);
|
|
18
|
+
*
|
|
19
|
+
* @example // Override the default routes
|
|
20
|
+
* const app = express();
|
|
21
|
+
* const middlewareOptions: IdpProtocolMiddlewareOptions = {
|
|
22
|
+
* basePath: '/',
|
|
23
|
+
* routes: {
|
|
24
|
+
* signIn: '/signin',
|
|
25
|
+
* signOut: '/signout',
|
|
26
|
+
* accessToken: '/accesstoken',
|
|
27
|
+
* user: '/api/userinfo',
|
|
28
|
+
* }
|
|
29
|
+
* };
|
|
30
|
+
* const idpProtocolMiddleware = new IdpProtocolMiddleware(provider, middlewareOptions);
|
|
31
|
+
* idpProtocolMiddleware.register(app);
|
|
32
|
+
*/
|
|
33
|
+
export class IdpProtocolMiddleware {
|
|
34
|
+
provider;
|
|
35
|
+
/**
|
|
36
|
+
* The default base path for the protocol middleware.
|
|
37
|
+
*/
|
|
38
|
+
DEFAULT_BASE_PATH = '/auth';
|
|
39
|
+
basePath;
|
|
40
|
+
routes;
|
|
41
|
+
/**
|
|
42
|
+
* The constructor for the protocol middleware.
|
|
43
|
+
* @param provider - The provider to use for the middleware.
|
|
44
|
+
* @param options - The options for the middleware.
|
|
45
|
+
*/
|
|
46
|
+
constructor(provider, options = {}) {
|
|
47
|
+
this.provider = provider;
|
|
48
|
+
this.basePath = this.normalizeBasePath(options.basePath ?? this.DEFAULT_BASE_PATH);
|
|
49
|
+
this.routes = {
|
|
50
|
+
signIn: options.routes?.signIn ?? ProtocolRoute.SIGN_IN,
|
|
51
|
+
signOut: options.routes?.signOut ?? ProtocolRoute.SIGN_OUT,
|
|
52
|
+
accessToken: options.routes?.accessToken ?? ProtocolRoute.ACCESS_TOKEN,
|
|
53
|
+
user: options.routes?.user ?? ProtocolRoute.USER,
|
|
54
|
+
};
|
|
55
|
+
this.validateConfiguration();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Normalize the base path.
|
|
59
|
+
* @param path - The path to normalize.
|
|
60
|
+
* @returns The normalized path.
|
|
61
|
+
*/
|
|
62
|
+
normalizeBasePath(path) {
|
|
63
|
+
if (!path.startsWith('/')) {
|
|
64
|
+
throw new Error(`Base path must start with '/': ${path}`);
|
|
65
|
+
}
|
|
66
|
+
return path.endsWith('/') && path !== '/' ? path.slice(0, -1) : path;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Validate the configuration.
|
|
70
|
+
*/
|
|
71
|
+
validateConfiguration() {
|
|
72
|
+
const routePaths = Object.values(this.routes);
|
|
73
|
+
const duplicates = routePaths.filter((path, index) => routePaths.indexOf(path) !== index);
|
|
74
|
+
if (duplicates.length > 0) {
|
|
75
|
+
throw new Error(`Duplicate route paths detected: ${duplicates.join(', ')}`);
|
|
76
|
+
}
|
|
77
|
+
routePaths.forEach(path => {
|
|
78
|
+
if (!path.startsWith('/')) {
|
|
79
|
+
throw new Error(`Route path must start with '/': ${path}`);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create a route handler.
|
|
85
|
+
* @param handler - The handler to create.
|
|
86
|
+
* @returns The created handler.
|
|
87
|
+
*/
|
|
88
|
+
createRouteHandler(handler) {
|
|
89
|
+
return async (req, res, next) => {
|
|
90
|
+
try {
|
|
91
|
+
await handler(req, res, next);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
next(error);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Register the protocol middleware routes with the express app.
|
|
100
|
+
* @param app - The express app to register the routes with.
|
|
101
|
+
* @example
|
|
102
|
+
* const app = express();
|
|
103
|
+
* const idpProtocolMiddleware = new IdpProtocolMiddleware(provider);
|
|
104
|
+
* idpProtocolMiddleware.register(app);
|
|
105
|
+
* app.listen(3000);
|
|
106
|
+
*/
|
|
107
|
+
register(app) {
|
|
108
|
+
const routeConfigs = [
|
|
109
|
+
{
|
|
110
|
+
path: this.routes.signIn,
|
|
111
|
+
handler: (req, res, next) => this.provider.signInMiddleware(req, res, next),
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
path: this.routes.signOut,
|
|
115
|
+
handler: (req, res, next) => this.provider.signOutMiddleware(req, res, next),
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
path: this.routes.accessToken,
|
|
119
|
+
handler: (req, res, next) => this.provider.accessTokenMiddleware(req, res, next),
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
path: this.routes.user,
|
|
123
|
+
handler: (req, res, next) => this.provider.userApiMiddleware(req, res, next),
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
routeConfigs.forEach(({ path, handler }) => {
|
|
127
|
+
const fullPath = `${this.basePath}${path}`;
|
|
128
|
+
app.all(fullPath, this.createRouteHandler(handler));
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NullIdpProvider } from './null-provider.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IdpProvider } from '../types/provider.js';
|
|
2
|
+
import { AuthResult, Payload } from '../types/models.js';
|
|
3
|
+
import { Request, Response, NextFunction } from 'express';
|
|
4
|
+
/**
|
|
5
|
+
* NULL IDP Provider - single user, single project
|
|
6
|
+
* Used for deployments without user management and development
|
|
7
|
+
*/
|
|
8
|
+
export declare class NullIdpProvider implements IdpProvider {
|
|
9
|
+
private defaultPayload;
|
|
10
|
+
private defaultAccessToken;
|
|
11
|
+
private defaultRefreshToken;
|
|
12
|
+
constructor();
|
|
13
|
+
refreshToken(_refreshToken: string): Promise<AuthResult>;
|
|
14
|
+
signInMiddleware(_req: Request, _res: Response, _next: NextFunction): Promise<void>;
|
|
15
|
+
signOutMiddleware(_req: Request, _res: Response, _next: NextFunction): Promise<void>;
|
|
16
|
+
accessTokenMiddleware(_req: Request, res: Response, _next: NextFunction): Promise<Response>;
|
|
17
|
+
userApiMiddleware(_req: Request, res: Response, _next: NextFunction): Promise<Response<Payload>>;
|
|
18
|
+
initialize(): Promise<void>;
|
|
19
|
+
shutdown(): Promise<void>;
|
|
20
|
+
introspectToken(_token: string): Promise<Payload | null>;
|
|
21
|
+
parseToken(_token: string): Promise<Payload | null>;
|
|
22
|
+
revokeToken(_token: string): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=null-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"null-provider.d.ts","sourceRoot":"","sources":["../../src/providers/null-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D;;;GAGG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,mBAAmB,CAAS;;IAc9B,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAM9D,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnF,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpF,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI3F,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAI1F,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAIxD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAInD,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGjD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NULL IDP Provider - single user, single project
|
|
3
|
+
* Used for deployments without user management and development
|
|
4
|
+
*/
|
|
5
|
+
export class NullIdpProvider {
|
|
6
|
+
defaultPayload;
|
|
7
|
+
defaultAccessToken;
|
|
8
|
+
defaultRefreshToken;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.defaultPayload = {
|
|
11
|
+
userId: '0',
|
|
12
|
+
email: 'admin@localhost',
|
|
13
|
+
roles: ['admin'],
|
|
14
|
+
fullName: 'Admin',
|
|
15
|
+
projectId: '0',
|
|
16
|
+
};
|
|
17
|
+
this.defaultAccessToken = 'accessToken';
|
|
18
|
+
this.defaultRefreshToken = 'refreshToken';
|
|
19
|
+
}
|
|
20
|
+
async refreshToken(_refreshToken) {
|
|
21
|
+
return {
|
|
22
|
+
accessToken: this.defaultAccessToken,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
signInMiddleware(_req, _res, _next) {
|
|
26
|
+
_res.cookie('refreshToken', this.defaultRefreshToken, {
|
|
27
|
+
httpOnly: true,
|
|
28
|
+
secure: true,
|
|
29
|
+
maxAge: 3600000,
|
|
30
|
+
});
|
|
31
|
+
return Promise.resolve(_res.redirect('/'));
|
|
32
|
+
}
|
|
33
|
+
signOutMiddleware(_req, _res, _next) {
|
|
34
|
+
_res.clearCookie('refreshToken');
|
|
35
|
+
return Promise.resolve(_res.redirect('/'));
|
|
36
|
+
}
|
|
37
|
+
accessTokenMiddleware(_req, res, _next) {
|
|
38
|
+
return Promise.resolve(res.json({ accessToken: this.defaultAccessToken }));
|
|
39
|
+
}
|
|
40
|
+
userApiMiddleware(_req, res, _next) {
|
|
41
|
+
return Promise.resolve(res.json(this.defaultPayload));
|
|
42
|
+
}
|
|
43
|
+
async initialize() {
|
|
44
|
+
// Nothing to initialize
|
|
45
|
+
}
|
|
46
|
+
async shutdown() {
|
|
47
|
+
// Nothing to cleanup
|
|
48
|
+
}
|
|
49
|
+
async introspectToken(_token) {
|
|
50
|
+
return this.defaultPayload;
|
|
51
|
+
}
|
|
52
|
+
async parseToken(_token) {
|
|
53
|
+
return this.defaultPayload;
|
|
54
|
+
}
|
|
55
|
+
async revokeToken(_token) {
|
|
56
|
+
// No-op for NULL provider
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Payload } from './models.js';
|
|
2
|
+
/**
|
|
3
|
+
* Commands for adding a user to the IDP by app cli.
|
|
4
|
+
*/
|
|
5
|
+
export interface IdpProviderAddUserCommand {
|
|
6
|
+
addUser(username: string, password?: string): Promise<AddUserCommandResponse>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Commands for listing users from the IDP
|
|
10
|
+
*/
|
|
11
|
+
export interface IdpProviderListUsersCommand {
|
|
12
|
+
listUsers(): Promise<Payload[]>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Commands for removing a user from the IDP
|
|
16
|
+
*/
|
|
17
|
+
export interface IdpProviderRemoveUserCommand {
|
|
18
|
+
removeUser(userId: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Response for adding a user to the IDP
|
|
22
|
+
*/
|
|
23
|
+
export interface AddUserCommandResponse {
|
|
24
|
+
username: string;
|
|
25
|
+
magicLink?: string;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/types/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC/E;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|