@forjio/engine-auth 0.1.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/dist/__tests__/api-keys.test.d.ts +2 -0
- package/dist/__tests__/api-keys.test.d.ts.map +1 -0
- package/dist/__tests__/api-keys.test.js +78 -0
- package/dist/__tests__/api-keys.test.js.map +1 -0
- package/dist/__tests__/helpers/express-mock.d.ts +13 -0
- package/dist/__tests__/helpers/express-mock.d.ts.map +1 -0
- package/dist/__tests__/helpers/express-mock.js +46 -0
- package/dist/__tests__/helpers/express-mock.js.map +1 -0
- package/dist/__tests__/helpers/redis-mock.d.ts +19 -0
- package/dist/__tests__/helpers/redis-mock.d.ts.map +1 -0
- package/dist/__tests__/helpers/redis-mock.js +69 -0
- package/dist/__tests__/helpers/redis-mock.js.map +1 -0
- package/dist/__tests__/jwt.test.d.ts +2 -0
- package/dist/__tests__/jwt.test.d.ts.map +1 -0
- package/dist/__tests__/jwt.test.js +98 -0
- package/dist/__tests__/jwt.test.js.map +1 -0
- package/dist/__tests__/middleware.test.d.ts +2 -0
- package/dist/__tests__/middleware.test.d.ts.map +1 -0
- package/dist/__tests__/middleware.test.js +173 -0
- package/dist/__tests__/middleware.test.js.map +1 -0
- package/dist/__tests__/session.test.d.ts +2 -0
- package/dist/__tests__/session.test.d.ts.map +1 -0
- package/dist/__tests__/session.test.js +96 -0
- package/dist/__tests__/session.test.js.map +1 -0
- package/dist/api-keys.d.ts +29 -0
- package/dist/api-keys.d.ts.map +1 -0
- package/dist/api-keys.js +50 -0
- package/dist/api-keys.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt.d.ts +7 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +66 -0
- package/dist/jwt.js.map +1 -0
- package/dist/middleware.d.ts +29 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +94 -0
- package/dist/middleware.js.map +1 -0
- package/dist/oauth.d.ts +16 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +78 -0
- package/dist/oauth.js.map +1 -0
- package/dist/session.d.ts +9 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +61 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
- package/src/__tests__/api-keys.test.ts +94 -0
- package/src/__tests__/helpers/express-mock.ts +47 -0
- package/src/__tests__/helpers/redis-mock.ts +65 -0
- package/src/__tests__/jwt.test.ts +122 -0
- package/src/__tests__/middleware.test.ts +220 -0
- package/src/__tests__/session.test.ts +120 -0
- package/src/api-keys.ts +56 -0
- package/src/index.ts +46 -0
- package/src/jwt.ts +61 -0
- package/src/middleware.ts +113 -0
- package/src/oauth.ts +111 -0
- package/src/session.ts +78 -0
- package/src/types.ts +45 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +21 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const redis_mock_1 = require("./helpers/redis-mock");
|
|
5
|
+
// Mock ioredis before importing session module
|
|
6
|
+
const redisMock = new redis_mock_1.RedisMock();
|
|
7
|
+
vitest_1.vi.mock('ioredis', () => ({
|
|
8
|
+
default: vitest_1.vi.fn(() => redisMock),
|
|
9
|
+
}));
|
|
10
|
+
// Import after mock is set up
|
|
11
|
+
const session_1 = require("../session");
|
|
12
|
+
const TEST_SESSION = {
|
|
13
|
+
userId: 'user-456',
|
|
14
|
+
email: 'session@example.com',
|
|
15
|
+
role: 'user',
|
|
16
|
+
productSlug: 'portal',
|
|
17
|
+
expiresAt: Date.now() + 3600_000, // 1 hour from now
|
|
18
|
+
};
|
|
19
|
+
(0, vitest_1.describe)('session store', () => {
|
|
20
|
+
let store;
|
|
21
|
+
(0, vitest_1.beforeEach)(() => {
|
|
22
|
+
redisMock.clear();
|
|
23
|
+
store = (0, session_1.createSessionStore)('redis://localhost:6379');
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.describe)('create', () => {
|
|
26
|
+
(0, vitest_1.it)('should create session and return session ID', async () => {
|
|
27
|
+
const sessionId = await store.create(TEST_SESSION);
|
|
28
|
+
(0, vitest_1.expect)(sessionId).toBeDefined();
|
|
29
|
+
(0, vitest_1.expect)(typeof sessionId).toBe('string');
|
|
30
|
+
(0, vitest_1.expect)(sessionId.length).toBeGreaterThan(0);
|
|
31
|
+
});
|
|
32
|
+
(0, vitest_1.it)('should store session data retrievable by ID', async () => {
|
|
33
|
+
const sessionId = await store.create(TEST_SESSION);
|
|
34
|
+
const retrieved = await store.get(sessionId);
|
|
35
|
+
(0, vitest_1.expect)(retrieved).not.toBeNull();
|
|
36
|
+
(0, vitest_1.expect)(retrieved.userId).toBe('user-456');
|
|
37
|
+
(0, vitest_1.expect)(retrieved.email).toBe('session@example.com');
|
|
38
|
+
(0, vitest_1.expect)(retrieved.role).toBe('user');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.describe)('get', () => {
|
|
42
|
+
(0, vitest_1.it)('should return session data for valid ID', async () => {
|
|
43
|
+
const sessionId = await store.create(TEST_SESSION);
|
|
44
|
+
const session = await store.get(sessionId);
|
|
45
|
+
(0, vitest_1.expect)(session).not.toBeNull();
|
|
46
|
+
(0, vitest_1.expect)(session.userId).toBe(TEST_SESSION.userId);
|
|
47
|
+
(0, vitest_1.expect)(session.productSlug).toBe(TEST_SESSION.productSlug);
|
|
48
|
+
});
|
|
49
|
+
(0, vitest_1.it)('should return null for non-existent ID', async () => {
|
|
50
|
+
const session = await store.get('non-existent-id');
|
|
51
|
+
(0, vitest_1.expect)(session).toBeNull();
|
|
52
|
+
});
|
|
53
|
+
(0, vitest_1.it)('should return null for logically expired session', async () => {
|
|
54
|
+
const expiredSession = {
|
|
55
|
+
...TEST_SESSION,
|
|
56
|
+
expiresAt: Date.now() - 1000, // already expired
|
|
57
|
+
};
|
|
58
|
+
const sessionId = await store.create(expiredSession);
|
|
59
|
+
const session = await store.get(sessionId);
|
|
60
|
+
(0, vitest_1.expect)(session).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.describe)('destroy', () => {
|
|
64
|
+
(0, vitest_1.it)('should remove session', async () => {
|
|
65
|
+
const sessionId = await store.create(TEST_SESSION);
|
|
66
|
+
// Verify it exists first
|
|
67
|
+
(0, vitest_1.expect)(await store.get(sessionId)).not.toBeNull();
|
|
68
|
+
await store.destroy(sessionId);
|
|
69
|
+
(0, vitest_1.expect)(await store.get(sessionId)).toBeNull();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
(0, vitest_1.describe)('destroyAllForUser', () => {
|
|
73
|
+
(0, vitest_1.it)('should remove all sessions for a user', async () => {
|
|
74
|
+
const id1 = await store.create(TEST_SESSION);
|
|
75
|
+
const id2 = await store.create({ ...TEST_SESSION, productSlug: 'other' });
|
|
76
|
+
// Both should exist
|
|
77
|
+
(0, vitest_1.expect)(await store.get(id1)).not.toBeNull();
|
|
78
|
+
(0, vitest_1.expect)(await store.get(id2)).not.toBeNull();
|
|
79
|
+
await store.destroyAllForUser(TEST_SESSION.userId);
|
|
80
|
+
(0, vitest_1.expect)(await store.get(id1)).toBeNull();
|
|
81
|
+
(0, vitest_1.expect)(await store.get(id2)).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
(0, vitest_1.it)('should not affect other users sessions', async () => {
|
|
84
|
+
const id1 = await store.create(TEST_SESSION);
|
|
85
|
+
const otherSession = {
|
|
86
|
+
...TEST_SESSION,
|
|
87
|
+
userId: 'other-user',
|
|
88
|
+
};
|
|
89
|
+
const id2 = await store.create(otherSession);
|
|
90
|
+
await store.destroyAllForUser(TEST_SESSION.userId);
|
|
91
|
+
(0, vitest_1.expect)(await store.get(id1)).toBeNull();
|
|
92
|
+
(0, vitest_1.expect)(await store.get(id2)).not.toBeNull();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=session.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.test.js","sourceRoot":"","sources":["../../src/__tests__/session.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface CreateApiKeyInput {
|
|
2
|
+
userId: string;
|
|
3
|
+
productSlug: string;
|
|
4
|
+
scopes: string[];
|
|
5
|
+
expiresAt?: Date | null;
|
|
6
|
+
}
|
|
7
|
+
export interface ApiKeyWithHash {
|
|
8
|
+
plainKey: string;
|
|
9
|
+
hashedKey: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generates a new API key with the `ek_` prefix.
|
|
13
|
+
* Optionally accepts a custom prefix that replaces the default.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateApiKey(prefix?: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a SHA-256 hash of an API key for secure storage.
|
|
18
|
+
* Only the hash should be persisted — never store the plain key.
|
|
19
|
+
*/
|
|
20
|
+
export declare function hashApiKey(key: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Validates that a key matches the expected `ek_` format and length.
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateApiKeyFormat(key: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Generates a new API key and returns both the plain key and its hash.
|
|
27
|
+
*/
|
|
28
|
+
export declare function createApiKeyPair(prefix?: string): ApiKeyWithHash;
|
|
29
|
+
//# sourceMappingURL=api-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-keys.d.ts","sourceRoot":"","sources":["../src/api-keys.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAItD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,CAIhE"}
|
package/dist/api-keys.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateApiKey = generateApiKey;
|
|
7
|
+
exports.hashApiKey = hashApiKey;
|
|
8
|
+
exports.validateApiKeyFormat = validateApiKeyFormat;
|
|
9
|
+
exports.createApiKeyPair = createApiKeyPair;
|
|
10
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
+
const API_KEY_PREFIX = 'ek_';
|
|
12
|
+
const API_KEY_BYTES = 32;
|
|
13
|
+
const EXPECTED_KEY_LENGTH = API_KEY_PREFIX.length + API_KEY_BYTES * 2; // hex encoding
|
|
14
|
+
/**
|
|
15
|
+
* Generates a new API key with the `ek_` prefix.
|
|
16
|
+
* Optionally accepts a custom prefix that replaces the default.
|
|
17
|
+
*/
|
|
18
|
+
function generateApiKey(prefix) {
|
|
19
|
+
const keyPrefix = prefix || API_KEY_PREFIX;
|
|
20
|
+
const randomPart = crypto_1.default.randomBytes(API_KEY_BYTES).toString('hex');
|
|
21
|
+
return `${keyPrefix}${randomPart}`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Creates a SHA-256 hash of an API key for secure storage.
|
|
25
|
+
* Only the hash should be persisted — never store the plain key.
|
|
26
|
+
*/
|
|
27
|
+
function hashApiKey(key) {
|
|
28
|
+
return crypto_1.default.createHash('sha256').update(key).digest('hex');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validates that a key matches the expected `ek_` format and length.
|
|
32
|
+
*/
|
|
33
|
+
function validateApiKeyFormat(key) {
|
|
34
|
+
if (!key.startsWith(API_KEY_PREFIX))
|
|
35
|
+
return false;
|
|
36
|
+
if (key.length !== EXPECTED_KEY_LENGTH)
|
|
37
|
+
return false;
|
|
38
|
+
// Verify the hex portion is valid
|
|
39
|
+
const hexPart = key.slice(API_KEY_PREFIX.length);
|
|
40
|
+
return /^[a-f0-9]+$/.test(hexPart);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generates a new API key and returns both the plain key and its hash.
|
|
44
|
+
*/
|
|
45
|
+
function createApiKeyPair(prefix) {
|
|
46
|
+
const plainKey = generateApiKey(prefix);
|
|
47
|
+
const hashedKey = hashApiKey(plainKey);
|
|
48
|
+
return { plainKey, hashedKey };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=api-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-keys.js","sourceRoot":"","sources":["../src/api-keys.ts"],"names":[],"mappings":";;;;;AAsBA,wCAIC;AAMD,gCAEC;AAKD,oDAOC;AAKD,4CAIC;AAvDD,oDAA4B;AAE5B,MAAM,cAAc,GAAG,KAAK,CAAC;AAC7B,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,mBAAmB,GAAG,cAAc,CAAC,MAAM,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,eAAe;AActF;;;GAGG;AACH,SAAgB,cAAc,CAAC,MAAe;IAC5C,MAAM,SAAS,GAAG,MAAM,IAAI,cAAc,CAAC;IAC3C,MAAM,UAAU,GAAG,gBAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrE,OAAO,GAAG,SAAS,GAAG,UAAU,EAAE,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,SAAgB,UAAU,CAAC,GAAW;IACpC,OAAO,gBAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAAC,GAAW;IAC9C,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC;QAAE,OAAO,KAAK,CAAC;IAClD,IAAI,GAAG,CAAC,MAAM,KAAK,mBAAmB;QAAE,OAAO,KAAK,CAAC;IAErD,kCAAkC;IAClC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD,OAAO,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,MAAe;IAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACjC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { EngineUser, ApiKey, SessionData, JwtPayload, AuthConfig, } from './types';
|
|
2
|
+
export { signAccessToken, signRefreshToken, signRememberMeToken, verifyAccessToken, verifyRefreshToken, } from './jwt';
|
|
3
|
+
export { createSessionStore } from './session';
|
|
4
|
+
export type { SessionStore } from './session';
|
|
5
|
+
export { generateApiKey, hashApiKey, validateApiKeyFormat, createApiKeyPair, } from './api-keys';
|
|
6
|
+
export type { CreateApiKeyInput, ApiKeyWithHash } from './api-keys';
|
|
7
|
+
export { configureGoogleStrategy, configureGithubStrategy, setupOAuth, } from './oauth';
|
|
8
|
+
export type { OAuthProfile, FindOrCreateUser } from './oauth';
|
|
9
|
+
export { authenticateToken, requireApiKey, requireProduct, requireRole, } from './middleware';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,UAAU,EACV,MAAM,EACN,WAAW,EACX,UAAU,EACV,UAAU,GACX,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,OAAO,CAAC;AAGf,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,OAAO,EACL,cAAc,EACd,UAAU,EACV,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGpE,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG9D,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,WAAW,GACZ,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireRole = exports.requireProduct = exports.requireApiKey = exports.authenticateToken = exports.setupOAuth = exports.configureGithubStrategy = exports.configureGoogleStrategy = exports.createApiKeyPair = exports.validateApiKeyFormat = exports.hashApiKey = exports.generateApiKey = exports.createSessionStore = exports.verifyRefreshToken = exports.verifyAccessToken = exports.signRememberMeToken = exports.signRefreshToken = exports.signAccessToken = void 0;
|
|
4
|
+
// JWT utilities
|
|
5
|
+
var jwt_1 = require("./jwt");
|
|
6
|
+
Object.defineProperty(exports, "signAccessToken", { enumerable: true, get: function () { return jwt_1.signAccessToken; } });
|
|
7
|
+
Object.defineProperty(exports, "signRefreshToken", { enumerable: true, get: function () { return jwt_1.signRefreshToken; } });
|
|
8
|
+
Object.defineProperty(exports, "signRememberMeToken", { enumerable: true, get: function () { return jwt_1.signRememberMeToken; } });
|
|
9
|
+
Object.defineProperty(exports, "verifyAccessToken", { enumerable: true, get: function () { return jwt_1.verifyAccessToken; } });
|
|
10
|
+
Object.defineProperty(exports, "verifyRefreshToken", { enumerable: true, get: function () { return jwt_1.verifyRefreshToken; } });
|
|
11
|
+
// Session store
|
|
12
|
+
var session_1 = require("./session");
|
|
13
|
+
Object.defineProperty(exports, "createSessionStore", { enumerable: true, get: function () { return session_1.createSessionStore; } });
|
|
14
|
+
// API key utilities
|
|
15
|
+
var api_keys_1 = require("./api-keys");
|
|
16
|
+
Object.defineProperty(exports, "generateApiKey", { enumerable: true, get: function () { return api_keys_1.generateApiKey; } });
|
|
17
|
+
Object.defineProperty(exports, "hashApiKey", { enumerable: true, get: function () { return api_keys_1.hashApiKey; } });
|
|
18
|
+
Object.defineProperty(exports, "validateApiKeyFormat", { enumerable: true, get: function () { return api_keys_1.validateApiKeyFormat; } });
|
|
19
|
+
Object.defineProperty(exports, "createApiKeyPair", { enumerable: true, get: function () { return api_keys_1.createApiKeyPair; } });
|
|
20
|
+
// OAuth strategies
|
|
21
|
+
var oauth_1 = require("./oauth");
|
|
22
|
+
Object.defineProperty(exports, "configureGoogleStrategy", { enumerable: true, get: function () { return oauth_1.configureGoogleStrategy; } });
|
|
23
|
+
Object.defineProperty(exports, "configureGithubStrategy", { enumerable: true, get: function () { return oauth_1.configureGithubStrategy; } });
|
|
24
|
+
Object.defineProperty(exports, "setupOAuth", { enumerable: true, get: function () { return oauth_1.setupOAuth; } });
|
|
25
|
+
// Express middleware
|
|
26
|
+
var middleware_1 = require("./middleware");
|
|
27
|
+
Object.defineProperty(exports, "authenticateToken", { enumerable: true, get: function () { return middleware_1.authenticateToken; } });
|
|
28
|
+
Object.defineProperty(exports, "requireApiKey", { enumerable: true, get: function () { return middleware_1.requireApiKey; } });
|
|
29
|
+
Object.defineProperty(exports, "requireProduct", { enumerable: true, get: function () { return middleware_1.requireProduct; } });
|
|
30
|
+
Object.defineProperty(exports, "requireRole", { enumerable: true, get: function () { return middleware_1.requireRole; } });
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AASA,gBAAgB;AAChB,6BAMe;AALb,sGAAA,eAAe,OAAA;AACf,uGAAA,gBAAgB,OAAA;AAChB,0GAAA,mBAAmB,OAAA;AACnB,wGAAA,iBAAiB,OAAA;AACjB,yGAAA,kBAAkB,OAAA;AAGpB,gBAAgB;AAChB,qCAA+C;AAAtC,6GAAA,kBAAkB,OAAA;AAG3B,oBAAoB;AACpB,uCAKoB;AAJlB,0GAAA,cAAc,OAAA;AACd,sGAAA,UAAU,OAAA;AACV,gHAAA,oBAAoB,OAAA;AACpB,4GAAA,gBAAgB,OAAA;AAIlB,mBAAmB;AACnB,iCAIiB;AAHf,gHAAA,uBAAuB,OAAA;AACvB,gHAAA,uBAAuB,OAAA;AACvB,mGAAA,UAAU,OAAA;AAIZ,qBAAqB;AACrB,2CAKsB;AAJpB,+GAAA,iBAAiB,OAAA;AACjB,2GAAA,aAAa,OAAA;AACb,4GAAA,cAAc,OAAA;AACd,yGAAA,WAAW,OAAA"}
|
package/dist/jwt.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { JwtPayload, AuthConfig } from './types';
|
|
2
|
+
export declare function signAccessToken(payload: JwtPayload, config: AuthConfig): string;
|
|
3
|
+
export declare function signRefreshToken(payload: JwtPayload, config: AuthConfig): string;
|
|
4
|
+
export declare function signRememberMeToken(payload: JwtPayload, config: AuthConfig): string;
|
|
5
|
+
export declare function verifyAccessToken(token: string, config: AuthConfig): JwtPayload;
|
|
6
|
+
export declare function verifyRefreshToken(token: string, config: AuthConfig): JwtPayload;
|
|
7
|
+
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAuBjD,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAI/E;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAIhF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAInF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAQ/E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAQhF"}
|
package/dist/jwt.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.signAccessToken = signAccessToken;
|
|
7
|
+
exports.signRefreshToken = signRefreshToken;
|
|
8
|
+
exports.signRememberMeToken = signRememberMeToken;
|
|
9
|
+
exports.verifyAccessToken = verifyAccessToken;
|
|
10
|
+
exports.verifyRefreshToken = verifyRefreshToken;
|
|
11
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
12
|
+
// Expiry values in seconds to satisfy jsonwebtoken's type requirements
|
|
13
|
+
const DEFAULT_ACCESS_EXPIRY = 15 * 60; // 15 minutes
|
|
14
|
+
const DEFAULT_REFRESH_EXPIRY = 7 * 24 * 60 * 60; // 7 days
|
|
15
|
+
const REMEMBER_ME_EXPIRY = 30 * 24 * 60 * 60; // 30 days
|
|
16
|
+
function parseExpiry(value, fallback) {
|
|
17
|
+
if (!value)
|
|
18
|
+
return fallback;
|
|
19
|
+
// Parse simple duration strings: "15m", "7d", "30d", "1h"
|
|
20
|
+
const match = value.match(/^(\d+)(s|m|h|d)$/);
|
|
21
|
+
if (!match)
|
|
22
|
+
return fallback;
|
|
23
|
+
const num = parseInt(match[1], 10);
|
|
24
|
+
const unit = match[2];
|
|
25
|
+
switch (unit) {
|
|
26
|
+
case 's': return num;
|
|
27
|
+
case 'm': return num * 60;
|
|
28
|
+
case 'h': return num * 3600;
|
|
29
|
+
case 'd': return num * 86400;
|
|
30
|
+
default: return fallback;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function signAccessToken(payload, config) {
|
|
34
|
+
return jsonwebtoken_1.default.sign(payload, config.jwtSecret, {
|
|
35
|
+
expiresIn: parseExpiry(config.jwtExpiresIn, DEFAULT_ACCESS_EXPIRY),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function signRefreshToken(payload, config) {
|
|
39
|
+
return jsonwebtoken_1.default.sign(payload, config.jwtRefreshSecret, {
|
|
40
|
+
expiresIn: parseExpiry(config.jwtRefreshExpiresIn, DEFAULT_REFRESH_EXPIRY),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function signRememberMeToken(payload, config) {
|
|
44
|
+
return jsonwebtoken_1.default.sign(payload, config.jwtRefreshSecret, {
|
|
45
|
+
expiresIn: REMEMBER_ME_EXPIRY,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function verifyAccessToken(token, config) {
|
|
49
|
+
const decoded = jsonwebtoken_1.default.verify(token, config.jwtSecret);
|
|
50
|
+
return {
|
|
51
|
+
userId: decoded.userId,
|
|
52
|
+
email: decoded.email,
|
|
53
|
+
role: decoded.role,
|
|
54
|
+
subscriptionTier: decoded.subscriptionTier,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function verifyRefreshToken(token, config) {
|
|
58
|
+
const decoded = jsonwebtoken_1.default.verify(token, config.jwtRefreshSecret);
|
|
59
|
+
return {
|
|
60
|
+
userId: decoded.userId,
|
|
61
|
+
email: decoded.email,
|
|
62
|
+
role: decoded.role,
|
|
63
|
+
subscriptionTier: decoded.subscriptionTier,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=jwt.js.map
|
package/dist/jwt.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":";;;;;AAwBA,0CAIC;AAED,4CAIC;AAED,kDAIC;AAED,8CAQC;AAED,gDAQC;AA5DD,gEAA+B;AAG/B,uEAAuE;AACvE,MAAM,qBAAqB,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,aAAa;AACpD,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,SAAS;AAC1D,MAAM,kBAAkB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU;AAExD,SAAS,WAAW,CAAC,KAAyB,EAAE,QAAgB;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,0DAA0D;IAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC;QACrB,KAAK,GAAG,CAAC,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC;QAC1B,KAAK,GAAG,CAAC,CAAC,OAAO,GAAG,GAAG,IAAI,CAAC;QAC5B,KAAK,GAAG,CAAC,CAAC,OAAO,GAAG,GAAG,KAAK,CAAC;QAC7B,OAAO,CAAC,CAAC,OAAO,QAAQ,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAgB,eAAe,CAAC,OAAmB,EAAE,MAAkB;IACrE,OAAO,sBAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE;QACzC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,YAAY,EAAE,qBAAqB,CAAC;KACnE,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAmB,EAAE,MAAkB;IACtE,OAAO,sBAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,gBAAgB,EAAE;QAChD,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC;KAC3E,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,mBAAmB,CAAC,OAAmB,EAAE,MAAkB;IACzE,OAAO,sBAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,gBAAgB,EAAE;QAChD,SAAS,EAAE,kBAAkB;KAC9B,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,iBAAiB,CAAC,KAAa,EAAE,MAAkB;IACjE,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,CAAgC,CAAC;IACnF,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;KAC3C,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa,EAAE,MAAkB;IAClE,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAgC,CAAC;IAC1F,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;KAC3C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { AuthConfig, JwtPayload, ApiKey } from './types';
|
|
3
|
+
declare module 'express-serve-static-core' {
|
|
4
|
+
interface Request {
|
|
5
|
+
authUser?: JwtPayload;
|
|
6
|
+
apiKey?: ApiKey;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Middleware that validates a Bearer token from the Authorization header.
|
|
11
|
+
* On success, attaches the decoded JwtPayload to `req.user`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function authenticateToken(config: AuthConfig): (req: Request, res: Response, next: NextFunction) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Middleware that validates an API key from the X-API-Key header.
|
|
16
|
+
* The `validateKey` callback should look up the hashed key in your DB.
|
|
17
|
+
*/
|
|
18
|
+
export declare function requireApiKey(validateKey: (key: string) => Promise<ApiKey | null>): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Middleware that ensures the API key is scoped to a specific product.
|
|
21
|
+
* Must be used after `requireApiKey`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function requireProduct(productSlug: string): (req: Request, res: Response, next: NextFunction) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Middleware that restricts access to specific user roles.
|
|
26
|
+
* Must be used after `authenticateToken`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function requireRole(...roles: string[]): (req: Request, res: Response, next: NextFunction) => void;
|
|
29
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGzD,OAAO,QAAQ,2BAA2B,CAAC;IACzC,UAAU,OAAO;QACf,QAAQ,CAAC,EAAE,UAAU,CAAC;QACtB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;CACF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,IAC1C,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAkB/D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,IAEtC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CA4B9E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,IACxC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAa/D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,IACpC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAa/D"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authenticateToken = authenticateToken;
|
|
4
|
+
exports.requireApiKey = requireApiKey;
|
|
5
|
+
exports.requireProduct = requireProduct;
|
|
6
|
+
exports.requireRole = requireRole;
|
|
7
|
+
const jwt_1 = require("./jwt");
|
|
8
|
+
/**
|
|
9
|
+
* Middleware that validates a Bearer token from the Authorization header.
|
|
10
|
+
* On success, attaches the decoded JwtPayload to `req.user`.
|
|
11
|
+
*/
|
|
12
|
+
function authenticateToken(config) {
|
|
13
|
+
return (req, res, next) => {
|
|
14
|
+
const authHeader = req.headers.authorization;
|
|
15
|
+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
16
|
+
res.status(401).json({ error: 'Missing or invalid Authorization header' });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const token = authHeader.slice(7);
|
|
20
|
+
try {
|
|
21
|
+
const payload = (0, jwt_1.verifyAccessToken)(token, config);
|
|
22
|
+
req.authUser = payload;
|
|
23
|
+
next();
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
res.status(401).json({ error: 'Invalid or expired token' });
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Middleware that validates an API key from the X-API-Key header.
|
|
32
|
+
* The `validateKey` callback should look up the hashed key in your DB.
|
|
33
|
+
*/
|
|
34
|
+
function requireApiKey(validateKey) {
|
|
35
|
+
return async (req, res, next) => {
|
|
36
|
+
const apiKey = req.headers['x-api-key'];
|
|
37
|
+
if (!apiKey) {
|
|
38
|
+
res.status(401).json({ error: 'Missing X-API-Key header' });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const keyRecord = await validateKey(apiKey);
|
|
43
|
+
if (!keyRecord) {
|
|
44
|
+
res.status(401).json({ error: 'Invalid API key' });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Check expiration
|
|
48
|
+
if (keyRecord.expiresAt && new Date(keyRecord.expiresAt) < new Date()) {
|
|
49
|
+
res.status(401).json({ error: 'API key has expired' });
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
req.apiKey = keyRecord;
|
|
53
|
+
next();
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
res.status(500).json({ error: 'Failed to validate API key' });
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Middleware that ensures the API key is scoped to a specific product.
|
|
62
|
+
* Must be used after `requireApiKey`.
|
|
63
|
+
*/
|
|
64
|
+
function requireProduct(productSlug) {
|
|
65
|
+
return (req, res, next) => {
|
|
66
|
+
if (!req.apiKey) {
|
|
67
|
+
res.status(401).json({ error: 'No API key context' });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (req.apiKey.productSlug !== productSlug) {
|
|
71
|
+
res.status(403).json({ error: `API key not authorized for product: ${productSlug}` });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
next();
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Middleware that restricts access to specific user roles.
|
|
79
|
+
* Must be used after `authenticateToken`.
|
|
80
|
+
*/
|
|
81
|
+
function requireRole(...roles) {
|
|
82
|
+
return (req, res, next) => {
|
|
83
|
+
if (!req.authUser) {
|
|
84
|
+
res.status(401).json({ error: 'Not authenticated' });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!roles.includes(req.authUser.role)) {
|
|
88
|
+
res.status(403).json({ error: 'Insufficient permissions' });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
next();
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AuthConfig } from './types';
|
|
2
|
+
export interface OAuthProfile {
|
|
3
|
+
provider: 'google' | 'github';
|
|
4
|
+
providerId: string;
|
|
5
|
+
email: string;
|
|
6
|
+
name: string | null;
|
|
7
|
+
avatarUrl: string | null;
|
|
8
|
+
}
|
|
9
|
+
export type FindOrCreateUser = (profile: OAuthProfile) => Promise<{
|
|
10
|
+
id: string;
|
|
11
|
+
email: string;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function configureGoogleStrategy(config: AuthConfig, findOrCreateUser: FindOrCreateUser): void;
|
|
14
|
+
export declare function configureGithubStrategy(config: AuthConfig, findOrCreateUser: FindOrCreateUser): void;
|
|
15
|
+
export declare function setupOAuth(config: AuthConfig, findOrCreateUser: FindOrCreateUser): void;
|
|
16
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE5C,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,UAAU,EAClB,gBAAgB,EAAE,gBAAgB,GACjC,IAAI,CAkCN;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,UAAU,EAClB,gBAAgB,EAAE,gBAAgB,GACjC,IAAI,CAuCN;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,UAAU,EAClB,gBAAgB,EAAE,gBAAgB,GACjC,IAAI,CAON"}
|
package/dist/oauth.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.configureGoogleStrategy = configureGoogleStrategy;
|
|
7
|
+
exports.configureGithubStrategy = configureGithubStrategy;
|
|
8
|
+
exports.setupOAuth = setupOAuth;
|
|
9
|
+
const passport_1 = __importDefault(require("passport"));
|
|
10
|
+
const passport_google_oauth20_1 = require("passport-google-oauth20");
|
|
11
|
+
const passport_github2_1 = require("passport-github2");
|
|
12
|
+
function configureGoogleStrategy(config, findOrCreateUser) {
|
|
13
|
+
if (!config.google)
|
|
14
|
+
return;
|
|
15
|
+
passport_1.default.use(new passport_google_oauth20_1.Strategy({
|
|
16
|
+
clientID: config.google.clientId,
|
|
17
|
+
clientSecret: config.google.clientSecret,
|
|
18
|
+
callbackURL: config.google.callbackUrl,
|
|
19
|
+
scope: ['profile', 'email'],
|
|
20
|
+
}, async (_accessToken, _refreshToken, profile, done) => {
|
|
21
|
+
try {
|
|
22
|
+
const email = profile.emails?.[0]?.value;
|
|
23
|
+
if (!email) {
|
|
24
|
+
return done(new Error('No email found in Google profile'));
|
|
25
|
+
}
|
|
26
|
+
const oauthProfile = {
|
|
27
|
+
provider: 'google',
|
|
28
|
+
providerId: profile.id,
|
|
29
|
+
email,
|
|
30
|
+
name: profile.displayName || null,
|
|
31
|
+
avatarUrl: profile.photos?.[0]?.value || null,
|
|
32
|
+
};
|
|
33
|
+
const user = await findOrCreateUser(oauthProfile);
|
|
34
|
+
return done(null, user);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
return done(err);
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
function configureGithubStrategy(config, findOrCreateUser) {
|
|
42
|
+
if (!config.github)
|
|
43
|
+
return;
|
|
44
|
+
passport_1.default.use(new passport_github2_1.Strategy({
|
|
45
|
+
clientID: config.github.clientId,
|
|
46
|
+
clientSecret: config.github.clientSecret,
|
|
47
|
+
callbackURL: config.github.callbackUrl,
|
|
48
|
+
scope: ['user:email'],
|
|
49
|
+
}, async (_accessToken, _refreshToken, profile, done) => {
|
|
50
|
+
try {
|
|
51
|
+
const email = profile.emails?.[0]?.value;
|
|
52
|
+
if (!email) {
|
|
53
|
+
return done(new Error('No email found in GitHub profile'));
|
|
54
|
+
}
|
|
55
|
+
const oauthProfile = {
|
|
56
|
+
provider: 'github',
|
|
57
|
+
providerId: profile.id,
|
|
58
|
+
email,
|
|
59
|
+
name: profile.displayName || null,
|
|
60
|
+
avatarUrl: profile.photos?.[0]?.value || null,
|
|
61
|
+
};
|
|
62
|
+
const user = await findOrCreateUser(oauthProfile);
|
|
63
|
+
return done(null, user);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
return done(err);
|
|
67
|
+
}
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
function setupOAuth(config, findOrCreateUser) {
|
|
71
|
+
if (config.google) {
|
|
72
|
+
configureGoogleStrategy(config, findOrCreateUser);
|
|
73
|
+
}
|
|
74
|
+
if (config.github) {
|
|
75
|
+
configureGithubStrategy(config, findOrCreateUser);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SessionData } from './types';
|
|
2
|
+
export interface SessionStore {
|
|
3
|
+
create(sessionData: SessionData): Promise<string>;
|
|
4
|
+
get(sessionId: string): Promise<SessionData | null>;
|
|
5
|
+
destroy(sessionId: string): Promise<void>;
|
|
6
|
+
destroyAllForUser(userId: string): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare function createSessionStore(redisUrl: string): SessionStore;
|
|
9
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAMtC,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CA8DjE"}
|