@thisisagile/easy-express 15.14.2 → 15.14.4

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.
@@ -1,19 +1,20 @@
1
1
  /// <reference types="node" />
2
- import express, { Request, RequestHandler } from 'express';
3
- import { Scope, UseCase } from '@thisisagile/easy';
4
- type SecretOrKeyProvider = (request: Request, rawJwtToken: any) => Promise<string | Buffer>;
2
+ import type { NextFunction, Request, RequestHandler, Response } from 'express';
3
+ import type { Algorithm } from 'jsonwebtoken';
4
+ import type { Scope, UseCase } from '@thisisagile/easy';
5
+ type EasySecretOrKeyProvider = (request: Request, rawJwtToken: any) => Promise<string | Buffer>;
5
6
  export interface SecurityOptions {
6
7
  jwtStrategyOptions?: {
7
8
  secretOrKey?: string | Buffer;
8
- secretOrKeyProvider?: SecretOrKeyProvider;
9
+ secretOrKeyProvider?: EasySecretOrKeyProvider;
9
10
  issuer?: string;
10
11
  audience?: string;
11
- algorithms?: string[];
12
+ algorithms?: Algorithm[];
12
13
  };
13
14
  }
14
15
  export declare const checkLabCoat: () => RequestHandler;
15
16
  export declare const checkToken: () => RequestHandler;
16
17
  export declare const checkScope: (scope: Scope) => RequestHandler;
17
18
  export declare const checkUseCase: (uc: UseCase) => RequestHandler;
18
- export declare const security: ({ jwtStrategyOptions }?: SecurityOptions) => (req: express.Request, res: express.Response, next: express.NextFunction) => void;
19
+ export declare const security: ({ jwtStrategyOptions }?: SecurityOptions) => (req: Request, res: Response, next: NextFunction) => void;
19
20
  export {};
