@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.
Files changed (46) hide show
  1. package/README.md +298 -0
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +6 -0
  5. package/dist/middleware/index.d.ts +2 -0
  6. package/dist/middleware/index.d.ts.map +1 -0
  7. package/dist/middleware/index.js +1 -0
  8. package/dist/middleware/protocol-middleware.d.ts +99 -0
  9. package/dist/middleware/protocol-middleware.d.ts.map +1 -0
  10. package/dist/middleware/protocol-middleware.js +131 -0
  11. package/dist/providers/index.d.ts +2 -0
  12. package/dist/providers/index.d.ts.map +1 -0
  13. package/dist/providers/index.js +1 -0
  14. package/dist/providers/null-provider.d.ts +24 -0
  15. package/dist/providers/null-provider.d.ts.map +1 -0
  16. package/dist/providers/null-provider.js +58 -0
  17. package/dist/types/cli.d.ts +27 -0
  18. package/dist/types/cli.d.ts.map +1 -0
  19. package/dist/types/cli.js +1 -0
  20. package/dist/types/config.d.ts +14 -0
  21. package/dist/types/config.d.ts.map +1 -0
  22. package/dist/types/config.js +1 -0
  23. package/dist/types/errors.d.ts +33 -0
  24. package/dist/types/errors.d.ts.map +1 -0
  25. package/dist/types/errors.js +45 -0
  26. package/dist/types/index.d.ts +9 -0
  27. package/dist/types/index.d.ts.map +1 -0
  28. package/dist/types/index.js +13 -0
  29. package/dist/types/models.d.ts +24 -0
  30. package/dist/types/models.d.ts.map +1 -0
  31. package/dist/types/models.js +1 -0
  32. package/dist/types/provider.d.ts +63 -0
  33. package/dist/types/provider.d.ts.map +1 -0
  34. package/dist/types/provider.js +1 -0
  35. package/package.json +52 -0
  36. package/src/index.ts +8 -0
  37. package/src/middleware/index.ts +1 -0
  38. package/src/middleware/protocol-middleware.ts +178 -0
  39. package/src/providers/index.ts +1 -0
  40. package/src/providers/null-provider.ts +71 -0
  41. package/src/types/cli.ts +30 -0
  42. package/src/types/config.ts +14 -0
  43. package/src/types/errors.ts +49 -0
  44. package/src/types/index.ts +18 -0
  45. package/src/types/models.ts +28 -0
  46. package/src/types/provider.ts +72 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Configuration for the IDP provider
