@productcraft/heimdall-passport 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/dist/index.cjs +32 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +50 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @productcraft/heimdall-passport
|
|
2
|
+
|
|
3
|
+
Passport-JWT adapter for [`@productcraft/heimdall`](../heimdall). Plug a Heimdall `ConsumerScope` into a `passport-jwt` Strategy so existing Passport setups can authenticate Heimdall-issued tokens.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @productcraft/heimdall @productcraft/heimdall-passport passport-jwt
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import passportJwt from "passport-jwt";
|
|
13
|
+
import { Heimdall } from "@productcraft/heimdall";
|
|
14
|
+
import { createPassportSecretOrKeyProvider } from "@productcraft/heimdall-passport";
|
|
15
|
+
|
|
16
|
+
const heimdall = new Heimdall({
|
|
17
|
+
auth: { type: "apiKey", key: process.env.PCFT_KEY! },
|
|
18
|
+
});
|
|
19
|
+
const scope = heimdall.consumer("my-app-slug");
|
|
20
|
+
|
|
21
|
+
new passportJwt.Strategy(
|
|
22
|
+
{
|
|
23
|
+
jwtFromRequest: passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
24
|
+
secretOrKeyProvider: createPassportSecretOrKeyProvider(scope),
|
|
25
|
+
issuer: scope.expectedIssuer,
|
|
26
|
+
audience: "my-app", // optional
|
|
27
|
+
algorithms: ["ES256"],
|
|
28
|
+
},
|
|
29
|
+
(payload, done) => {
|
|
30
|
+
// payload is the verified Heimdall claims object (sub, role, permissions, ...)
|
|
31
|
+
return done(null, payload);
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The helper decodes the JWT header, asks the Heimdall `ConsumerScope` for the matching signing key via its cached JWKS, converts the resulting `CryptoKey` into a Node `KeyObject`, and hands it to passport-jwt.
|
|
37
|
+
|
|
38
|
+
## How it relates to the main package
|
|
39
|
+
|
|
40
|
+
`@productcraft/heimdall` already ships a `scope.verifyToken(token)` one-liner. Use **this** package only when you have an existing Passport setup you'd rather keep. For Express middleware without Passport, the direct verify is simpler.
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
[MIT](../../LICENSE).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
var jose = require('jose');
|
|
5
|
+
|
|
6
|
+
// src/index.ts
|
|
7
|
+
function createPassportSecretOrKeyProvider(scope) {
|
|
8
|
+
return (_request, rawJwt, done) => {
|
|
9
|
+
let header;
|
|
10
|
+
try {
|
|
11
|
+
header = jose.decodeProtectedHeader(rawJwt);
|
|
12
|
+
} catch (err) {
|
|
13
|
+
done(err);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
scope.jwks.getKey(header).then(
|
|
17
|
+
(cryptoKey) => {
|
|
18
|
+
try {
|
|
19
|
+
const keyObject = crypto.KeyObject.from(cryptoKey);
|
|
20
|
+
done(null, keyObject);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
done(err);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
(err) => done(err)
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
exports.createPassportSecretOrKeyProvider = createPassportSecretOrKeyProvider;
|
|
31
|
+
//# sourceMappingURL=index.cjs.map
|
|
32
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["decodeProtectedHeader","KeyObject"],"mappings":";;;;;;AAsDO,SAAS,kCACd,KAAA,EAC6B;AAC7B,EAAA,OAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,IAAA,KAAS;AACjC,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAASA,2BAAsB,MAAM,CAAA;AAAA,IACvC,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,GAAG,CAAA;AACR,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,MAA6B,CAAA,CAAE,IAAA;AAAA,MAC/C,CAAC,SAAA,KAAc;AACb,QAAA,IAAI;AAKF,UAAA,MAAM,SAAA,GAAYC,gBAAA,CAAU,IAAA,CAAK,SAAS,CAAA;AAC1C,UAAA,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,QACtB,SAAS,GAAA,EAAK;AACZ,UAAA,IAAA,CAAK,GAAG,CAAA;AAAA,QACV;AAAA,MACF,CAAA;AAAA,MACA,CAAC,GAAA,KAAQ,IAAA,CAAK,GAAG;AAAA,KACnB;AAAA,EACF,CAAA;AACF","file":"index.cjs","sourcesContent":["/**\n * `@productcraft/heimdall-passport` — passport-jwt adapter for Heimdall.\n *\n * Install alongside `@productcraft/heimdall` + `passport-jwt`:\n *\n * ```bash\n * npm install @productcraft/heimdall @productcraft/heimdall-passport passport-jwt\n * ```\n *\n * Usage:\n *\n * ```ts\n * import passportJwt from \"passport-jwt\";\n * import { Heimdall } from \"@productcraft/heimdall\";\n * import { createPassportSecretOrKeyProvider } from \"@productcraft/heimdall-passport\";\n *\n * const heimdall = new Heimdall({ auth: { type: \"apiKey\", key: process.env.PCFT_KEY! } });\n * const scope = heimdall.consumer(\"my-app-slug\");\n *\n * new passportJwt.Strategy(\n * {\n * jwtFromRequest: passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken(),\n * secretOrKeyProvider: createPassportSecretOrKeyProvider(scope),\n * issuer: scope.expectedIssuer,\n * algorithms: [\"ES256\"],\n * },\n * (payload, done) => done(null, payload),\n * );\n * ```\n */\n\nimport { KeyObject } from \"node:crypto\";\nimport { decodeProtectedHeader, type JWTHeaderParameters } from \"jose\";\n\nimport type { ConsumerScope } from \"@productcraft/heimdall\";\n\n/**\n * passport-jwt's `secretOrKeyProvider` callback signature. We don't\n * depend on passport-jwt's types directly (to keep it a soft dep),\n * so this is the same shape as `SecretOrKeyProvider` in their typings.\n */\ntype PassportSecretOrKeyProvider = (\n request: unknown,\n rawJwtToken: string,\n done: (err: unknown, secretOrKey?: string | Buffer | KeyObject) => void,\n) => void;\n\n/**\n * Returns a passport-jwt `secretOrKeyProvider` bound to a Heimdall\n * `ConsumerScope`. Decodes the protected header, looks up the matching\n * key via the scope's JWKS cache, and converts the resulting jose\n * `CryptoKey` into a Node `KeyObject` that `jsonwebtoken` (the library\n * passport-jwt delegates to) accepts.\n */\nexport function createPassportSecretOrKeyProvider(\n scope: ConsumerScope,\n): PassportSecretOrKeyProvider {\n return (_request, rawJwt, done) => {\n let header;\n try {\n header = decodeProtectedHeader(rawJwt);\n } catch (err) {\n done(err);\n return;\n }\n\n scope.jwks.getKey(header as JWTHeaderParameters).then(\n (cryptoKey) => {\n try {\n // `jsonwebtoken` (passport-jwt's verifier) doesn't accept\n // Web Crypto `CryptoKey`, but it does accept Node's\n // `KeyObject`. `KeyObject.from(cryptoKey)` was added in\n // Node 16.6 and is the right adapter.\n const keyObject = KeyObject.from(cryptoKey);\n done(null, keyObject);\n } catch (err) {\n done(err);\n }\n },\n (err) => done(err),\n );\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { KeyObject } from 'node:crypto';
|
|
2
|
+
import { ConsumerScope } from '@productcraft/heimdall';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@productcraft/heimdall-passport` — passport-jwt adapter for Heimdall.
|
|
6
|
+
*
|
|
7
|
+
* Install alongside `@productcraft/heimdall` + `passport-jwt`:
|
|
8
|
+
*
|
|
9
|
+
* ```bash
|
|
10
|
+
* npm install @productcraft/heimdall @productcraft/heimdall-passport passport-jwt
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* import passportJwt from "passport-jwt";
|
|
17
|
+
* import { Heimdall } from "@productcraft/heimdall";
|
|
18
|
+
* import { createPassportSecretOrKeyProvider } from "@productcraft/heimdall-passport";
|
|
19
|
+
*
|
|
20
|
+
* const heimdall = new Heimdall({ auth: { type: "apiKey", key: process.env.PCFT_KEY! } });
|
|
21
|
+
* const scope = heimdall.consumer("my-app-slug");
|
|
22
|
+
*
|
|
23
|
+
* new passportJwt.Strategy(
|
|
24
|
+
* {
|
|
25
|
+
* jwtFromRequest: passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
26
|
+
* secretOrKeyProvider: createPassportSecretOrKeyProvider(scope),
|
|
27
|
+
* issuer: scope.expectedIssuer,
|
|
28
|
+
* algorithms: ["ES256"],
|
|
29
|
+
* },
|
|
30
|
+
* (payload, done) => done(null, payload),
|
|
31
|
+
* );
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* passport-jwt's `secretOrKeyProvider` callback signature. We don't
|
|
37
|
+
* depend on passport-jwt's types directly (to keep it a soft dep),
|
|
38
|
+
* so this is the same shape as `SecretOrKeyProvider` in their typings.
|
|
39
|
+
*/
|
|
40
|
+
type PassportSecretOrKeyProvider = (request: unknown, rawJwtToken: string, done: (err: unknown, secretOrKey?: string | Buffer | KeyObject) => void) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Returns a passport-jwt `secretOrKeyProvider` bound to a Heimdall
|
|
43
|
+
* `ConsumerScope`. Decodes the protected header, looks up the matching
|
|
44
|
+
* key via the scope's JWKS cache, and converts the resulting jose
|
|
45
|
+
* `CryptoKey` into a Node `KeyObject` that `jsonwebtoken` (the library
|
|
46
|
+
* passport-jwt delegates to) accepts.
|
|
47
|
+
*/
|
|
48
|
+
declare function createPassportSecretOrKeyProvider(scope: ConsumerScope): PassportSecretOrKeyProvider;
|
|
49
|
+
|
|
50
|
+
export { createPassportSecretOrKeyProvider };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { KeyObject } from 'node:crypto';
|
|
2
|
+
import { ConsumerScope } from '@productcraft/heimdall';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@productcraft/heimdall-passport` — passport-jwt adapter for Heimdall.
|
|
6
|
+
*
|
|
7
|
+
* Install alongside `@productcraft/heimdall` + `passport-jwt`:
|
|
8
|
+
*
|
|
9
|
+
* ```bash
|
|
10
|
+
* npm install @productcraft/heimdall @productcraft/heimdall-passport passport-jwt
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* import passportJwt from "passport-jwt";
|
|
17
|
+
* import { Heimdall } from "@productcraft/heimdall";
|
|
18
|
+
* import { createPassportSecretOrKeyProvider } from "@productcraft/heimdall-passport";
|
|
19
|
+
*
|
|
20
|
+
* const heimdall = new Heimdall({ auth: { type: "apiKey", key: process.env.PCFT_KEY! } });
|
|
21
|
+
* const scope = heimdall.consumer("my-app-slug");
|
|
22
|
+
*
|
|
23
|
+
* new passportJwt.Strategy(
|
|
24
|
+
* {
|
|
25
|
+
* jwtFromRequest: passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
26
|
+
* secretOrKeyProvider: createPassportSecretOrKeyProvider(scope),
|
|
27
|
+
* issuer: scope.expectedIssuer,
|
|
28
|
+
* algorithms: ["ES256"],
|
|
29
|
+
* },
|
|
30
|
+
* (payload, done) => done(null, payload),
|
|
31
|
+
* );
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* passport-jwt's `secretOrKeyProvider` callback signature. We don't
|
|
37
|
+
* depend on passport-jwt's types directly (to keep it a soft dep),
|
|
38
|
+
* so this is the same shape as `SecretOrKeyProvider` in their typings.
|
|
39
|
+
*/
|
|
40
|
+
type PassportSecretOrKeyProvider = (request: unknown, rawJwtToken: string, done: (err: unknown, secretOrKey?: string | Buffer | KeyObject) => void) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Returns a passport-jwt `secretOrKeyProvider` bound to a Heimdall
|
|
43
|
+
* `ConsumerScope`. Decodes the protected header, looks up the matching
|
|
44
|
+
* key via the scope's JWKS cache, and converts the resulting jose
|
|
45
|
+
* `CryptoKey` into a Node `KeyObject` that `jsonwebtoken` (the library
|
|
46
|
+
* passport-jwt delegates to) accepts.
|
|
47
|
+
*/
|
|
48
|
+
declare function createPassportSecretOrKeyProvider(scope: ConsumerScope): PassportSecretOrKeyProvider;
|
|
49
|
+
|
|
50
|
+
export { createPassportSecretOrKeyProvider };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { KeyObject } from 'crypto';
|
|
2
|
+
import { decodeProtectedHeader } from 'jose';
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
function createPassportSecretOrKeyProvider(scope) {
|
|
6
|
+
return (_request, rawJwt, done) => {
|
|
7
|
+
let header;
|
|
8
|
+
try {
|
|
9
|
+
header = decodeProtectedHeader(rawJwt);
|
|
10
|
+
} catch (err) {
|
|
11
|
+
done(err);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
scope.jwks.getKey(header).then(
|
|
15
|
+
(cryptoKey) => {
|
|
16
|
+
try {
|
|
17
|
+
const keyObject = KeyObject.from(cryptoKey);
|
|
18
|
+
done(null, keyObject);
|
|
19
|
+
} catch (err) {
|
|
20
|
+
done(err);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
(err) => done(err)
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { createPassportSecretOrKeyProvider };
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;AAsDO,SAAS,kCACd,KAAA,EAC6B;AAC7B,EAAA,OAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,IAAA,KAAS;AACjC,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,sBAAsB,MAAM,CAAA;AAAA,IACvC,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,GAAG,CAAA;AACR,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,MAA6B,CAAA,CAAE,IAAA;AAAA,MAC/C,CAAC,SAAA,KAAc;AACb,QAAA,IAAI;AAKF,UAAA,MAAM,SAAA,GAAY,SAAA,CAAU,IAAA,CAAK,SAAS,CAAA;AAC1C,UAAA,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,QACtB,SAAS,GAAA,EAAK;AACZ,UAAA,IAAA,CAAK,GAAG,CAAA;AAAA,QACV;AAAA,MACF,CAAA;AAAA,MACA,CAAC,GAAA,KAAQ,IAAA,CAAK,GAAG;AAAA,KACnB;AAAA,EACF,CAAA;AACF","file":"index.js","sourcesContent":["/**\n * `@productcraft/heimdall-passport` — passport-jwt adapter for Heimdall.\n *\n * Install alongside `@productcraft/heimdall` + `passport-jwt`:\n *\n * ```bash\n * npm install @productcraft/heimdall @productcraft/heimdall-passport passport-jwt\n * ```\n *\n * Usage:\n *\n * ```ts\n * import passportJwt from \"passport-jwt\";\n * import { Heimdall } from \"@productcraft/heimdall\";\n * import { createPassportSecretOrKeyProvider } from \"@productcraft/heimdall-passport\";\n *\n * const heimdall = new Heimdall({ auth: { type: \"apiKey\", key: process.env.PCFT_KEY! } });\n * const scope = heimdall.consumer(\"my-app-slug\");\n *\n * new passportJwt.Strategy(\n * {\n * jwtFromRequest: passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken(),\n * secretOrKeyProvider: createPassportSecretOrKeyProvider(scope),\n * issuer: scope.expectedIssuer,\n * algorithms: [\"ES256\"],\n * },\n * (payload, done) => done(null, payload),\n * );\n * ```\n */\n\nimport { KeyObject } from \"node:crypto\";\nimport { decodeProtectedHeader, type JWTHeaderParameters } from \"jose\";\n\nimport type { ConsumerScope } from \"@productcraft/heimdall\";\n\n/**\n * passport-jwt's `secretOrKeyProvider` callback signature. We don't\n * depend on passport-jwt's types directly (to keep it a soft dep),\n * so this is the same shape as `SecretOrKeyProvider` in their typings.\n */\ntype PassportSecretOrKeyProvider = (\n request: unknown,\n rawJwtToken: string,\n done: (err: unknown, secretOrKey?: string | Buffer | KeyObject) => void,\n) => void;\n\n/**\n * Returns a passport-jwt `secretOrKeyProvider` bound to a Heimdall\n * `ConsumerScope`. Decodes the protected header, looks up the matching\n * key via the scope's JWKS cache, and converts the resulting jose\n * `CryptoKey` into a Node `KeyObject` that `jsonwebtoken` (the library\n * passport-jwt delegates to) accepts.\n */\nexport function createPassportSecretOrKeyProvider(\n scope: ConsumerScope,\n): PassportSecretOrKeyProvider {\n return (_request, rawJwt, done) => {\n let header;\n try {\n header = decodeProtectedHeader(rawJwt);\n } catch (err) {\n done(err);\n return;\n }\n\n scope.jwks.getKey(header as JWTHeaderParameters).then(\n (cryptoKey) => {\n try {\n // `jsonwebtoken` (passport-jwt's verifier) doesn't accept\n // Web Crypto `CryptoKey`, but it does accept Node's\n // `KeyObject`. `KeyObject.from(cryptoKey)` was added in\n // Node 16.6 and is the right adapter.\n const keyObject = KeyObject.from(cryptoKey);\n done(null, keyObject);\n } catch (err) {\n done(err);\n }\n },\n (err) => done(err),\n );\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@productcraft/heimdall-passport",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Passport-JWT adapter for ProductCraft Heimdall. Plug a Heimdall ConsumerScope into a `passport-jwt` Strategy so existing Passport setups can authenticate Heimdall-issued tokens.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist/**",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=18"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"test": "vitest run"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"productcraft",
|
|
30
|
+
"sdk",
|
|
31
|
+
"heimdall",
|
|
32
|
+
"passport",
|
|
33
|
+
"passport-jwt",
|
|
34
|
+
"auth",
|
|
35
|
+
"jwt"
|
|
36
|
+
],
|
|
37
|
+
"author": "ProductCraft",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/clauderanelagh/productcraft-node.git",
|
|
42
|
+
"directory": "packages/heimdall-passport"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/clauderanelagh/productcraft-node/tree/main/packages/heimdall-passport",
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"provenance": true
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@productcraft/heimdall": "workspace:^",
|
|
51
|
+
"jose": "^6.2.3"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"passport-jwt": "^4.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|