@rudderjs/passport 0.0.1
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/LICENSE +21 -0
- package/dist/Passport.d.ts +41 -0
- package/dist/Passport.d.ts.map +1 -0
- package/dist/Passport.js +77 -0
- package/dist/Passport.js.map +1 -0
- package/dist/commands/client.d.ts +16 -0
- package/dist/commands/client.d.ts.map +1 -0
- package/dist/commands/client.js +25 -0
- package/dist/commands/client.js.map +1 -0
- package/dist/commands/keys.d.ts +11 -0
- package/dist/commands/keys.d.ts.map +1 -0
- package/dist/commands/keys.js +27 -0
- package/dist/commands/keys.js.map +1 -0
- package/dist/commands/purge.d.ts +11 -0
- package/dist/commands/purge.d.ts.map +1 -0
- package/dist/commands/purge.js +48 -0
- package/dist/commands/purge.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +112 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/bearer.d.ts +12 -0
- package/dist/middleware/bearer.d.ts.map +1 -0
- package/dist/middleware/bearer.js +111 -0
- package/dist/middleware/bearer.js.map +1 -0
- package/dist/middleware/scope.d.ts +11 -0
- package/dist/middleware/scope.d.ts.map +1 -0
- package/dist/middleware/scope.js +39 -0
- package/dist/middleware/scope.js.map +1 -0
- package/dist/models/AccessToken.d.ts +23 -0
- package/dist/models/AccessToken.d.ts.map +1 -0
- package/dist/models/AccessToken.js +35 -0
- package/dist/models/AccessToken.js.map +1 -0
- package/dist/models/AuthCode.d.ts +18 -0
- package/dist/models/AuthCode.d.ts.map +1 -0
- package/dist/models/AuthCode.js +21 -0
- package/dist/models/AuthCode.js.map +1 -0
- package/dist/models/DeviceCode.d.ts +23 -0
- package/dist/models/DeviceCode.d.ts.map +1 -0
- package/dist/models/DeviceCode.js +29 -0
- package/dist/models/DeviceCode.js.map +1 -0
- package/dist/models/OAuthClient.d.ts +22 -0
- package/dist/models/OAuthClient.d.ts.map +1 -0
- package/dist/models/OAuthClient.js +52 -0
- package/dist/models/OAuthClient.js.map +1 -0
- package/dist/models/RefreshToken.d.ts +13 -0
- package/dist/models/RefreshToken.d.ts.map +1 -0
- package/dist/models/RefreshToken.js +15 -0
- package/dist/models/RefreshToken.js.map +1 -0
- package/dist/token.d.ts +40 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +80 -0
- package/dist/token.js.map +1 -0
- package/package.json +51 -0
- package/schema/passport.prisma +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Suleiman Shahbari
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface PassportScope {
|
|
2
|
+
id: string;
|
|
3
|
+
description: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class Passport {
|
|
6
|
+
private static _scopes;
|
|
7
|
+
private static _tokenLifetime;
|
|
8
|
+
private static _refreshTokenLifetime;
|
|
9
|
+
private static _personalTokenLifetime;
|
|
10
|
+
private static _keyPath;
|
|
11
|
+
private static _privateKey;
|
|
12
|
+
private static _publicKey;
|
|
13
|
+
/** Define available OAuth scopes. */
|
|
14
|
+
static tokensCan(scopes: Record<string, string>): void;
|
|
15
|
+
/** Check if a scope is defined. */
|
|
16
|
+
static hasScope(id: string): boolean;
|
|
17
|
+
/** Get all defined scopes. */
|
|
18
|
+
static scopes(): PassportScope[];
|
|
19
|
+
/** Validate a list of scopes — returns only the valid ones. */
|
|
20
|
+
static validScopes(requested: string[]): string[];
|
|
21
|
+
static tokensExpireIn(ms: number): void;
|
|
22
|
+
static refreshTokensExpireIn(ms: number): void;
|
|
23
|
+
static personalAccessTokensExpireIn(ms: number): void;
|
|
24
|
+
static tokenLifetime(): number;
|
|
25
|
+
static refreshTokenLifetime(): number;
|
|
26
|
+
static personalTokenLifetime(): number;
|
|
27
|
+
/** Set the directory where RSA keys are stored. */
|
|
28
|
+
static loadKeysFrom(path: string): void;
|
|
29
|
+
/** Get the configured key path. */
|
|
30
|
+
static keyPath(): string;
|
|
31
|
+
/** Set keys directly (from environment variables). */
|
|
32
|
+
static setKeys(privateKey: string, publicKey: string): void;
|
|
33
|
+
/** Load keys from files or env. Returns { privateKey, publicKey }. */
|
|
34
|
+
static keys(): Promise<{
|
|
35
|
+
privateKey: string;
|
|
36
|
+
publicKey: string;
|
|
37
|
+
}>;
|
|
38
|
+
/** @internal */
|
|
39
|
+
static reset(): void;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=Passport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Passport.d.ts","sourceRoot":"","sources":["../src/Passport.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAW,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAC,OAAO,CAA4B;IAClD,OAAO,CAAC,MAAM,CAAC,cAAc,CAAiC;IAC9D,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAA2B;IAC/D,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAA+B;IACpE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAY;IACnC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAsB;IAChD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAsB;IAI/C,qCAAqC;IACrC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAMtD,mCAAmC;IACnC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIpC,8BAA8B;IAC9B,MAAM,CAAC,MAAM,IAAI,aAAa,EAAE;IAIhC,+DAA+D;IAC/D,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IAMjD,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IACvC,MAAM,CAAC,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAC9C,MAAM,CAAC,4BAA4B,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAErD,MAAM,CAAC,aAAa,IAAI,MAAM;IAC9B,MAAM,CAAC,oBAAoB,IAAI,MAAM;IACrC,MAAM,CAAC,qBAAqB,IAAI,MAAM;IAItC,mDAAmD;IACnD,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAEvC,mCAAmC;IACnC,MAAM,CAAC,OAAO,IAAI,MAAM;IAExB,sDAAsD;IACtD,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAK3D,sEAAsE;WACzD,IAAI,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IA0BvE,gBAAgB;IAChB,MAAM,CAAC,KAAK,IAAI,IAAI;CASrB"}
|
package/dist/Passport.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// ─── Passport Configuration Singleton ─────────────────────
|
|
2
|
+
export class Passport {
|
|
3
|
+
static _scopes = new Map();
|
|
4
|
+
static _tokenLifetime = 15 * 24 * 60 * 60 * 1000; // 15 days
|
|
5
|
+
static _refreshTokenLifetime = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
6
|
+
static _personalTokenLifetime = 6 * 30 * 24 * 60 * 60 * 1000; // ~6 months
|
|
7
|
+
static _keyPath = 'storage';
|
|
8
|
+
static _privateKey = null;
|
|
9
|
+
static _publicKey = null;
|
|
10
|
+
// ── Scopes ──────────────────────────────────────────────
|
|
11
|
+
/** Define available OAuth scopes. */
|
|
12
|
+
static tokensCan(scopes) {
|
|
13
|
+
for (const [id, description] of Object.entries(scopes)) {
|
|
14
|
+
this._scopes.set(id, description);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Check if a scope is defined. */
|
|
18
|
+
static hasScope(id) {
|
|
19
|
+
return this._scopes.has(id);
|
|
20
|
+
}
|
|
21
|
+
/** Get all defined scopes. */
|
|
22
|
+
static scopes() {
|
|
23
|
+
return [...this._scopes.entries()].map(([id, description]) => ({ id, description }));
|
|
24
|
+
}
|
|
25
|
+
/** Validate a list of scopes — returns only the valid ones. */
|
|
26
|
+
static validScopes(requested) {
|
|
27
|
+
return requested.filter(s => this._scopes.has(s) || s === '*');
|
|
28
|
+
}
|
|
29
|
+
// ── Lifetimes ───────────────────────────────────────────
|
|
30
|
+
static tokensExpireIn(ms) { this._tokenLifetime = ms; }
|
|
31
|
+
static refreshTokensExpireIn(ms) { this._refreshTokenLifetime = ms; }
|
|
32
|
+
static personalAccessTokensExpireIn(ms) { this._personalTokenLifetime = ms; }
|
|
33
|
+
static tokenLifetime() { return this._tokenLifetime; }
|
|
34
|
+
static refreshTokenLifetime() { return this._refreshTokenLifetime; }
|
|
35
|
+
static personalTokenLifetime() { return this._personalTokenLifetime; }
|
|
36
|
+
// ── Keys ────────────────────────────────────────────────
|
|
37
|
+
/** Set the directory where RSA keys are stored. */
|
|
38
|
+
static loadKeysFrom(path) { this._keyPath = path; }
|
|
39
|
+
/** Get the configured key path. */
|
|
40
|
+
static keyPath() { return this._keyPath; }
|
|
41
|
+
/** Set keys directly (from environment variables). */
|
|
42
|
+
static setKeys(privateKey, publicKey) {
|
|
43
|
+
this._privateKey = privateKey;
|
|
44
|
+
this._publicKey = publicKey;
|
|
45
|
+
}
|
|
46
|
+
/** Load keys from files or env. Returns { privateKey, publicKey }. */
|
|
47
|
+
static async keys() {
|
|
48
|
+
// Prefer explicitly set keys (from env vars)
|
|
49
|
+
if (this._privateKey && this._publicKey) {
|
|
50
|
+
return { privateKey: this._privateKey, publicKey: this._publicKey };
|
|
51
|
+
}
|
|
52
|
+
// Load from filesystem
|
|
53
|
+
const { readFile } = await import('node:fs/promises');
|
|
54
|
+
const { join } = await import('node:path');
|
|
55
|
+
const privatePath = join(process.cwd(), this._keyPath, 'oauth-private.key');
|
|
56
|
+
const publicPath = join(process.cwd(), this._keyPath, 'oauth-public.key');
|
|
57
|
+
const [privateKey, publicKey] = await Promise.all([
|
|
58
|
+
readFile(privatePath, 'utf8'),
|
|
59
|
+
readFile(publicPath, 'utf8'),
|
|
60
|
+
]);
|
|
61
|
+
this._privateKey = privateKey;
|
|
62
|
+
this._publicKey = publicKey;
|
|
63
|
+
return { privateKey, publicKey };
|
|
64
|
+
}
|
|
65
|
+
// ── Reset (testing) ─────────────────────────────────────
|
|
66
|
+
/** @internal */
|
|
67
|
+
static reset() {
|
|
68
|
+
this._scopes.clear();
|
|
69
|
+
this._tokenLifetime = 15 * 24 * 60 * 60 * 1000;
|
|
70
|
+
this._refreshTokenLifetime = 30 * 24 * 60 * 60 * 1000;
|
|
71
|
+
this._personalTokenLifetime = 6 * 30 * 24 * 60 * 60 * 1000;
|
|
72
|
+
this._keyPath = 'storage';
|
|
73
|
+
this._privateKey = null;
|
|
74
|
+
this._publicKey = null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=Passport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Passport.js","sourceRoot":"","sources":["../src/Passport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { OAuthClient } from '../models/OAuthClient.js';
|
|
2
|
+
export interface CreateClientOpts {
|
|
3
|
+
name: string;
|
|
4
|
+
redirectUri?: string;
|
|
5
|
+
grantTypes?: string[];
|
|
6
|
+
confidential?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Create an OAuth client programmatically.
|
|
10
|
+
* Returns the client and the plain-text secret (if confidential).
|
|
11
|
+
*/
|
|
12
|
+
export declare function createClient(opts: CreateClientOpts): Promise<{
|
|
13
|
+
client: OAuthClient;
|
|
14
|
+
secret: string | null;
|
|
15
|
+
}>;
|
|
16
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/commands/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAEtD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAU,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAG,MAAM,EAAE,CAAA;IACtB,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC;IAClE,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB,CAAC,CAsBD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { OAuthClient } from '../models/OAuthClient.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create an OAuth client programmatically.
|
|
4
|
+
* Returns the client and the plain-text secret (if confidential).
|
|
5
|
+
*/
|
|
6
|
+
export async function createClient(opts) {
|
|
7
|
+
const { randomBytes, createHash } = await import('node:crypto');
|
|
8
|
+
const confidential = opts.confidential ?? true;
|
|
9
|
+
let plainSecret = null;
|
|
10
|
+
let hashedSecret = null;
|
|
11
|
+
if (confidential) {
|
|
12
|
+
plainSecret = randomBytes(32).toString('hex');
|
|
13
|
+
hashedSecret = createHash('sha256').update(plainSecret).digest('hex');
|
|
14
|
+
}
|
|
15
|
+
const client = await OAuthClient.create({
|
|
16
|
+
name: opts.name,
|
|
17
|
+
secret: hashedSecret,
|
|
18
|
+
redirectUris: JSON.stringify(opts.redirectUri ? [opts.redirectUri] : []),
|
|
19
|
+
grantTypes: JSON.stringify(opts.grantTypes ?? ['authorization_code']),
|
|
20
|
+
scopes: JSON.stringify([]),
|
|
21
|
+
confidential,
|
|
22
|
+
});
|
|
23
|
+
return { client, secret: plainSecret };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/commands/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAStD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAsB;IAIvD,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IAE/D,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAA;IAC9C,IAAI,WAAW,GAAkB,IAAI,CAAA;IACrC,IAAI,YAAY,GAAkB,IAAI,CAAA;IAEtC,IAAI,YAAY,EAAE,CAAC;QACjB,WAAW,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC7C,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACvE,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC;QACtC,IAAI,EAAU,IAAI,CAAC,IAAI;QACvB,MAAM,EAAQ,YAAY;QAC1B,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,UAAU,EAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACvE,MAAM,EAAQ,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,YAAY;KACc,CAAgB,CAAA;IAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;AACxC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate RSA keypair for JWT signing.
|
|
3
|
+
* Writes to storage/oauth-private.key and storage/oauth-public.key.
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateKeys(opts?: {
|
|
6
|
+
force?: boolean;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
privatePath: string;
|
|
9
|
+
publicPath: string;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/commands/keys.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAsB,YAAY,CAAC,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAyBvH"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Passport } from '../Passport.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate RSA keypair for JWT signing.
|
|
4
|
+
* Writes to storage/oauth-private.key and storage/oauth-public.key.
|
|
5
|
+
*/
|
|
6
|
+
export async function generateKeys(opts = {}) {
|
|
7
|
+
const { generateKeyPairSync } = await import('node:crypto');
|
|
8
|
+
const { writeFile, mkdir } = await import('node:fs/promises');
|
|
9
|
+
const { existsSync } = await import('node:fs');
|
|
10
|
+
const { join } = await import('node:path');
|
|
11
|
+
const keyDir = join(process.cwd(), Passport.keyPath());
|
|
12
|
+
const privatePath = join(keyDir, 'oauth-private.key');
|
|
13
|
+
const publicPath = join(keyDir, 'oauth-public.key');
|
|
14
|
+
if (!opts.force && existsSync(privatePath)) {
|
|
15
|
+
throw new Error(`Keys already exist at ${privatePath}. Use --force to overwrite.`);
|
|
16
|
+
}
|
|
17
|
+
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
|
|
18
|
+
modulusLength: 4096,
|
|
19
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
20
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
|
|
21
|
+
});
|
|
22
|
+
await mkdir(keyDir, { recursive: true });
|
|
23
|
+
await writeFile(privatePath, privateKey, { mode: 0o600 });
|
|
24
|
+
await writeFile(publicPath, publicKey, { mode: 0o644 });
|
|
25
|
+
return { privatePath, publicPath };
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/commands/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B,EAAE;IAC/D,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IAC3D,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAA;IAC7D,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAA;IAC9C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;IAE1C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;IACtD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IACrD,MAAM,UAAU,GAAI,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;IAEpD,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,yBAAyB,WAAW,6BAA6B,CAAC,CAAA;IACpF,CAAC;IAED,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,mBAAmB,CAAC,KAAK,EAAE;QAC3D,aAAa,EAAE,IAAI;QACnB,iBAAiB,EAAG,EAAE,IAAI,EAAE,MAAM,EAAG,MAAM,EAAE,KAAK,EAAE;QACpD,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;KACrD,CAAC,CAAA;IAEF,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,MAAM,SAAS,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACzD,MAAM,SAAS,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAEvD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAA;AACpC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove expired and revoked tokens from the database.
|
|
3
|
+
* Returns counts of purged records.
|
|
4
|
+
*/
|
|
5
|
+
export declare function purgeTokens(): Promise<{
|
|
6
|
+
accessTokens: number;
|
|
7
|
+
refreshTokens: number;
|
|
8
|
+
authCodes: number;
|
|
9
|
+
deviceCodes: number;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=purge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"purge.d.ts","sourceRoot":"","sources":["../../src/commands/purge.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC;IAC3C,YAAY,EAAG,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAM,MAAM,CAAA;IACrB,WAAW,EAAI,MAAM,CAAA;CACtB,CAAC,CA2CD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { AccessToken } from '../models/AccessToken.js';
|
|
2
|
+
import { RefreshToken } from '../models/RefreshToken.js';
|
|
3
|
+
import { AuthCode } from '../models/AuthCode.js';
|
|
4
|
+
import { DeviceCode } from '../models/DeviceCode.js';
|
|
5
|
+
/**
|
|
6
|
+
* Remove expired and revoked tokens from the database.
|
|
7
|
+
* Returns counts of purged records.
|
|
8
|
+
*/
|
|
9
|
+
export async function purgeTokens() {
|
|
10
|
+
const now = new Date();
|
|
11
|
+
// Purge expired/revoked access tokens
|
|
12
|
+
const expiredAccess = await AccessToken.query()
|
|
13
|
+
.where('expiresAt', '<', now)
|
|
14
|
+
.orWhere('revoked', true)
|
|
15
|
+
.get();
|
|
16
|
+
for (const t of expiredAccess) {
|
|
17
|
+
await AccessToken.delete(t.id);
|
|
18
|
+
}
|
|
19
|
+
// Purge expired/revoked refresh tokens
|
|
20
|
+
const expiredRefresh = await RefreshToken.query()
|
|
21
|
+
.where('expiresAt', '<', now)
|
|
22
|
+
.orWhere('revoked', true)
|
|
23
|
+
.get();
|
|
24
|
+
for (const t of expiredRefresh) {
|
|
25
|
+
await RefreshToken.delete(t.id);
|
|
26
|
+
}
|
|
27
|
+
// Purge expired auth codes
|
|
28
|
+
const expiredCodes = await AuthCode.query()
|
|
29
|
+
.where('expiresAt', '<', now)
|
|
30
|
+
.get();
|
|
31
|
+
for (const c of expiredCodes) {
|
|
32
|
+
await AuthCode.delete(c.id);
|
|
33
|
+
}
|
|
34
|
+
// Purge expired device codes
|
|
35
|
+
const expiredDevices = await DeviceCode.query()
|
|
36
|
+
.where('expiresAt', '<', now)
|
|
37
|
+
.get();
|
|
38
|
+
for (const d of expiredDevices) {
|
|
39
|
+
await DeviceCode.delete(d.id);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
accessTokens: expiredAccess.length,
|
|
43
|
+
refreshTokens: expiredRefresh.length,
|
|
44
|
+
authCodes: expiredCodes.length,
|
|
45
|
+
deviceCodes: expiredDevices.length,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=purge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"purge.js","sourceRoot":"","sources":["../../src/commands/purge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEpD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAM/B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IAEtB,sCAAsC;IACtC,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE;SAC5C,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC;SACxB,GAAG,EAAmB,CAAA;IACzB,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,MAAM,WAAW,CAAC,MAAM,CAAE,CAAS,CAAC,EAAY,CAAC,CAAA;IACnD,CAAC;IAED,uCAAuC;IACvC,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE;SAC9C,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC;SACxB,GAAG,EAAoB,CAAA;IAC1B,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;QAC/B,MAAM,YAAY,CAAC,MAAM,CAAE,CAAS,CAAC,EAAY,CAAC,CAAA;IACpD,CAAC;IAED,2BAA2B;IAC3B,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE;SACxC,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC;SAC5B,GAAG,EAAgB,CAAA;IACtB,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QAC7B,MAAM,QAAQ,CAAC,MAAM,CAAE,CAAS,CAAC,EAAY,CAAC,CAAA;IAChD,CAAC;IAED,6BAA6B;IAC7B,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE;SAC5C,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC;SAC5B,GAAG,EAAkB,CAAA;IACxB,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;QAC/B,MAAM,UAAU,CAAC,MAAM,CAAE,CAAS,CAAC,EAAY,CAAC,CAAA;IAClD,CAAC;IAED,OAAO;QACL,YAAY,EAAG,aAAa,CAAC,MAAM;QACnC,aAAa,EAAE,cAAc,CAAC,MAAM;QACpC,SAAS,EAAM,YAAY,CAAC,MAAM;QAClC,WAAW,EAAI,cAAc,CAAC,MAAM;KACrC,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ServiceProvider } from '@rudderjs/core';
|
|
2
|
+
export { Passport } from './Passport.js';
|
|
3
|
+
export type { PassportScope } from './Passport.js';
|
|
4
|
+
export { createToken, verifyToken, decodeToken } from './token.js';
|
|
5
|
+
export type { JwtHeader, JwtPayload } from './token.js';
|
|
6
|
+
export { OAuthClient } from './models/OAuthClient.js';
|
|
7
|
+
export { AccessToken } from './models/AccessToken.js';
|
|
8
|
+
export { RefreshToken } from './models/RefreshToken.js';
|
|
9
|
+
export { AuthCode } from './models/AuthCode.js';
|
|
10
|
+
export { DeviceCode } from './models/DeviceCode.js';
|
|
11
|
+
export { BearerMiddleware, RequireBearer } from './middleware/bearer.js';
|
|
12
|
+
export { scope } from './middleware/scope.js';
|
|
13
|
+
export { generateKeys } from './commands/keys.js';
|
|
14
|
+
export { createClient } from './commands/client.js';
|
|
15
|
+
export type { CreateClientOpts } from './commands/client.js';
|
|
16
|
+
export { purgeTokens } from './commands/purge.js';
|
|
17
|
+
export interface PassportConfig {
|
|
18
|
+
/** Directory where RSA keys are stored (default: 'storage') */
|
|
19
|
+
keyPath?: string;
|
|
20
|
+
/** Or set keys directly from env vars */
|
|
21
|
+
privateKey?: string;
|
|
22
|
+
publicKey?: string;
|
|
23
|
+
/** Access token lifetime in ms (default: 15 days) */
|
|
24
|
+
tokensExpireIn?: number;
|
|
25
|
+
/** Refresh token lifetime in ms (default: 30 days) */
|
|
26
|
+
refreshTokensExpireIn?: number;
|
|
27
|
+
/** Personal access token lifetime in ms (default: ~6 months) */
|
|
28
|
+
personalAccessTokensExpireIn?: number;
|
|
29
|
+
/** OAuth scopes: { scopeId: 'description' } */
|
|
30
|
+
scopes?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
export declare class PassportProvider extends ServiceProvider {
|
|
33
|
+
register(): void;
|
|
34
|
+
boot(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAU,MAAM,gBAAgB,CAAA;AAIxD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAClE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAEnD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAIjD,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,sDAAsD;IACtD,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,gEAAgE;IAChE,4BAA4B,CAAC,EAAE,MAAM,CAAA;IACrC,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAID,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,QAAQ,IAAI,IAAI;IAEV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAmG5B"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { ServiceProvider, config } from '@rudderjs/core';
|
|
2
|
+
// ─── Re-exports ───────────────────────────────────────────
|
|
3
|
+
export { Passport } from './Passport.js';
|
|
4
|
+
export { createToken, verifyToken, decodeToken } from './token.js';
|
|
5
|
+
export { OAuthClient } from './models/OAuthClient.js';
|
|
6
|
+
export { AccessToken } from './models/AccessToken.js';
|
|
7
|
+
export { RefreshToken } from './models/RefreshToken.js';
|
|
8
|
+
export { AuthCode } from './models/AuthCode.js';
|
|
9
|
+
export { DeviceCode } from './models/DeviceCode.js';
|
|
10
|
+
export { BearerMiddleware, RequireBearer } from './middleware/bearer.js';
|
|
11
|
+
export { scope } from './middleware/scope.js';
|
|
12
|
+
export { generateKeys } from './commands/keys.js';
|
|
13
|
+
export { createClient } from './commands/client.js';
|
|
14
|
+
export { purgeTokens } from './commands/purge.js';
|
|
15
|
+
// ─── Service Provider ─────────────────────────────────────
|
|
16
|
+
export class PassportProvider extends ServiceProvider {
|
|
17
|
+
register() { }
|
|
18
|
+
async boot() {
|
|
19
|
+
const { Passport } = await import('./Passport.js');
|
|
20
|
+
const cfg = config('passport');
|
|
21
|
+
// Configure keys
|
|
22
|
+
if (cfg.privateKey && cfg.publicKey) {
|
|
23
|
+
Passport.setKeys(cfg.privateKey, cfg.publicKey);
|
|
24
|
+
}
|
|
25
|
+
else if (cfg.keyPath) {
|
|
26
|
+
Passport.loadKeysFrom(cfg.keyPath);
|
|
27
|
+
}
|
|
28
|
+
// Configure lifetimes
|
|
29
|
+
if (cfg.tokensExpireIn)
|
|
30
|
+
Passport.tokensExpireIn(cfg.tokensExpireIn);
|
|
31
|
+
if (cfg.refreshTokensExpireIn)
|
|
32
|
+
Passport.refreshTokensExpireIn(cfg.refreshTokensExpireIn);
|
|
33
|
+
if (cfg.personalAccessTokensExpireIn)
|
|
34
|
+
Passport.personalAccessTokensExpireIn(cfg.personalAccessTokensExpireIn);
|
|
35
|
+
// Configure scopes
|
|
36
|
+
if (cfg.scopes)
|
|
37
|
+
Passport.tokensCan(cfg.scopes);
|
|
38
|
+
this.app.instance('passport', Passport);
|
|
39
|
+
// Register CLI commands
|
|
40
|
+
try {
|
|
41
|
+
const { rudder } = await import('@rudderjs/core');
|
|
42
|
+
rudder.command('passport:keys', async (args) => {
|
|
43
|
+
const force = args.includes('--force');
|
|
44
|
+
const { generateKeys } = await import('./commands/keys.js');
|
|
45
|
+
const { privatePath, publicPath } = await generateKeys({ force });
|
|
46
|
+
console.log(` RSA keys generated:`);
|
|
47
|
+
console.log(` Private: ${privatePath}`);
|
|
48
|
+
console.log(` Public: ${publicPath}`);
|
|
49
|
+
}).description('Generate RSA encryption keys for OAuth tokens');
|
|
50
|
+
rudder.command('passport:client', async (args) => {
|
|
51
|
+
const name = args[0] ?? 'My App';
|
|
52
|
+
const isPublic = args.includes('--public');
|
|
53
|
+
const isDevice = args.includes('--device');
|
|
54
|
+
const isPersonal = args.includes('--personal');
|
|
55
|
+
const grantTypes = isDevice
|
|
56
|
+
? ['urn:ietf:params:oauth:grant-type:device_code']
|
|
57
|
+
: isPersonal
|
|
58
|
+
? ['personal_access']
|
|
59
|
+
: ['authorization_code'];
|
|
60
|
+
const { createClient } = await import('./commands/client.js');
|
|
61
|
+
const { client, secret } = await createClient({
|
|
62
|
+
name,
|
|
63
|
+
confidential: !isPublic && !isDevice,
|
|
64
|
+
grantTypes,
|
|
65
|
+
});
|
|
66
|
+
console.log(` OAuth client created:`);
|
|
67
|
+
console.log(` Client ID: ${client.id}`);
|
|
68
|
+
console.log(` Name: ${client.name}`);
|
|
69
|
+
if (secret) {
|
|
70
|
+
console.log(` Secret: ${secret}`);
|
|
71
|
+
console.log(` (Store this secret — it won't be shown again.)`);
|
|
72
|
+
}
|
|
73
|
+
}).description('Create a new OAuth client');
|
|
74
|
+
rudder.command('passport:purge', async () => {
|
|
75
|
+
const { purgeTokens } = await import('./commands/purge.js');
|
|
76
|
+
const counts = await purgeTokens();
|
|
77
|
+
const total = counts.accessTokens + counts.refreshTokens + counts.authCodes + counts.deviceCodes;
|
|
78
|
+
console.log(` Purged ${total} expired/revoked record(s):`);
|
|
79
|
+
console.log(` Access tokens: ${counts.accessTokens}`);
|
|
80
|
+
console.log(` Refresh tokens: ${counts.refreshTokens}`);
|
|
81
|
+
console.log(` Auth codes: ${counts.authCodes}`);
|
|
82
|
+
console.log(` Device codes: ${counts.deviceCodes}`);
|
|
83
|
+
}).description('Remove expired tokens and auth codes');
|
|
84
|
+
// Register make:* scaffolder for passport
|
|
85
|
+
try {
|
|
86
|
+
const { registerMakeSpecs } = await import('@rudderjs/rudder');
|
|
87
|
+
registerMakeSpecs({
|
|
88
|
+
command: 'make:passport-client',
|
|
89
|
+
description: 'Create a new OAuth client seeder',
|
|
90
|
+
label: 'Passport client seeder created',
|
|
91
|
+
directory: 'app/Seeders',
|
|
92
|
+
stub: (className) => `import { createClient } from '@rudderjs/passport'
|
|
93
|
+
|
|
94
|
+
export async function ${className.replace(/Seeder$/, '').toLowerCase()}Clients(): Promise<void> {
|
|
95
|
+
// Create a confidential client (server-side apps)
|
|
96
|
+
const { client, secret } = await createClient({
|
|
97
|
+
name: 'My Application',
|
|
98
|
+
redirectUri: 'http://localhost:3000/callback',
|
|
99
|
+
grantTypes: ['authorization_code', 'refresh_token'],
|
|
100
|
+
})
|
|
101
|
+
console.log('Client ID:', (client as any).id)
|
|
102
|
+
console.log('Secret:', secret)
|
|
103
|
+
}
|
|
104
|
+
`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch { /* rudder not available */ }
|
|
108
|
+
}
|
|
109
|
+
catch { /* rudder not available */ }
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from '@rudderjs/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Middleware that authenticates via Bearer token (JWT).
|
|
4
|
+
* Validates the JWT signature, checks expiration, checks revocation in DB.
|
|
5
|
+
* Attaches user to the request if valid. Does not block unauthenticated requests.
|
|
6
|
+
*/
|
|
7
|
+
export declare function BearerMiddleware(): MiddlewareHandler;
|
|
8
|
+
/**
|
|
9
|
+
* Middleware that requires a valid Bearer token. Returns 401 if missing/invalid.
|
|
10
|
+
*/
|
|
11
|
+
export declare function RequireBearer(): MiddlewareHandler;
|
|
12
|
+
//# sourceMappingURL=bearer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/middleware/bearer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAI5D;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,CAkDpD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,iBAAiB,CAgDjD"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { verifyToken } from '../token.js';
|
|
2
|
+
import { AccessToken } from '../models/AccessToken.js';
|
|
3
|
+
/**
|
|
4
|
+
* Middleware that authenticates via Bearer token (JWT).
|
|
5
|
+
* Validates the JWT signature, checks expiration, checks revocation in DB.
|
|
6
|
+
* Attaches user to the request if valid. Does not block unauthenticated requests.
|
|
7
|
+
*/
|
|
8
|
+
export function BearerMiddleware() {
|
|
9
|
+
return async function BearerMiddleware(req, _res, next) {
|
|
10
|
+
const authHeader = req.headers['authorization'];
|
|
11
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
12
|
+
await next();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const jwt = authHeader.slice(7).trim();
|
|
16
|
+
try {
|
|
17
|
+
const payload = await verifyToken(jwt);
|
|
18
|
+
// Check revocation in DB
|
|
19
|
+
const token = await AccessToken.query()
|
|
20
|
+
.where('id', payload.jti)
|
|
21
|
+
.first();
|
|
22
|
+
if (!token || token.revoked) {
|
|
23
|
+
await next();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// Attach token info to the raw request
|
|
27
|
+
const raw = req.raw;
|
|
28
|
+
raw['__passport_token'] = token;
|
|
29
|
+
raw['__passport_scopes'] = payload.scopes;
|
|
30
|
+
raw['__passport_user_id'] = payload.sub;
|
|
31
|
+
// Resolve user if we have a userId
|
|
32
|
+
if (payload.sub) {
|
|
33
|
+
try {
|
|
34
|
+
const { app } = await import('@rudderjs/core');
|
|
35
|
+
const manager = app().make('auth.manager');
|
|
36
|
+
const user = await manager.guard().provider.retrieveById(payload.sub);
|
|
37
|
+
if (user) {
|
|
38
|
+
const plain = {};
|
|
39
|
+
for (const [k, v] of Object.entries(user)) {
|
|
40
|
+
if (typeof v !== 'function' && k !== 'password')
|
|
41
|
+
plain[k] = v;
|
|
42
|
+
}
|
|
43
|
+
raw['__rjs_user'] = plain;
|
|
44
|
+
try {
|
|
45
|
+
req['user'] = plain;
|
|
46
|
+
}
|
|
47
|
+
catch { /* read-only */ }
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch { /* auth not available */ }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Invalid JWT — continue without auth
|
|
55
|
+
}
|
|
56
|
+
await next();
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Middleware that requires a valid Bearer token. Returns 401 if missing/invalid.
|
|
61
|
+
*/
|
|
62
|
+
export function RequireBearer() {
|
|
63
|
+
return async function RequireBearer(req, res, next) {
|
|
64
|
+
const authHeader = req.headers['authorization'];
|
|
65
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
66
|
+
res.status(401).json({ error: 'unauthenticated', message: 'Bearer token required.' });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const jwt = authHeader.slice(7).trim();
|
|
70
|
+
try {
|
|
71
|
+
const payload = await verifyToken(jwt);
|
|
72
|
+
// Check revocation
|
|
73
|
+
const token = await AccessToken.query()
|
|
74
|
+
.where('id', payload.jti)
|
|
75
|
+
.first();
|
|
76
|
+
if (!token || token.revoked) {
|
|
77
|
+
res.status(401).json({ error: 'unauthenticated', message: 'Token has been revoked.' });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const raw = req.raw;
|
|
81
|
+
raw['__passport_token'] = token;
|
|
82
|
+
raw['__passport_scopes'] = payload.scopes;
|
|
83
|
+
raw['__passport_user_id'] = payload.sub;
|
|
84
|
+
if (payload.sub) {
|
|
85
|
+
try {
|
|
86
|
+
const { app } = await import('@rudderjs/core');
|
|
87
|
+
const manager = app().make('auth.manager');
|
|
88
|
+
const user = await manager.guard().provider.retrieveById(payload.sub);
|
|
89
|
+
if (user) {
|
|
90
|
+
const plain = {};
|
|
91
|
+
for (const [k, v] of Object.entries(user)) {
|
|
92
|
+
if (typeof v !== 'function' && k !== 'password')
|
|
93
|
+
plain[k] = v;
|
|
94
|
+
}
|
|
95
|
+
raw['__rjs_user'] = plain;
|
|
96
|
+
try {
|
|
97
|
+
req['user'] = plain;
|
|
98
|
+
}
|
|
99
|
+
catch { /* read-only */ }
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch { /* auth not available */ }
|
|
103
|
+
}
|
|
104
|
+
await next();
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
res.status(401).json({ error: 'unauthenticated', message: 'Invalid or expired token.' });
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=bearer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bearer.js","sourceRoot":"","sources":["../../src/middleware/bearer.ts"],"names":[],"mappings":"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"}
|