3
+ */
4
+ export interface IdpConfig {
5
+ /**
6
+ * Base URL for the IDP provider
7
+ */
8
+ baseUrl: string;
9
+ /**
10
+ * Additional provider-specific configuration
11
+ */
12
+ [key: string]: unknown;
13
+ }
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Base error class for the IDP protocol
3
+ */
4
+ export declare class IdpError extends Error {
5
+ code: string;
6
+ statusCode: number;
7
+ constructor(message: string, code: string, statusCode?: number);
8
+ }
9
+ /**
10
+ * Authentication error
11
+ */
12
+ export declare class AuthenticationError extends IdpError {
13
+ constructor(message?: string);
14
+ }
15
+ /**
16
+ * Authorization error
17
+ */
18
+ export declare class AuthorizationError extends IdpError {
19
+ constructor(message?: string);
20
+ }
21
+ /**
22
+ * Token expired error
23
+ */
24
+ export declare class TokenExpiredError extends IdpError {
25
+ constructor(message?: string);
26
+ }
27
+ /**
28
+ * Invalid token error
29
+ */
30
+ export declare class InvalidTokenError extends IdpError {
31
+ constructor(message?: string);
32
+ }
33
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IAGxB,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,MAAM;gBAFzB,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAAY;CAKlC;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,GAAE,MAAgC;CAGtD;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,OAAO,GAAE,MAAmC;CAGzD;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,OAAO,GAAE,MAA4B;CAGlD;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,OAAO,GAAE,MAAwB;CAG9C"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Base error class for the IDP protocol
3
+ */
4
+ export class IdpError extends Error {
5
+ code;
6
+ statusCode;
7
+ constructor(message, code, statusCode = 400) {
8
+ super(message);
9
+ this.code = code;
10
+ this.statusCode = statusCode;
11
+ this.name = 'IdpError';
12
+ }
13
+ }
14
+ /**
15
+ * Authentication error
16
+ */
17
+ export class AuthenticationError extends IdpError {
18
+ constructor(message = 'Authentication failed') {
19
+ super(message, 'AUTHENTICATION_ERROR', 401);
20
+ }
21
+ }
22
+ /**
23
+ * Authorization error
24
+ */
25
+ export class AuthorizationError extends IdpError {
26
+ constructor(message = 'Insufficient permissions') {
27
+ super(message, 'AUTHORIZATION_ERROR', 403);
28
+ }
29
+ }
30
+ /**
31
+ * Token expired error
32
+ */
33
+ export class TokenExpiredError extends IdpError {
34
+ constructor(message = 'Token has expired') {
35
+ super(message, 'TOKEN_EXPIRED', 401);
36
+ }
37
+ }
38
+ /**
39
+ * Invalid token error
40
+ */
41
+ export class InvalidTokenError extends IdpError {
42
+ constructor(message = 'Invalid token') {
43
+ super(message, 'INVALID_TOKEN', 401);
44
+ }
45
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Main types export - organized by category
3
+ */
4
+ export * from './provider.js';
5
+ export * from './models.js';
6
+ export * from './config.js';
7
+ export * from './errors.js';
8
+ export * from './cli.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,eAAe,CAAC;AAG9B,cAAc,aAAa,CAAC;AAG5B,cAAc,aAAa,CAAC;AAG5B,cAAc,aAAa,CAAC;AAG5B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Main types export - organized by category
3
+ */
4
+ // Core provider interface
5
+ export * from './provider.js';
6
+ // Domain models
7
+ export * from './models.js';
8
+ // Configuration
9
+ export * from './config.js';
10
+ // Error classes
11
+ export * from './errors.js';
12
+ // CLI commands
13
+ export * from './cli.js';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The roles that are supported by the IDP.
3
+ */
4
+ export type Role = 'admin' | 'editor' | 'viewer';
5
+ /**
6
+ * Standardized token payload that all IDP implementations must return when introspecting their native tokens.
7
+ */
8
+ export interface Payload {
9
+ userId: string;
10
+ projectId: string;
11
+ email?: string;
12
+ fullName?: string;
13
+ avatar?: string;
14
+ roles?: Role[];
15
+ projectTitle?: string;
16
+ }
17
+ /**
18
+ * Authentication result from IDP callback
19
+ */
20
+ export interface AuthResult {
21
+ accessToken: string;
22
+ refreshToken?: string;
23
+ }
24
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/types/models.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAElB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IAEf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,63 @@
1
+ import { Payload, AuthResult } from './models.js';
2
+ import { NextFunction, Request, Response } from 'express';
3
+ /**
4
+ * Simplified IDP Provider interface.
5
+ */
6
+ export interface IdpProvider {
7
+ /**
8
+ * Sign in middleware. This method is used to handle the sign in request and use response to send the sign in response.
9
+ * <br/>
10
+ * If the IDP implementation does not support sign in, this method should call the `next()` function.
11
+ */
12
+ signInMiddleware(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
13
+ /**
14
+ * Sign out middleware. This method is used to handle the sign out request and use response to send the sign out response.
15
+ * <br/>
16
+ * If the IDP implementation does not support sign out, this method should call the `next()` function.
17
+ */
18
+ signOutMiddleware(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
19
+ /**
20
+ * Access token middleware. This method is used to handle the access token request and use response to send the access token response.
21
+ * <br/>
22
+ * If the IDP implementation does not support access token, this method should call the `next()` function.
23
+ */
24
+ accessTokenMiddleware(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
25
+ /**
26
+ * User api middleware. This method is used to handle the user request and use response to send the user response.
27
+ * <br/>
28
+ * If the IDP implementation does not support user, this method should call the `next()` function.
29
+ */
30
+ userApiMiddleware(req: Request, res: Response, next: NextFunction): Promise<Response<Payload>>;
31
+ /**
32
+ * Introspect a token
33
+ * @param token - The token to introspect
34
+ * @returns The token payload
35
+ */
36
+ introspectToken(token: string): Promise<Payload | null>;
37
+ /**
38
+ * Parse a token
39
+ * @param token - The token to parse
40
+ * @returns The token payload
41
+ */
42
+ parseToken(token: string): Promise<Payload | null>;
43
+ /**
44
+ * Refresh a token
45
+ * @param refreshToken - The refresh token to use for the refresh
46
+ * @returns The authentication result
47
+ */
48
+ refreshToken(refreshToken: string): Promise<AuthResult>;
49
+ /**
50
+ * Revoke a token. In different IDP implementations, this may have different token types.
51
+ * @param token - The token to revoke
52
+ */
53
+ revokeToken(token: string): Promise<void>;
54
+ /**
55
+ * Initialize the IDP. Create resources, connect to databases, etc.
56
+ */
57
+ initialize(): Promise<void>;
58
+ /**
59
+ * Shutdown the IDP, close all connections and release resources
60
+ */
61
+ shutdown(): Promise<void>;
62
+ }
63
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/types/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;IAE5F;;;;OAIG;IACH,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;IAE7F;;;;OAIG;IACH,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;IAEjG;;;;OAIG;IACH,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAE/F;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAExD;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAEnD;;;;OAIG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAExD;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;OAEG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@owox/idp-protocol",
3
+ "version": "0.4.0",
4
+ "type": "module",
5
+ "author": "OWOX",
6
+ "license": "ELv2",
7
+ "description": "Identity Provider protocol contracts and interfaces for OWOX Data Marts",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "engines": {
12
+ "node": ">=22.16.0"
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "clean": "rimraf dist",
17
+ "test": "jest",
18
+ "lint": "eslint . --config ./eslint.config.js",
19
+ "lint:fix": "eslint . --fix --config ./eslint.config.js",
20
+ "format": "prettier --write \"**/*.{ts,js,json,md}\"",
21
+ "format:check": "prettier --check \"**/*.{ts,js,json,md}\"",
22
+ "typecheck": "tsc --noEmit",
23
+ "prepack": "npm run build",
24
+ "prepublishOnly": "npm audit && npm run lint && npm run typecheck"
25
+ },
26
+ "keywords": [
27
+ "idp",
28
+ "authentication",
29
+ "owox"
30
+ ],
31
+ "peerDependencies": {
32
+ "express": "^5"
33
+ },
34
+ "devDependencies": {
35
+ "@types/express": "^5.0.0",
36
+ "@types/node": "^22.10.7",
37
+ "typescript": "^5.7.3"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "src"
42
+ ],
43
+ "exports": {
44
+ ".": {
45
+ "import": "./dist/index.js",
46
+ "require": "./dist/index.js",
47
+ "types": "./dist/index.d.ts"
48
+ }
49
+ },
50
+ "main": "./dist/index.js",
51
+ "types": "./dist/index.d.ts"
52
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ // Core types and interfaces
2
+ export * from './types/index.js';
3
+
4
+ // Provider implementations (only NULL provider)
5
+ export * from './providers/index.js';
6
+
7
+ // Middleware
8
+ export * from './middleware/index.js';
@@ -0,0 +1 @@
1
+ export * from './protocol-middleware.js';
@@ -0,0 +1,178 @@
1
+ import { IdpProvider } from '../types/provider.js';
2
+ import { Express, Request, Response, NextFunction } from 'express';
3
+
4
+ /**
5
+ * The routes that are supported by the protocol middleware.
6
+ */
7
+ export enum ProtocolRoute {
8
+ SIGN_IN = '/sign-in',
9
+ SIGN_OUT = '/sign-out',
10
+ ACCESS_TOKEN = '/access-token',
11
+ USER = '/api/user',
12
+ }
13
+
14
+ /**
15
+ * The options for the protocol middleware.
16
+ * @property basePath - The base path for the protoc ol middleware.
17
+ * @property routes - The routes that are supported by the protocol middleware.
18
+ * @example
19
+ * {
20
+ * basePath: '/',
21
+ * routes: {
22
+ * signIn: '/signin', // override the default sign in route
23
+ * signOut: '/signout', // override the default sign out route
24
+ * accessToken: '/accesstoken', // override the default access token route
25
+ * user: '/api/userinfo', // override the default user route
26
+ * },
27
+ * }
28
+ */
29
+ export interface IdpProtocolMiddlewareOptions {
30
+ basePath?: string;
31
+ routes?: {
32
+ signIn?: string;
33
+ signOut?: string;
34
+ accessToken?: string;
35
+ user?: string;
36
+ };
37
+ }
38
+
39
+ type MiddlewareHandler = (
40
+ req: Request,
41
+ res: Response,
42
+ next: NextFunction
43
+ ) => Promise<void | Response>;
44
+
45
+ /**
46
+ * The protocol middleware for the IDP.
47
+ * @param provider - The provider to use for the middleware.
48
+ * @param options - The options for the middleware.
49
+ * @example // Register the middleware with the default routes
50
+ * const idpProtocolMiddleware = new IdpProtocolMiddleware(provider);
51
+ * idpProtocolMiddleware.register(app);
52
+ *
53
+ * @example // Override the default routes
54
+ * const app = express();
55
+ * const middlewareOptions: IdpProtocolMiddlewareOptions = {
56
+ * basePath: '/',
57
+ * routes: {
58
+ * signIn: '/signin',
59
+ * signOut: '/signout',
60
+ * accessToken: '/accesstoken',
61
+ * user: '/api/userinfo',
62
+ * }
63
+ * };
64
+ * const idpProtocolMiddleware = new IdpProtocolMiddleware(provider, middlewareOptions);
65
+ * idpProtocolMiddleware.register(app);
66
+ */
67
+ export class IdpProtocolMiddleware {
68
+ /**
69
+ * The default base path for the protocol middleware.
70
+ */
71
+ public readonly DEFAULT_BASE_PATH = '/auth';
72
+ private readonly basePath: string;
73
+ private readonly routes: Required<NonNullable<IdpProtocolMiddlewareOptions['routes']>>;
74
+
75
+ /**
76
+ * The constructor for the protocol middleware.
77
+ * @param provider - The provider to use for the middleware.
78
+ * @param options - The options for the middleware.
79
+ */
80
+ constructor(
81
+ private readonly provider: IdpProvider,
82
+ options: IdpProtocolMiddlewareOptions = {}
83
+ ) {
84
+ this.basePath = this.normalizeBasePath(options.basePath ?? this.DEFAULT_BASE_PATH);
85
+ this.routes = {
86
+ signIn: options.routes?.signIn ?? ProtocolRoute.SIGN_IN,
87
+ signOut: options.routes?.signOut ?? ProtocolRoute.SIGN_OUT,
88
+ accessToken: options.routes?.accessToken ?? ProtocolRoute.ACCESS_TOKEN,
89
+ user: options.routes?.user ?? ProtocolRoute.USER,
90
+ };
91
+
92
+ this.validateConfiguration();
93
+ }
94
+
95
+ /**
96
+ * Normalize the base path.
97
+ * @param path - The path to normalize.
98
+ * @returns The normalized path.
99
+ */
100
+ private normalizeBasePath(path: string): string {
101
+ if (!path.startsWith('/')) {
102
+ throw new Error(`Base path must start with '/': ${path}`);
103
+ }
104
+ return path.endsWith('/') && path !== '/' ? path.slice(0, -1) : path;
105
+ }
106
+
107
+ /**
108
+ * Validate the configuration.
109
+ */
110
+ private validateConfiguration(): void {
111
+ const routePaths = Object.values(this.routes);
112
+ const duplicates = routePaths.filter((path, index) => routePaths.indexOf(path) !== index);
113
+
114
+ if (duplicates.length > 0) {
115
+ throw new Error(`Duplicate route paths detected: ${duplicates.join(', ')}`);
116
+ }
117
+
118
+ routePaths.forEach(path => {
119
+ if (!path.startsWith('/')) {
120
+ throw new Error(`Route path must start with '/': ${path}`);
121
+ }
122
+ });
123
+ }
124
+
125
+ /**
126
+ * Create a route handler.
127
+ * @param handler - The handler to create.
128
+ * @returns The created handler.
129
+ */
130
+ private createRouteHandler(handler: MiddlewareHandler): MiddlewareHandler {
131
+ return async (req: Request, res: Response, next: NextFunction) => {
132
+ try {
133
+ await handler(req, res, next);
134
+ } catch (error) {
135
+ next(error);
136
+ }
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Register the protocol middleware routes with the express app.
142
+ * @param app - The express app to register the routes with.
143
+ * @example
144
+ * const app = express();
145
+ * const idpProtocolMiddleware = new IdpProtocolMiddleware(provider);
146
+ * idpProtocolMiddleware.register(app);
147
+ * app.listen(3000);
148
+ */
149
+ register(app: Express): void {
150
+ const routeConfigs = [
151
+ {
152
+ path: this.routes.signIn,
153
+ handler: (req: Request, res: Response, next: NextFunction) =>
154
+ this.provider.signInMiddleware(req, res, next),
155
+ },
156
+ {
157
+ path: this.routes.signOut,
158
+ handler: (req: Request, res: Response, next: NextFunction) =>
159
+ this.provider.signOutMiddleware(req, res, next),
160
+ },
161
+ {
162
+ path: this.routes.accessToken,
163
+ handler: (req: Request, res: Response, next: NextFunction) =>
164
+ this.provider.accessTokenMiddleware(req, res, next),
165
+ },
166
+ {
167
+ path: this.routes.user,
168
+ handler: (req: Request, res: Response, next: NextFunction) =>
169
+ this.provider.userApiMiddleware(req, res, next),
170
+ },
171
+ ];
172
+
173
+ routeConfigs.forEach(({ path, handler }) => {
174
+ const fullPath = `${this.basePath}${path}`;
175
+ app.all(fullPath, this.createRouteHandler(handler));
176
+ });
177
+ }
178
+ }
@@ -0,0 +1 @@
1
+ export { NullIdpProvider } from './null-provider.js';
@@ -0,0 +1,71 @@
1
+ import { IdpProvider } from '../types/provider.js';
2
+ import { AuthResult, Payload } from '../types/models.js';
3
+ import { Request, Response, NextFunction } from 'express';
4
+
5
+ /**
6
+ * NULL IDP Provider - single user, single project
7
+ * Used for deployments without user management and development
8
+ */
9
+ export class NullIdpProvider implements IdpProvider {
10
+ private defaultPayload: Payload;
11
+ private defaultAccessToken: string;
12
+ private defaultRefreshToken: string;
13
+
14
+ constructor() {
15
+ this.defaultPayload = {
16
+ userId: '0',
17
+ email: 'admin@localhost',
18
+ roles: ['admin'],
19
+ fullName: 'Admin',
20
+ projectId: '0',
21
+ };
22
+ this.defaultAccessToken = 'accessToken';
23
+ this.defaultRefreshToken = 'refreshToken';
24
+ }
25
+
26
+ async refreshToken(_refreshToken: string): Promise<AuthResult> {
27
+ return {
28
+ accessToken: this.defaultAccessToken,
29
+ };
30
+ }
31
+
32
+ signInMiddleware(_req: Request, _res: Response, _next: NextFunction): Promise<void> {
33
+ _res.cookie('refreshToken', this.defaultRefreshToken, {
34
+ httpOnly: true,
35
+ secure: true,
36
+ maxAge: 3600000,
37
+ });
38
+ return Promise.resolve(_res.redirect('/'));
39
+ }
40
+ signOutMiddleware(_req: Request, _res: Response, _next: NextFunction): Promise<void> {
41
+ _res.clearCookie('refreshToken');
42
+ return Promise.resolve(_res.redirect('/'));
43
+ }
44
+ accessTokenMiddleware(_req: Request, res: Response, _next: NextFunction): Promise<Response> {
45
+ return Promise.resolve(res.json({ accessToken: this.defaultAccessToken }));
46
+ }
47
+
48
+ userApiMiddleware(_req: Request, res: Response, _next: NextFunction): Promise<Response<Payload>> {
49
+ return Promise.resolve(res.json(this.defaultPayload));
50
+ }
51
+
52
+ async initialize(): Promise<void> {
53
+ // Nothing to initialize
54
+ }
55
+
56
+ async shutdown(): Promise<void> {
57
+ // Nothing to cleanup
58
+ }
59
+
60
+ async introspectToken(_token: string): Promise<Payload | null> {
61
+ return this.defaultPayload;
62
+ }
63
+
64
+ async parseToken(_token: string): Promise<Payload | null> {
65
+ return this.defaultPayload;
66
+ }
67
+
68
+ async revokeToken(_token: string): Promise<void> {
69
+ // No-op for NULL provider
70
+ }
71
+ }
@@ -0,0 +1,30 @@
1
+ import { Payload } from './models.js';
2
+
3
+ /**
4
+ * Commands for adding a user to the IDP by app cli.
5
+ */
6
+ export interface IdpProviderAddUserCommand {
7
+ addUser(username: string, password?: string): Promise<AddUserCommandResponse>;
8
+ }
9
+
10
+ /**
11
+ * Commands for listing users from the IDP
12
+ */
13
+ export interface IdpProviderListUsersCommand {
14
+ listUsers(): Promise<Payload[]>;
15
+ }
16
+
17
+ /**
18
+ * Commands for removing a user from the IDP
19
+ */
20
+ export interface IdpProviderRemoveUserCommand {
21
+ removeUser(userId: string): Promise<void>;
22
+ }
23
+
24
+ /**
25
+ * Response for adding a user to the IDP
26
+ */
27
+ export interface AddUserCommandResponse {
28
+ username: string;
29
+ magicLink?: string;
30
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Configuration for the IDP provider
3
+ */
4
+ export interface IdpConfig {
5
+ /**
6
+ * Base URL for the IDP provider
7
+ */
8
+ baseUrl: string;
9
+
10
+ /**
11
+ * Additional provider-specific configuration
12
+ */
13
+ [key: string]: unknown;
14
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Base error class for the IDP protocol
3
+ */
4
+ export class IdpError extends Error {
5
+ constructor(
6
+ message: string,
7
+ public code: string,
8
+ public statusCode: number = 400
9
+ ) {
10
+ super(message);
11
+ this.name = 'IdpError';
12
+ }
13
+ }
14
+
15
+ /**
16
+ * Authentication error
17
+ */
18
+ export class AuthenticationError extends IdpError {
19
+ constructor(message: string = 'Authentication failed') {
20
+ super(message, 'AUTHENTICATION_ERROR', 401);
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Authorization error
26
+ */
27
+ export class AuthorizationError extends IdpError {
28
+ constructor(message: string = 'Insufficient permissions') {
29
+ super(message, 'AUTHORIZATION_ERROR', 403);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Token expired error
35
+ */
36
+ export class TokenExpiredError extends IdpError {
37
+ constructor(message: string = 'Token has expired') {
38
+ super(message, 'TOKEN_EXPIRED', 401);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Invalid token error
44
+ */
45
+ export class InvalidTokenError extends IdpError {
46
+ constructor(message: string = 'Invalid token') {
47
+ super(message, 'INVALID_TOKEN', 401);
48
+ }
49
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Main types export - organized by category
3
+ */
4
+
5
+ // Core provider interface
6
+ export * from './provider.js';
7
+
8
+ // Domain models
9
+ export * from './models.js';
10
+
11
+ // Configuration
12
+ export * from './config.js';
13
+
14
+ // Error classes
15
+ export * from './errors.js';
16
+
17
+ // CLI commands
18
+ export * from './cli.js';