@@ -45,16 +45,16 @@ const checkScope = (scope) => (req, res, next) => next((0, import_easy.ifFalse)(
45
45
  const checkUseCase = (uc) => (req, res, next) => next((0, import_easy.ifFalse)(req.user?.usecases?.includes(uc.id), (0, import_AuthError.authError)(import_easy.HttpStatus.Forbidden)));
46
46
  const wrapSecretOrKeyProvider = (p) => p ? (request, rawJwtToken, done) => p(request, rawJwtToken).then((t) => done(null, t)).catch((e) => done(e)) : void 0;
47
47
  const security = ({ jwtStrategyOptions } = {}) => {
48
- const jwtConfig = {
48
+ jwtStrategyOptions ??= {};
49
+ if ("secretOrKeyProvider" in jwtStrategyOptions)
50
+ jwtStrategyOptions.secretOrKeyProvider = wrapSecretOrKeyProvider(jwtStrategyOptions.secretOrKeyProvider);
51
+ else if (!("secretOrKey" in jwtStrategyOptions))
52
+ jwtStrategyOptions.secretOrKey = import_easy.ctx.env.get("tokenPublicKey");
53
+ const strategy = new import_passport_jwt.Strategy({
49
54
  jwtFromRequest: import_passport_jwt.ExtractJwt.fromAuthHeaderAsBearerToken(),
50
- secretOrKey: jwtStrategyOptions?.secretOrKey ?? (jwtStrategyOptions?.secretOrKeyProvider ? void 0 : import_easy.ctx.env.get("tokenPublicKey")),
51
- secretOrKeyProvider: wrapSecretOrKeyProvider(jwtStrategyOptions?.secretOrKeyProvider),
52
- issuer: jwtStrategyOptions?.issuer,
53
- audience: jwtStrategyOptions?.audience,
54
- algorithms: jwtStrategyOptions?.algorithms,
55
- passReqToCallback: true
56
- };
57
- const strategy = new import_passport_jwt.Strategy(jwtConfig, (req, payload, done) => {
55
+ passReqToCallback: true,
56
+ ...jwtStrategyOptions
57
+ }, (req, payload, done) => {
58
58
  import_easy.ctx.request.token = payload;
59
59
  import_easy.ctx.request.jwt = import_passport_jwt.ExtractJwt.fromAuthHeaderAsBearerToken()(req) ?? "";
60
60
  done(null, payload);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/express/SecurityHandler.ts"],"sourcesContent":["import express, { Request, RequestHandler } from 'express';\nimport passport from 'passport';\nimport passportJwt, { ExtractJwt, Strategy as JwtStrategy, StrategyOptions } from 'passport-jwt';\nimport { authError } from './AuthError';\nimport { ctx, Environment, HttpStatus, ifFalse, Scope, UseCase } from '@thisisagile/easy';\n\ntype SecretOrKeyProvider = (request: Request, rawJwtToken: any) => Promise<string | Buffer>;\n\nexport interface SecurityOptions {\n /** Configuration for verifying JWTs */\n jwtStrategyOptions?: {\n /** The secret (symmetric) or PEM-encoded public key (asymmetric) for verifying the token's signature.\n * REQUIRED unless secretOrKeyProvider is provided. Defaults to JWT_PUBLIC_KEY from the system environment. */\n secretOrKey?: string | Buffer;\n\n /** Should return a secret (symmetric) or PEM-encoded public key (asymmetric) for the given key and request combination.\n * REQUIRED unless secretOrKey is provided. Note it is up to the implementer to decode rawJwtToken. */\n secretOrKeyProvider?: SecretOrKeyProvider;\n\n /** If defined, the token issuer (iss) will be verified against this value. */\n issuer?: string;\n\n /** If defined, the token audience (aud) will be verified against this value. */\n audience?: string;\n\n /** If defined, the token algorithm (alg) must be in this list. */\n algorithms?: string[];\n };\n}\n\nexport const checkLabCoat = (): RequestHandler => (req, res, next) => next(ifFalse(Environment.Dev.equals(ctx.env.name), authError(HttpStatus.Forbidden)));\n\nexport const checkToken = (): RequestHandler => passport.authenticate('jwt', { session: false, failWithError: true });\n\nexport const checkScope =\n (scope: Scope): RequestHandler =>\n (req, res, next) =>\n next(ifFalse((req.user as any)?.scopes?.includes(scope.id), authError(HttpStatus.Forbidden)));\n\nexport const checkUseCase =\n (uc: UseCase): RequestHandler =>\n (req, res, next) =>\n next(ifFalse((req.user as any)?.usecases?.includes(uc.id), authError(HttpStatus.Forbidden)));\n\nconst wrapSecretOrKeyProvider = (p?: SecretOrKeyProvider): passportJwt.SecretOrKeyProvider | undefined =>\n p\n ? (request, rawJwtToken, done) =>\n p(request, rawJwtToken)\n .then(t => done(null, t))\n .catch(e => done(e))\n : undefined;\n\nexport const security = ({ jwtStrategyOptions }: SecurityOptions = {}): ((req: express.Request, res: express.Response, next: express.NextFunction) => void) => {\n const jwtConfig: StrategyOptions = {\n jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),\n secretOrKey: jwtStrategyOptions?.secretOrKey ?? (jwtStrategyOptions?.secretOrKeyProvider ? undefined : ctx.env.get('tokenPublicKey')),\n secretOrKeyProvider: wrapSecretOrKeyProvider(jwtStrategyOptions?.secretOrKeyProvider),\n issuer: jwtStrategyOptions?.issuer,\n audience: jwtStrategyOptions?.audience,\n algorithms: jwtStrategyOptions?.algorithms,\n passReqToCallback: true,\n };\n\n const strategy = new JwtStrategy(jwtConfig, (req: express.Request, payload: any, done: (err: any, user: any) => void) => {\n ctx.request.token = payload;\n ctx.request.jwt = ExtractJwt.fromAuthHeaderAsBearerToken()(req) ?? '';\n done(null, payload);\n });\n\n passport.use(strategy);\n return passport.initialize();\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,sBAAqB;AACrB,0BAAkF;AAClF,uBAA0B;AAC1B,kBAAsE;AA0B/D,MAAM,eAAe,MAAsB,CAAC,KAAK,KAAK,SAAS,SAAK,qBAAQ,wBAAY,IAAI,OAAO,gBAAI,IAAI,IAAI,OAAG,4BAAU,uBAAW,SAAS,CAAC,CAAC;AAElJ,MAAM,aAAa,MAAsB,gBAAAA,QAAS,aAAa,OAAO,EAAE,SAAS,OAAO,eAAe,KAAK,CAAC;AAE7G,MAAM,aACX,CAAC,UACD,CAAC,KAAK,KAAK,SACT,SAAK,qBAAS,IAAI,MAAc,QAAQ,SAAS,MAAM,EAAE,OAAG,4BAAU,uBAAW,SAAS,CAAC,CAAC;AAEzF,MAAM,eACX,CAAC,OACD,CAAC,KAAK,KAAK,SACT,SAAK,qBAAS,IAAI,MAAc,UAAU,SAAS,GAAG,EAAE,OAAG,4BAAU,uBAAW,SAAS,CAAC,CAAC;AAE/F,MAAM,0BAA0B,CAAC,MAC/B,IACI,CAAC,SAAS,aAAa,SACrB,EAAE,SAAS,WAAW,EACnB,KAAK,OAAK,KAAK,MAAM,CAAC,CAAC,EACvB,MAAM,OAAK,KAAK,CAAC,CAAC,IACvB;AAEC,MAAM,WAAW,CAAC,EAAE,mBAAmB,IAAqB,CAAC,MAA2F;AAC7J,QAAM,YAA6B;AAAA,IACjC,gBAAgB,+BAAW,4BAA4B;AAAA,IACvD,aAAa,oBAAoB,gBAAgB,oBAAoB,sBAAsB,SAAY,gBAAI,IAAI,IAAI,gBAAgB;AAAA,IACnI,qBAAqB,wBAAwB,oBAAoB,mBAAmB;AAAA,IACpF,QAAQ,oBAAoB;AAAA,IAC5B,UAAU,oBAAoB;AAAA,IAC9B,YAAY,oBAAoB;AAAA,IAChC,mBAAmB;AAAA,EACrB;AAEA,QAAM,WAAW,IAAI,oBAAAC,SAAY,WAAW,CAAC,KAAsB,SAAc,SAAwC;AACvH,oBAAI,QAAQ,QAAQ;AACpB,oBAAI,QAAQ,MAAM,+BAAW,4BAA4B,EAAE,GAAG,KAAK;AACnE,SAAK,MAAM,OAAO;AAAA,EACpB,CAAC;AAED,kBAAAD,QAAS,IAAI,QAAQ;AACrB,SAAO,gBAAAA,QAAS,WAAW;AAC7B;","names":["passport","JwtStrategy"]}
1
+ {"version":3,"sources":["../../src/express/SecurityHandler.ts"],"sourcesContent":["import type { NextFunction, Request, RequestHandler, Response } from 'express';\nimport passport from 'passport';\nimport { ExtractJwt, Strategy as JwtStrategy } from 'passport-jwt';\nimport type { SecretOrKeyProvider, StrategyOptionsWithRequest } from 'passport-jwt';\nimport type { Algorithm } from 'jsonwebtoken';\nimport { authError } from './AuthError';\nimport { ctx, Environment, HttpStatus, ifFalse } from '@thisisagile/easy';\nimport type { Scope, UseCase } from '@thisisagile/easy';\n\ntype EasySecretOrKeyProvider = (request: Request, rawJwtToken: any) => Promise<string | Buffer>;\n\nexport interface SecurityOptions {\n /** Configuration for verifying JWTs */\n jwtStrategyOptions?: {\n /** The secret (symmetric) or PEM-encoded public key (asymmetric) for verifying the token's signature.\n * REQUIRED unless secretOrKeyProvider is provided. Defaults to JWT_PUBLIC_KEY from the system environment. */\n secretOrKey?: string | Buffer;\n\n /** Should return a secret (symmetric) or PEM-encoded public key (asymmetric) for the given key and request combination.\n * REQUIRED unless secretOrKey is provided. Note it is up to the implementer to decode rawJwtToken. */\n secretOrKeyProvider?: EasySecretOrKeyProvider;\n\n /** If defined, the token issuer (iss) will be verified against this value. */\n issuer?: string;\n\n /** If defined, the token audience (aud) will be verified against this value. */\n audience?: string;\n\n /** If defined, the token algorithm (alg) must be in this list. */\n algorithms?: Algorithm[];\n };\n}\n\nexport const checkLabCoat = (): RequestHandler => (req, res, next) => next(ifFalse(Environment.Dev.equals(ctx.env.name), authError(HttpStatus.Forbidden)));\n\nexport const checkToken = (): RequestHandler => passport.authenticate('jwt', { session: false, failWithError: true });\n\nexport const checkScope =\n (scope: Scope): RequestHandler =>\n (req, res, next) =>\n next(ifFalse((req.user as any)?.scopes?.includes(scope.id), authError(HttpStatus.Forbidden)));\n\nexport const checkUseCase =\n (uc: UseCase): RequestHandler =>\n (req, res, next) =>\n next(ifFalse((req.user as any)?.usecases?.includes(uc.id), authError(HttpStatus.Forbidden)));\n\nconst wrapSecretOrKeyProvider = (p?: EasySecretOrKeyProvider): SecretOrKeyProvider | undefined =>\n p\n ? (request, rawJwtToken, done) =>\n p(request, rawJwtToken)\n .then(t => done(null, t))\n .catch(e => done(e))\n : undefined;\n\nexport const security = ({ jwtStrategyOptions }: SecurityOptions = {}): ((req: Request, res: Response, next: NextFunction) => void) => {\n jwtStrategyOptions ??= {};\n if ('secretOrKeyProvider' in jwtStrategyOptions) (jwtStrategyOptions as any).secretOrKeyProvider = wrapSecretOrKeyProvider(jwtStrategyOptions.secretOrKeyProvider);\n else if (!('secretOrKey' in jwtStrategyOptions)) jwtStrategyOptions.secretOrKey = ctx.env.get('tokenPublicKey') as string;\n\n const strategy =\n new JwtStrategy({\n jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),\n passReqToCallback: true,\n ...jwtStrategyOptions,\n } as StrategyOptionsWithRequest, (req: Request, payload: any, done: (err: any, user: any) => void) => {\n ctx.request.token = payload;\n ctx.request.jwt = ExtractJwt.fromAuthHeaderAsBearerToken()(req) ?? '';\n done(null, payload);\n });\n\n passport.use(strategy);\n return passport.initialize();\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,sBAAqB;AACrB,0BAAoD;AAGpD,uBAA0B;AAC1B,kBAAsD;AA2B/C,MAAM,eAAe,MAAsB,CAAC,KAAK,KAAK,SAAS,SAAK,qBAAQ,wBAAY,IAAI,OAAO,gBAAI,IAAI,IAAI,OAAG,4BAAU,uBAAW,SAAS,CAAC,CAAC;AAElJ,MAAM,aAAa,MAAsB,gBAAAA,QAAS,aAAa,OAAO,EAAE,SAAS,OAAO,eAAe,KAAK,CAAC;AAE7G,MAAM,aACX,CAAC,UACD,CAAC,KAAK,KAAK,SACT,SAAK,qBAAS,IAAI,MAAc,QAAQ,SAAS,MAAM,EAAE,OAAG,4BAAU,uBAAW,SAAS,CAAC,CAAC;AAEzF,MAAM,eACX,CAAC,OACD,CAAC,KAAK,KAAK,SACT,SAAK,qBAAS,IAAI,MAAc,UAAU,SAAS,GAAG,EAAE,OAAG,4BAAU,uBAAW,SAAS,CAAC,CAAC;AAE/F,MAAM,0BAA0B,CAAC,MAC/B,IACI,CAAC,SAAS,aAAa,SACrB,EAAE,SAAS,WAAW,EACnB,KAAK,OAAK,KAAK,MAAM,CAAC,CAAC,EACvB,MAAM,OAAK,KAAK,CAAC,CAAC,IACvB;AAEC,MAAM,WAAW,CAAC,EAAE,mBAAmB,IAAqB,CAAC,MAAmE;AACrI,yBAAuB,CAAC;AACxB,MAAI,yBAAyB;AAAoB,IAAC,mBAA2B,sBAAsB,wBAAwB,mBAAmB,mBAAmB;AAAA,WACxJ,EAAE,iBAAiB;AAAqB,uBAAmB,cAAc,gBAAI,IAAI,IAAI,gBAAgB;AAE9G,QAAM,WACJ,IAAI,oBAAAC,SAAY;AAAA,IAChB,gBAAgB,+BAAW,4BAA4B;AAAA,IACvD,mBAAmB;AAAA,IACnB,GAAG;AAAA,EACL,GAAiC,CAAC,KAAc,SAAc,SAAwC;AACpG,oBAAI,QAAQ,QAAQ;AACpB,oBAAI,QAAQ,MAAM,+BAAW,4BAA4B,EAAE,GAAG,KAAK;AACnE,SAAK,MAAM,OAAO;AAAA,EACpB,CAAC;AAED,kBAAAD,QAAS,IAAI,QAAQ;AACrB,SAAO,gBAAAA,QAAS,WAAW;AAC7B;","names":["passport","JwtStrategy"]}
@@ -8,16 +8,16 @@ const checkScope = (scope) => (req, res, next) => next(ifFalse(req.user?.scopes?
8
8
  const checkUseCase = (uc) => (req, res, next) => next(ifFalse(req.user?.usecases?.includes(uc.id), authError(HttpStatus.Forbidden)));
9
9
  const wrapSecretOrKeyProvider = (p) => p ? (request, rawJwtToken, done) => p(request, rawJwtToken).then((t) => done(null, t)).catch((e) => done(e)) : void 0;
10
10
  const security = ({ jwtStrategyOptions } = {}) => {
11
- const jwtConfig = {
11
+ jwtStrategyOptions ??= {};
12
+ if ("secretOrKeyProvider" in jwtStrategyOptions)
13
+ jwtStrategyOptions.secretOrKeyProvider = wrapSecretOrKeyProvider(jwtStrategyOptions.secretOrKeyProvider);
14
+ else if (!("secretOrKey" in jwtStrategyOptions))
15
+ jwtStrategyOptions.secretOrKey = ctx.env.get("tokenPublicKey");
16
+ const strategy = new JwtStrategy({
12
17
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
13
- secretOrKey: jwtStrategyOptions?.secretOrKey ?? (jwtStrategyOptions?.secretOrKeyProvider ? void 0 : ctx.env.get("tokenPublicKey")),
14
- secretOrKeyProvider: wrapSecretOrKeyProvider(jwtStrategyOptions?.secretOrKeyProvider),
15
- issuer: jwtStrategyOptions?.issuer,
16
- audience: jwtStrategyOptions?.audience,
17
- algorithms: jwtStrategyOptions?.algorithms,
18
- passReqToCallback: true
19
- };
20
- const strategy = new JwtStrategy(jwtConfig, (req, payload, done) => {
18
+ passReqToCallback: true,
19
+ ...jwtStrategyOptions
20
+ }, (req, payload, done) => {
21
21
  ctx.request.token = payload;
22
22
  ctx.request.jwt = ExtractJwt.fromAuthHeaderAsBearerToken()(req) ?? "";
23
23
  done(null, payload);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/express/SecurityHandler.ts"],"sourcesContent":["import express, { Request, RequestHandler } from 'express';\nimport passport from 'passport';\nimport passportJwt, { ExtractJwt, Strategy as JwtStrategy, StrategyOptions } from 'passport-jwt';\nimport { authError } from './AuthError';\nimport { ctx, Environment, HttpStatus, ifFalse, Scope, UseCase } from '@thisisagile/easy';\n\ntype SecretOrKeyProvider = (request: Request, rawJwtToken: any) => Promise<string | Buffer>;\n\nexport interface SecurityOptions {\n /** Configuration for verifying JWTs */\n jwtStrategyOptions?: {\n /** The secret (symmetric) or PEM-encoded public key (asymmetric) for verifying the token's signature.\n * REQUIRED unless secretOrKeyProvider is provided. Defaults to JWT_PUBLIC_KEY from the system environment. */\n secretOrKey?: string | Buffer;\n\n /** Should return a secret (symmetric) or PEM-encoded public key (asymmetric) for the given key and request combination.\n * REQUIRED unless secretOrKey is provided. Note it is up to the implementer to decode rawJwtToken. */\n secretOrKeyProvider?: SecretOrKeyProvider;\n\n /** If defined, the token issuer (iss) will be verified against this value. */\n issuer?: string;\n\n /** If defined, the token audience (aud) will be verified against this value. */\n audience?: string;\n\n /** If defined, the token algorithm (alg) must be in this list. */\n algorithms?: string[];\n };\n}\n\nexport const checkLabCoat = (): RequestHandler => (req, res, next) => next(ifFalse(Environment.Dev.equals(ctx.env.name), authError(HttpStatus.Forbidden)));\n\nexport const checkToken = (): RequestHandler => passport.authenticate('jwt', { session: false, failWithError: true });\n\nexport const checkScope =\n (scope: Scope): RequestHandler =>\n (req, res, next) =>\n next(ifFalse((req.user as any)?.scopes?.includes(scope.id), authError(HttpStatus.Forbidden)));\n\nexport const checkUseCase =\n (uc: UseCase): RequestHandler =>\n (req, res, next) =>\n next(ifFalse((req.user as any)?.usecases?.includes(uc.id), authError(HttpStatus.Forbidden)));\n\nconst wrapSecretOrKeyProvider = (p?: SecretOrKeyProvider): passportJwt.SecretOrKeyProvider | undefined =>\n p\n ? (request, rawJwtToken, done) =>\n p(request, rawJwtToken)\n .then(t => done(null, t))\n .catch(e => done(e))\n : undefined;\n\nexport const security = ({ jwtStrategyOptions }: SecurityOptions = {}): ((req: express.Request, res: express.Response, next: express.NextFunction) => void) => {\n const jwtConfig: StrategyOptions = {\n jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),\n secretOrKey: jwtStrategyOptions?.secretOrKey ?? (jwtStrategyOptions?.secretOrKeyProvider ? undefined : ctx.env.get('tokenPublicKey')),\n secretOrKeyProvider: wrapSecretOrKeyProvider(jwtStrategyOptions?.secretOrKeyProvider),\n issuer: jwtStrategyOptions?.issuer,\n audience: jwtStrategyOptions?.audience,\n algorithms: jwtStrategyOptions?.algorithms,\n passReqToCallback: true,\n };\n\n const strategy = new JwtStrategy(jwtConfig, (req: express.Request, payload: any, done: (err: any, user: any) => void) => {\n ctx.request.token = payload;\n ctx.request.jwt = ExtractJwt.fromAuthHeaderAsBearerToken()(req) ?? '';\n done(null, payload);\n });\n\n passport.use(strategy);\n return passport.initialize();\n};\n"],"mappings":"AACA,OAAO,cAAc;AACrB,SAAsB,YAAY,YAAY,mBAAoC;AAClF,SAAS,iBAAiB;AAC1B,SAAS,KAAK,aAAa,YAAY,eAA+B;AA0B/D,MAAM,eAAe,MAAsB,CAAC,KAAK,KAAK,SAAS,KAAK,QAAQ,YAAY,IAAI,OAAO,IAAI,IAAI,IAAI,GAAG,UAAU,WAAW,SAAS,CAAC,CAAC;AAElJ,MAAM,aAAa,MAAsB,SAAS,aAAa,OAAO,EAAE,SAAS,OAAO,eAAe,KAAK,CAAC;AAE7G,MAAM,aACX,CAAC,UACD,CAAC,KAAK,KAAK,SACT,KAAK,QAAS,IAAI,MAAc,QAAQ,SAAS,MAAM,EAAE,GAAG,UAAU,WAAW,SAAS,CAAC,CAAC;AAEzF,MAAM,eACX,CAAC,OACD,CAAC,KAAK,KAAK,SACT,KAAK,QAAS,IAAI,MAAc,UAAU,SAAS,GAAG,EAAE,GAAG,UAAU,WAAW,SAAS,CAAC,CAAC;AAE/F,MAAM,0BAA0B,CAAC,MAC/B,IACI,CAAC,SAAS,aAAa,SACrB,EAAE,SAAS,WAAW,EACnB,KAAK,OAAK,KAAK,MAAM,CAAC,CAAC,EACvB,MAAM,OAAK,KAAK,CAAC,CAAC,IACvB;AAEC,MAAM,WAAW,CAAC,EAAE,mBAAmB,IAAqB,CAAC,MAA2F;AAC7J,QAAM,YAA6B;AAAA,IACjC,gBAAgB,WAAW,4BAA4B;AAAA,IACvD,aAAa,oBAAoB,gBAAgB,oBAAoB,sBAAsB,SAAY,IAAI,IAAI,IAAI,gBAAgB;AAAA,IACnI,qBAAqB,wBAAwB,oBAAoB,mBAAmB;AAAA,IACpF,QAAQ,oBAAoB;AAAA,IAC5B,UAAU,oBAAoB;AAAA,IAC9B,YAAY,oBAAoB;AAAA,IAChC,mBAAmB;AAAA,EACrB;AAEA,QAAM,WAAW,IAAI,YAAY,WAAW,CAAC,KAAsB,SAAc,SAAwC;AACvH,QAAI,QAAQ,QAAQ;AACpB,QAAI,QAAQ,MAAM,WAAW,4BAA4B,EAAE,GAAG,KAAK;AACnE,SAAK,MAAM,OAAO;AAAA,EACpB,CAAC;AAED,WAAS,IAAI,QAAQ;AACrB,SAAO,SAAS,WAAW;AAC7B;","names":[]}
1
+ {"version":3,"sources":["../../src/express/SecurityHandler.ts"],"sourcesContent":["import type { NextFunction, Request, RequestHandler, Response } from 'express';\nimport passport from 'passport';\nimport { ExtractJwt, Strategy as JwtStrategy } from 'passport-jwt';\nimport type { SecretOrKeyProvider, StrategyOptionsWithRequest } from 'passport-jwt';\nimport type { Algorithm } from 'jsonwebtoken';\nimport { authError } from './AuthError';\nimport { ctx, Environment, HttpStatus, ifFalse } from '@thisisagile/easy';\nimport type { Scope, UseCase } from '@thisisagile/easy';\n\ntype EasySecretOrKeyProvider = (request: Request, rawJwtToken: any) => Promise<string | Buffer>;\n\nexport interface SecurityOptions {\n /** Configuration for verifying JWTs */\n jwtStrategyOptions?: {\n /** The secret (symmetric) or PEM-encoded public key (asymmetric) for verifying the token's signature.\n * REQUIRED unless secretOrKeyProvider is provided. Defaults to JWT_PUBLIC_KEY from the system environment. */\n secretOrKey?: string | Buffer;\n\n /** Should return a secret (symmetric) or PEM-encoded public key (asymmetric) for the given key and request combination.\n * REQUIRED unless secretOrKey is provided. Note it is up to the implementer to decode rawJwtToken. */\n secretOrKeyProvider?: EasySecretOrKeyProvider;\n\n /** If defined, the token issuer (iss) will be verified against this value. */\n issuer?: string;\n\n /** If defined, the token audience (aud) will be verified against this value. */\n audience?: string;\n\n /** If defined, the token algorithm (alg) must be in this list. */\n algorithms?: Algorithm[];\n };\n}\n\nexport const checkLabCoat = (): RequestHandler => (req, res, next) => next(ifFalse(Environment.Dev.equals(ctx.env.name), authError(HttpStatus.Forbidden)));\n\nexport const checkToken = (): RequestHandler => passport.authenticate('jwt', { session: false, failWithError: true });\n\nexport const checkScope =\n (scope: Scope): RequestHandler =>\n (req, res, next) =>\n next(ifFalse((req.user as any)?.scopes?.includes(scope.id), authError(HttpStatus.Forbidden)));\n\nexport const checkUseCase =\n (uc: UseCase): RequestHandler =>\n (req, res, next) =>\n next(ifFalse((req.user as any)?.usecases?.includes(uc.id), authError(HttpStatus.Forbidden)));\n\nconst wrapSecretOrKeyProvider = (p?: EasySecretOrKeyProvider): SecretOrKeyProvider | undefined =>\n p\n ? (request, rawJwtToken, done) =>\n p(request, rawJwtToken)\n .then(t => done(null, t))\n .catch(e => done(e))\n : undefined;\n\nexport const security = ({ jwtStrategyOptions }: SecurityOptions = {}): ((req: Request, res: Response, next: NextFunction) => void) => {\n jwtStrategyOptions ??= {};\n if ('secretOrKeyProvider' in jwtStrategyOptions) (jwtStrategyOptions as any).secretOrKeyProvider = wrapSecretOrKeyProvider(jwtStrategyOptions.secretOrKeyProvider);\n else if (!('secretOrKey' in jwtStrategyOptions)) jwtStrategyOptions.secretOrKey = ctx.env.get('tokenPublicKey') as string;\n\n const strategy =\n new JwtStrategy({\n jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),\n passReqToCallback: true,\n ...jwtStrategyOptions,\n } as StrategyOptionsWithRequest, (req: Request, payload: any, done: (err: any, user: any) => void) => {\n ctx.request.token = payload;\n ctx.request.jwt = ExtractJwt.fromAuthHeaderAsBearerToken()(req) ?? '';\n done(null, payload);\n });\n\n passport.use(strategy);\n return passport.initialize();\n};\n"],"mappings":"AACA,OAAO,cAAc;AACrB,SAAS,YAAY,YAAY,mBAAmB;AAGpD,SAAS,iBAAiB;AAC1B,SAAS,KAAK,aAAa,YAAY,eAAe;AA2B/C,MAAM,eAAe,MAAsB,CAAC,KAAK,KAAK,SAAS,KAAK,QAAQ,YAAY,IAAI,OAAO,IAAI,IAAI,IAAI,GAAG,UAAU,WAAW,SAAS,CAAC,CAAC;AAElJ,MAAM,aAAa,MAAsB,SAAS,aAAa,OAAO,EAAE,SAAS,OAAO,eAAe,KAAK,CAAC;AAE7G,MAAM,aACX,CAAC,UACD,CAAC,KAAK,KAAK,SACT,KAAK,QAAS,IAAI,MAAc,QAAQ,SAAS,MAAM,EAAE,GAAG,UAAU,WAAW,SAAS,CAAC,CAAC;AAEzF,MAAM,eACX,CAAC,OACD,CAAC,KAAK,KAAK,SACT,KAAK,QAAS,IAAI,MAAc,UAAU,SAAS,GAAG,EAAE,GAAG,UAAU,WAAW,SAAS,CAAC,CAAC;AAE/F,MAAM,0BAA0B,CAAC,MAC/B,IACI,CAAC,SAAS,aAAa,SACrB,EAAE,SAAS,WAAW,EACnB,KAAK,OAAK,KAAK,MAAM,CAAC,CAAC,EACvB,MAAM,OAAK,KAAK,CAAC,CAAC,IACvB;AAEC,MAAM,WAAW,CAAC,EAAE,mBAAmB,IAAqB,CAAC,MAAmE;AACrI,yBAAuB,CAAC;AACxB,MAAI,yBAAyB;AAAoB,IAAC,mBAA2B,sBAAsB,wBAAwB,mBAAmB,mBAAmB;AAAA,WACxJ,EAAE,iBAAiB;AAAqB,uBAAmB,cAAc,IAAI,IAAI,IAAI,gBAAgB;AAE9G,QAAM,WACJ,IAAI,YAAY;AAAA,IAChB,gBAAgB,WAAW,4BAA4B;AAAA,IACvD,mBAAmB;AAAA,IACnB,GAAG;AAAA,EACL,GAAiC,CAAC,KAAc,SAAc,SAAwC;AACpG,QAAI,QAAQ,QAAQ;AACpB,QAAI,QAAQ,MAAM,WAAW,4BAA4B,EAAE,GAAG,KAAK;AACnE,SAAK,MAAM,OAAO;AAAA,EACpB,CAAC;AAED,WAAS,IAAI,QAAQ;AACrB,SAAO,SAAS,WAAW;AAC7B;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thisisagile/easy-express",
3
- "version": "15.14.2",
3
+ "version": "15.14.4",
4
4
  "description": "Straightforward library for building domain-driven microservice architectures",
5
5
  "author": "Sander Hoogendoorn",
6
6
  "license": "MIT",
@@ -33,23 +33,23 @@
33
33
  "access": "public"
34
34
  },
35
35
  "devDependencies": {
36
- "@thisisagile/easy-test": "15.14.2",
36
+ "@thisisagile/easy-test": "15.14.4",
37
37
  "@types/cls-hooked": "^4.3.4",
38
38
  "@types/form-urlencoded": "^4.4.0",
39
39
  "@types/jsonwebtoken": "^9.0.2",
40
- "@types/passport": "^1.0.12",
41
- "@types/passport-jwt": "^3.0.8",
40
+ "@types/passport": "^1.0.16",
41
+ "@types/passport-jwt": "^4.0.1",
42
42
  "@types/uuid": "^9.0.2",
43
43
  "@types/validator": "^13.7.17"
44
44
  },
45
45
  "dependencies": {
46
- "@thisisagile/easy": "^15.14.2",
46
+ "@thisisagile/easy": "^15.14.4",
47
47
  "@types/express": "^4.17.21",
48
48
  "cls-hooked": "^4.2.2",
49
49
  "express": "^4.18.2",
50
50
  "form-urlencoded": "^6.1.0",
51
51
  "jsonwebtoken": "^9.0.0",
52
- "passport": "^0.6.0",
52
+ "passport": "^0.7.0",
53
53
  "passport-jwt": "^4.0.1"
54
54
  }
55
55
  }
@@ -1,10 +1,13 @@
1
- import express, { Request, RequestHandler } from 'express';
1
+ import type { NextFunction, Request, RequestHandler, Response } from 'express';
2
2
  import passport from 'passport';
3
- import passportJwt, { ExtractJwt, Strategy as JwtStrategy, StrategyOptions } from 'passport-jwt';
3
+ import { ExtractJwt, Strategy as JwtStrategy } from 'passport-jwt';
4
+ import type { SecretOrKeyProvider, StrategyOptionsWithRequest } from 'passport-jwt';
5
+ import type { Algorithm } from 'jsonwebtoken';
4
6
  import { authError } from './AuthError';
5
- import { ctx, Environment, HttpStatus, ifFalse, Scope, UseCase } from '@thisisagile/easy';
7
+ import { ctx, Environment, HttpStatus, ifFalse } from '@thisisagile/easy';
8
+ import type { Scope, UseCase } from '@thisisagile/easy';
6
9
 
7
- type SecretOrKeyProvider = (request: Request, rawJwtToken: any) => Promise<string | Buffer>;
10
+ type EasySecretOrKeyProvider = (request: Request, rawJwtToken: any) => Promise<string | Buffer>;
8
11
 
9
12
  export interface SecurityOptions {
10
13
  /** Configuration for verifying JWTs */
@@ -15,7 +18,7 @@ export interface SecurityOptions {
15
18
 
16
19
  /** Should return a secret (symmetric) or PEM-encoded public key (asymmetric) for the given key and request combination.
17
20
  * REQUIRED unless secretOrKey is provided. Note it is up to the implementer to decode rawJwtToken. */
18
- secretOrKeyProvider?: SecretOrKeyProvider;
21
+ secretOrKeyProvider?: EasySecretOrKeyProvider;
19
22
 
20
23
  /** If defined, the token issuer (iss) will be verified against this value. */
21
24
  issuer?: string;
@@ -24,7 +27,7 @@ export interface SecurityOptions {
24
27
  audience?: string;
25
28
 
26
29
  /** If defined, the token algorithm (alg) must be in this list. */
27
- algorithms?: string[];
30
+ algorithms?: Algorithm[];
28
31
  };
29
32
  }
30
33
 
@@ -42,7 +45,7 @@ export const checkUseCase =
42
45
  (req, res, next) =>
43
46
  next(ifFalse((req.user as any)?.usecases?.includes(uc.id), authError(HttpStatus.Forbidden)));
44
47
 
45
- const wrapSecretOrKeyProvider = (p?: SecretOrKeyProvider): passportJwt.SecretOrKeyProvider | undefined =>
48
+ const wrapSecretOrKeyProvider = (p?: EasySecretOrKeyProvider): SecretOrKeyProvider | undefined =>
46
49
  p
47
50
  ? (request, rawJwtToken, done) =>
48
51
  p(request, rawJwtToken)
@@ -50,18 +53,17 @@ const wrapSecretOrKeyProvider = (p?: SecretOrKeyProvider): passportJwt.SecretOrK
50
53
  .catch(e => done(e))
51
54
  : undefined;
52
55
 
53
- export const security = ({ jwtStrategyOptions }: SecurityOptions = {}): ((req: express.Request, res: express.Response, next: express.NextFunction) => void) => {
54
- const jwtConfig: StrategyOptions = {
56
+ export const security = ({ jwtStrategyOptions }: SecurityOptions = {}): ((req: Request, res: Response, next: NextFunction) => void) => {
57
+ jwtStrategyOptions ??= {};
58
+ if ('secretOrKeyProvider' in jwtStrategyOptions) (jwtStrategyOptions as any).secretOrKeyProvider = wrapSecretOrKeyProvider(jwtStrategyOptions.secretOrKeyProvider);
59
+ else if (!('secretOrKey' in jwtStrategyOptions)) jwtStrategyOptions.secretOrKey = ctx.env.get('tokenPublicKey') as string;
60
+
61
+ const strategy =
62
+ new JwtStrategy({
55
63
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
56
- secretOrKey: jwtStrategyOptions?.secretOrKey ?? (jwtStrategyOptions?.secretOrKeyProvider ? undefined : ctx.env.get('tokenPublicKey')),
57
- secretOrKeyProvider: wrapSecretOrKeyProvider(jwtStrategyOptions?.secretOrKeyProvider),
58
- issuer: jwtStrategyOptions?.issuer,
59
- audience: jwtStrategyOptions?.audience,
60
- algorithms: jwtStrategyOptions?.algorithms,
61
64
  passReqToCallback: true,
62
- };
63
-
64
- const strategy = new JwtStrategy(jwtConfig, (req: express.Request, payload: any, done: (err: any, user: any) => void) => {
65
+ ...jwtStrategyOptions,
66
+ } as StrategyOptionsWithRequest, (req: Request, payload: any, done: (err: any, user: any) => void) => {
65
67
  ctx.request.token = payload;
66
68
  ctx.request.jwt = ExtractJwt.fromAuthHeaderAsBearerToken()(req) ?? '';
67
69
  done(null, payload);