@volontariapp/auth 1.0.0 → 2.0.0-next.20260407092728
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/auth.module.d.ts.map +1 -1
- package/dist/auth.module.js +5 -1
- package/dist/auth.module.js.map +1 -1
- package/dist/guards/grpc-internal.guard.d.ts +1 -1
- package/dist/guards/grpc-internal.guard.d.ts.map +1 -1
- package/dist/guards/grpc-internal.guard.js +5 -1
- package/dist/guards/grpc-internal.guard.js.map +1 -1
- package/dist/interceptors/grpc-internal.interceptor.d.ts +1 -1
- package/dist/interceptors/grpc-internal.interceptor.d.ts.map +1 -1
- package/dist/interceptors/grpc-internal.interceptor.js +2 -1
- package/dist/interceptors/grpc-internal.interceptor.js.map +1 -1
- package/dist/interfaces/auth-config.interface.d.ts +5 -4
- package/dist/interfaces/auth-config.interface.d.ts.map +1 -1
- package/dist/interfaces/auth-user.interface.d.ts +1 -0
- package/dist/interfaces/auth-user.interface.d.ts.map +1 -1
- package/dist/services/jwt.service.d.ts +7 -2
- package/dist/services/jwt.service.d.ts.map +1 -1
- package/dist/services/jwt.service.js +72 -44
- package/dist/services/jwt.service.js.map +1 -1
- package/dist/test/example/test.controller.d.ts +11 -0
- package/dist/test/example/test.controller.d.ts.map +1 -0
- package/dist/test/example/test.controller.js +42 -0
- package/dist/test/example/test.controller.js.map +1 -0
- package/dist/test/factories/auth-user.factory.d.ts +3 -0
- package/dist/test/factories/auth-user.factory.d.ts.map +1 -0
- package/dist/test/factories/auth-user.factory.js +6 -0
- package/dist/test/factories/auth-user.factory.js.map +1 -0
- package/dist/test/helpers/context.helper.d.ts +4 -0
- package/dist/test/helpers/context.helper.d.ts.map +1 -0
- package/dist/test/helpers/context.helper.js +18 -0
- package/dist/test/helpers/context.helper.js.map +1 -0
- package/dist/test/integration/grpc-internal.guard.int.spec.d.ts +2 -0
- package/dist/test/integration/grpc-internal.guard.int.spec.d.ts.map +1 -0
- package/dist/test/integration/grpc-internal.guard.int.spec.js +81 -0
- package/dist/test/integration/grpc-internal.guard.int.spec.js.map +1 -0
- package/dist/test/setup.d.ts +2 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/test/setup.js +2 -0
- package/dist/test/setup.js.map +1 -0
- package/dist/test/unit/grpc-internal.guard.unit.spec.d.ts +2 -0
- package/dist/test/unit/grpc-internal.guard.unit.spec.d.ts.map +1 -0
- package/dist/test/unit/grpc-internal.guard.unit.spec.js +49 -0
- package/dist/test/unit/grpc-internal.guard.unit.spec.js.map +1 -0
- package/dist/test/unit/grpc-internal.interceptor.unit.spec.d.ts +2 -0
- package/dist/test/unit/grpc-internal.interceptor.unit.spec.d.ts.map +1 -0
- package/dist/test/unit/grpc-internal.interceptor.unit.spec.js +42 -0
- package/dist/test/unit/grpc-internal.interceptor.unit.spec.js.map +1 -0
- package/dist/test/unit/jwt.service.unit.spec.d.ts +2 -0
- package/dist/test/unit/jwt.service.unit.spec.d.ts.map +1 -0
- package/dist/test/unit/jwt.service.unit.spec.js +75 -0
- package/dist/test/unit/jwt.service.unit.spec.js.map +1 -0
- package/package.json +9 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,qBAEa,UAAU;IACrB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,aAAa;
|
|
1
|
+
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,qBAEa,UAAU;IACrB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,aAAa;CAkBpD"}
|
package/dist/auth.module.js
CHANGED
|
@@ -18,7 +18,11 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
18
18
|
provide: AUTH_OPTIONS,
|
|
19
19
|
useValue: options,
|
|
20
20
|
},
|
|
21
|
-
|
|
21
|
+
{
|
|
22
|
+
provide: JwtService,
|
|
23
|
+
useFactory: (opts) => new JwtService(opts),
|
|
24
|
+
inject: [AUTH_OPTIONS],
|
|
25
|
+
},
|
|
22
26
|
GrpcMetadataHelper,
|
|
23
27
|
],
|
|
24
28
|
exports: [JwtService, GrpcMetadataHelper],
|
package/dist/auth.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":";;;;;;;AACA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAIjE,IAAM,UAAU,kBAAhB,MAAM,UAAU;IACrB,MAAM,CAAC,QAAQ,CAAC,OAAmB;QACjC,OAAO;YACL,MAAM,EAAE,YAAU;YAClB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,YAAY;oBACrB,QAAQ,EAAE,OAAO;iBAClB;gBACD,UAAU;
|
|
1
|
+
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":";;;;;;;AACA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAIjE,IAAM,UAAU,kBAAhB,MAAM,UAAU;IACrB,MAAM,CAAC,QAAQ,CAAC,OAAmB;QACjC,OAAO;YACL,MAAM,EAAE,YAAU;YAClB,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,YAAY;oBACrB,QAAQ,EAAE,OAAO;iBAClB;gBACD;oBACE,OAAO,EAAE,UAAU;oBACnB,UAAU,EAAE,CAAC,IAAgB,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC;oBACtD,MAAM,EAAE,CAAC,YAAY,CAAC;iBACvB;gBACD,kBAAkB;aACnB;YACD,OAAO,EAAE,CAAC,UAAU,EAAE,kBAAkB,CAAC;SAC1C,CAAC;IACJ,CAAC;CACF,CAAA;AAnBY,UAAU;IAFtB,MAAM,EAAE;IACR,MAAM,CAAC,EAAE,CAAC;GACE,UAAU,CAmBtB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
-
import
|
|
2
|
+
import { JwtService } from '../services/jwt.service.js';
|
|
3
3
|
export declare class GrpcInternalGuard implements CanActivate {
|
|
4
4
|
private readonly jwtService;
|
|
5
5
|
private readonly logger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grpc-internal.guard.d.ts","sourceRoot":"","sources":["../../src/guards/grpc-internal.guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIpE,OAAO,
|
|
1
|
+
{"version":3,"file":"grpc-internal.guard.d.ts","sourceRoot":"","sources":["../../src/guards/grpc-internal.guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAGxD,qBACa,iBAAkB,YAAW,WAAW;IAGvC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;gBAEhC,UAAU,EAAE,UAAU;IAE7C,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAgC/D"}
|
|
@@ -10,6 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
var GrpcInternalGuard_1;
|
|
11
11
|
import { Injectable, Logger } from '@nestjs/common';
|
|
12
12
|
import { UnauthorizedError } from '@volontariapp/errors';
|
|
13
|
+
import { JwtService } from '../services/jwt.service.js';
|
|
13
14
|
import { INTERNAL_TOKEN_METADATA_KEY } from '../constants/index.js';
|
|
14
15
|
let GrpcInternalGuard = GrpcInternalGuard_1 = class GrpcInternalGuard {
|
|
15
16
|
jwtService;
|
|
@@ -29,6 +30,9 @@ let GrpcInternalGuard = GrpcInternalGuard_1 = class GrpcInternalGuard {
|
|
|
29
30
|
throw new UnauthorizedError('Missing internal token');
|
|
30
31
|
}
|
|
31
32
|
const token = tokens[0];
|
|
33
|
+
if (typeof token !== 'string') {
|
|
34
|
+
throw new UnauthorizedError('Invalid internal token format');
|
|
35
|
+
}
|
|
32
36
|
try {
|
|
33
37
|
const user = await this.jwtService.verifyInternal(token);
|
|
34
38
|
const rpcContext = rpcArgumentsHost.getContext();
|
|
@@ -44,7 +48,7 @@ let GrpcInternalGuard = GrpcInternalGuard_1 = class GrpcInternalGuard {
|
|
|
44
48
|
};
|
|
45
49
|
GrpcInternalGuard = GrpcInternalGuard_1 = __decorate([
|
|
46
50
|
Injectable(),
|
|
47
|
-
__metadata("design:paramtypes", [
|
|
51
|
+
__metadata("design:paramtypes", [JwtService])
|
|
48
52
|
], GrpcInternalGuard);
|
|
49
53
|
export { GrpcInternalGuard };
|
|
50
54
|
//# sourceMappingURL=grpc-internal.guard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grpc-internal.guard.js","sourceRoot":"","sources":["../../src/guards/grpc-internal.guard.ts"],"names":[],"mappings":";;;;;;;;;;AACA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"grpc-internal.guard.js","sourceRoot":"","sources":["../../src/guards/grpc-internal.guard.ts"],"names":[],"mappings":";;;;;;;;;;AACA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAG7D,IAAM,iBAAiB,yBAAvB,MAAM,iBAAiB;IAGC;IAFZ,MAAM,GAAG,IAAI,MAAM,CAAC,mBAAiB,CAAC,IAAI,CAAC,CAAC;IAE7D,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,IAAI,OAAO,CAAC,OAAO,EAAE,KAAK,KAAK,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,gBAAgB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,EAAY,CAAC;QACzD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QAEzD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,2BAA2B,cAAc,CAAC,CAAC;YACvE,MAAM,IAAI,iBAAiB,CAAC,wBAAwB,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,iBAAiB,CAAC,+BAA+B,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAEzD,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,EAA2B,CAAC;YAC1E,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC;YAEvB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACzE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;YACxD,MAAM,IAAI,iBAAiB,CAAC,wBAAwB,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;CACF,CAAA;AArCY,iBAAiB;IAD7B,UAAU,EAAE;qCAI8B,UAAU;GAHxC,iBAAiB,CAqC7B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
|
2
2
|
import type { Observable } from 'rxjs';
|
|
3
|
-
import
|
|
3
|
+
import { JwtService } from '../services/jwt.service.js';
|
|
4
4
|
export declare class GrpcInternalInterceptor implements NestInterceptor {
|
|
5
5
|
private readonly jwtService;
|
|
6
6
|
constructor(jwtService: JwtService);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grpc-internal.interceptor.d.ts","sourceRoot":"","sources":["../../src/interceptors/grpc-internal.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAErF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAGvC,OAAO,
|
|
1
|
+
{"version":3,"file":"grpc-internal.interceptor.d.ts","sourceRoot":"","sources":["../../src/interceptors/grpc-internal.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAErF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAGvC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAGxD,qBACa,uBAAwB,YAAW,eAAe;IACjD,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,UAAU;IAEnD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;CAc7E"}
|
|
@@ -10,6 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
import { Injectable } from '@nestjs/common';
|
|
11
11
|
import { from } from 'rxjs';
|
|
12
12
|
import { switchMap } from 'rxjs/operators';
|
|
13
|
+
import { JwtService } from '../services/jwt.service.js';
|
|
13
14
|
let GrpcInternalInterceptor = class GrpcInternalInterceptor {
|
|
14
15
|
jwtService;
|
|
15
16
|
constructor(jwtService) {
|
|
@@ -28,7 +29,7 @@ let GrpcInternalInterceptor = class GrpcInternalInterceptor {
|
|
|
28
29
|
};
|
|
29
30
|
GrpcInternalInterceptor = __decorate([
|
|
30
31
|
Injectable(),
|
|
31
|
-
__metadata("design:paramtypes", [
|
|
32
|
+
__metadata("design:paramtypes", [JwtService])
|
|
32
33
|
], GrpcInternalInterceptor);
|
|
33
34
|
export { GrpcInternalInterceptor };
|
|
34
35
|
//# sourceMappingURL=grpc-internal.interceptor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grpc-internal.interceptor.js","sourceRoot":"","sources":["../../src/interceptors/grpc-internal.interceptor.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"grpc-internal.interceptor.js","sourceRoot":"","sources":["../../src/interceptors/grpc-internal.interceptor.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAIjD,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IACL;IAA7B,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,SAAS,CAAC,OAAyB,EAAE,IAAiB;QACpD,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAuB,CAAC;QAC7E,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;QAE9B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC;QAED,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAClD,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE;YACnB,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;CACF,CAAA;AAjBY,uBAAuB;IADnC,UAAU,EAAE;qCAE8B,UAAU;GADxC,uBAAuB,CAiBnC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export interface AuthConfig {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
internalPrivateKeyPath?: string;
|
|
3
|
+
internalPublicKeyPath?: string;
|
|
4
|
+
gatewayPublicKeyPath?: string;
|
|
5
|
+
internalExpiresIn: number | string;
|
|
6
|
+
gatewayExpiresIn: number | string;
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=auth-config.interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-config.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/auth-config.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,
|
|
1
|
+
{"version":3,"file":"auth-config.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/auth-config.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC;CACnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-user.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/auth-user.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"auth-user.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/auth-user.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type { AuthConfig, AuthUser } from '../interfaces/index.js';
|
|
2
2
|
export declare class JwtService {
|
|
3
3
|
private readonly options;
|
|
4
|
-
private
|
|
5
|
-
private
|
|
4
|
+
private internalPrivateKey?;
|
|
5
|
+
private internalPublicKey?;
|
|
6
|
+
private gatewayPublicKey?;
|
|
6
7
|
constructor(options: AuthConfig);
|
|
8
|
+
private getInternalPrivateKey;
|
|
9
|
+
private getInternalPublicKey;
|
|
10
|
+
private getGatewayPublicKey;
|
|
7
11
|
signInternal(user: AuthUser): Promise<string>;
|
|
8
12
|
verifyInternal(token: string): Promise<AuthUser>;
|
|
9
13
|
verifyExternal(token: string): Promise<AuthUser>;
|
|
14
|
+
private isAuthUser;
|
|
10
15
|
}
|
|
11
16
|
//# sourceMappingURL=jwt.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.service.d.ts","sourceRoot":"","sources":["../../src/services/jwt.service.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEnE,
|
|
1
|
+
{"version":3,"file":"jwt.service.d.ts","sourceRoot":"","sources":["../../src/services/jwt.service.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEnE,qBAAa,UAAU;IAKT,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,kBAAkB,CAAC,CAAY;IACvC,OAAO,CAAC,iBAAiB,CAAC,CAAY;IACtC,OAAO,CAAC,gBAAgB,CAAC,CAAY;gBAER,OAAO,EAAE,UAAU;YASlC,qBAAqB;YAoBrB,oBAAoB;YAiBpB,mBAAmB;IAiB3B,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAa7C,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAShD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAStD,OAAO,CAAC,UAAU;CAInB"}
|
|
@@ -1,66 +1,94 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
-
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
-
};
|
|
13
|
-
import { Inject, Injectable } from '@nestjs/common';
|
|
14
1
|
import * as jose from 'jose';
|
|
2
|
+
import fs from 'node:fs';
|
|
15
3
|
import { InternalServerError } from '@volontariapp/errors';
|
|
16
|
-
|
|
17
|
-
let JwtService = class JwtService {
|
|
4
|
+
export class JwtService {
|
|
18
5
|
options;
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
internalPrivateKey;
|
|
7
|
+
internalPublicKey;
|
|
8
|
+
gatewayPublicKey;
|
|
21
9
|
constructor(options) {
|
|
22
10
|
this.options = options;
|
|
23
|
-
if (
|
|
24
|
-
throw new InternalServerError('Internal secret not configured', 'AUTH_CONFIG_ERROR');
|
|
25
|
-
}
|
|
26
|
-
if (!options.internalExpiresIn) {
|
|
11
|
+
if (options.internalExpiresIn === '' || options.internalExpiresIn === 0) {
|
|
27
12
|
throw new InternalServerError('Internal expiration time not configured', 'AUTH_CONFIG_ERROR');
|
|
28
13
|
}
|
|
29
|
-
if (
|
|
30
|
-
throw new InternalServerError('Gateway secret not configured', 'AUTH_CONFIG_ERROR');
|
|
31
|
-
}
|
|
32
|
-
if (!options.gatewayExpiresIn) {
|
|
14
|
+
if (options.gatewayExpiresIn === '' || options.gatewayExpiresIn === 0) {
|
|
33
15
|
throw new InternalServerError('Gateway expiration time not configured', 'AUTH_CONFIG_ERROR');
|
|
34
16
|
}
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
}
|
|
18
|
+
async getInternalPrivateKey() {
|
|
19
|
+
if (this.internalPrivateKey)
|
|
20
|
+
return this.internalPrivateKey;
|
|
21
|
+
if (this.options.internalPrivateKeyPath === undefined) {
|
|
22
|
+
throw new InternalServerError('Internal private key path not configured', 'AUTH_CONFIG_ERROR');
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const key = fs.readFileSync(this.options.internalPrivateKeyPath, 'utf8');
|
|
26
|
+
this.internalPrivateKey = await jose.importPKCS8(key, 'RS256');
|
|
27
|
+
return this.internalPrivateKey;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throw new InternalServerError(`Failed to import internal private key: ${error.message}`, 'AUTH_CONFIG_ERROR');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async getInternalPublicKey() {
|
|
34
|
+
if (this.internalPublicKey)
|
|
35
|
+
return this.internalPublicKey;
|
|
36
|
+
if (this.options.internalPublicKeyPath === undefined) {
|
|
37
|
+
throw new InternalServerError('Internal public key path not configured', 'AUTH_CONFIG_ERROR');
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const key = fs.readFileSync(this.options.internalPublicKeyPath, 'utf8');
|
|
41
|
+
this.internalPublicKey = await jose.importSPKI(key, 'RS256');
|
|
42
|
+
return this.internalPublicKey;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
throw new InternalServerError(`Failed to import internal public key: ${error.message}`, 'AUTH_CONFIG_ERROR');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async getGatewayPublicKey() {
|
|
49
|
+
if (this.gatewayPublicKey)
|
|
50
|
+
return this.gatewayPublicKey;
|
|
51
|
+
if (this.options.gatewayPublicKeyPath === undefined) {
|
|
52
|
+
throw new InternalServerError('Gateway public key path not configured', 'AUTH_CONFIG_ERROR');
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const key = fs.readFileSync(this.options.gatewayPublicKeyPath, 'utf8');
|
|
56
|
+
this.gatewayPublicKey = await jose.importSPKI(key, 'RS256');
|
|
57
|
+
return this.gatewayPublicKey;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new InternalServerError(`Failed to import gateway public key: ${error.message}`, 'AUTH_CONFIG_ERROR');
|
|
61
|
+
}
|
|
37
62
|
}
|
|
38
63
|
async signInternal(user) {
|
|
64
|
+
const key = await this.getInternalPrivateKey();
|
|
39
65
|
const sessionPayload = { ...user };
|
|
40
66
|
const token = await new jose.SignJWT(sessionPayload)
|
|
41
|
-
.setProtectedHeader({ alg: '
|
|
67
|
+
.setProtectedHeader({ alg: 'RS256' })
|
|
42
68
|
.setIssuedAt()
|
|
43
|
-
.setExpirationTime(this.options.internalExpiresIn
|
|
44
|
-
.sign(
|
|
69
|
+
.setExpirationTime(this.options.internalExpiresIn)
|
|
70
|
+
.sign(key);
|
|
45
71
|
return token;
|
|
46
72
|
}
|
|
47
73
|
async verifyInternal(token) {
|
|
48
|
-
const
|
|
49
|
-
|
|
74
|
+
const key = await this.getInternalPublicKey();
|
|
75
|
+
const { payload } = await jose.jwtVerify(token, key, { algorithms: ['RS256'] });
|
|
76
|
+
if (this.isAuthUser(payload)) {
|
|
77
|
+
return payload;
|
|
78
|
+
}
|
|
79
|
+
throw new InternalServerError('Invalid internal token payload', 'AUTH_TOKEN_ERROR');
|
|
50
80
|
}
|
|
51
81
|
async verifyExternal(token) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
82
|
+
const key = await this.getGatewayPublicKey();
|
|
83
|
+
const { payload } = await jose.jwtVerify(token, key, { algorithms: ['RS256'] });
|
|
84
|
+
if (this.isAuthUser(payload)) {
|
|
85
|
+
return payload;
|
|
55
86
|
}
|
|
56
|
-
|
|
57
|
-
|
|
87
|
+
throw new InternalServerError('Invalid external token payload', 'AUTH_TOKEN_ERROR');
|
|
88
|
+
}
|
|
89
|
+
isAuthUser(payload) {
|
|
90
|
+
const p = payload;
|
|
91
|
+
return typeof p['id'] === 'string' && typeof p['role'] === 'string';
|
|
58
92
|
}
|
|
59
|
-
}
|
|
60
|
-
JwtService = __decorate([
|
|
61
|
-
Injectable(),
|
|
62
|
-
__param(0, Inject(AUTH_OPTIONS)),
|
|
63
|
-
__metadata("design:paramtypes", [Object])
|
|
64
|
-
], JwtService);
|
|
65
|
-
export { JwtService };
|
|
93
|
+
}
|
|
66
94
|
//# sourceMappingURL=jwt.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.service.js","sourceRoot":"","sources":["../../src/services/jwt.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"jwt.service.js","sourceRoot":"","sources":["../../src/services/jwt.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AuthUser } from '../../interfaces/auth-user.interface.js';
|
|
2
|
+
export declare class AuthTestController {
|
|
3
|
+
getProtected(user: AuthUser): {
|
|
4
|
+
success: boolean;
|
|
5
|
+
user: AuthUser;
|
|
6
|
+
};
|
|
7
|
+
getPublic(): {
|
|
8
|
+
success: boolean;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=test.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.controller.d.ts","sourceRoot":"","sources":["../../../src/test/example/test.controller.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AAGxE,qBACa,kBAAkB;IAG7B,YAAY,CAAgB,IAAI,EAAE,QAAQ;;;;IAK1C,SAAS;;;CAGV"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Controller, Get, UseGuards } from '@nestjs/common';
|
|
14
|
+
import { GrpcInternalGuard } from '../../guards/grpc-internal.guard.js';
|
|
15
|
+
import { CurrentUser } from '../../decorators/current-user.decorator.js';
|
|
16
|
+
let AuthTestController = class AuthTestController {
|
|
17
|
+
getProtected(user) {
|
|
18
|
+
return { success: true, user };
|
|
19
|
+
}
|
|
20
|
+
getPublic() {
|
|
21
|
+
return { success: true };
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
__decorate([
|
|
25
|
+
Get('protected'),
|
|
26
|
+
UseGuards(GrpcInternalGuard),
|
|
27
|
+
__param(0, CurrentUser()),
|
|
28
|
+
__metadata("design:type", Function),
|
|
29
|
+
__metadata("design:paramtypes", [Object]),
|
|
30
|
+
__metadata("design:returntype", void 0)
|
|
31
|
+
], AuthTestController.prototype, "getProtected", null);
|
|
32
|
+
__decorate([
|
|
33
|
+
Get('public'),
|
|
34
|
+
__metadata("design:type", Function),
|
|
35
|
+
__metadata("design:paramtypes", []),
|
|
36
|
+
__metadata("design:returntype", void 0)
|
|
37
|
+
], AuthTestController.prototype, "getPublic", null);
|
|
38
|
+
AuthTestController = __decorate([
|
|
39
|
+
Controller('test')
|
|
40
|
+
], AuthTestController);
|
|
41
|
+
export { AuthTestController };
|
|
42
|
+
//# sourceMappingURL=test.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.controller.js","sourceRoot":"","sources":["../../../src/test/example/test.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAExE,OAAO,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAGlE,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAG7B,YAAY,CAAgB,IAAc;QACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;IAGD,SAAS;QACP,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;CACF,CAAA;AARC;IAFC,GAAG,CAAC,WAAW,CAAC;IAChB,SAAS,CAAC,iBAAiB,CAAC;IACf,WAAA,WAAW,EAAE,CAAA;;;;sDAE1B;AAGD;IADC,GAAG,CAAC,QAAQ,CAAC;;;;mDAGb;AAVU,kBAAkB;IAD9B,UAAU,CAAC,MAAM,CAAC;GACN,kBAAkB,CAW9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-user.factory.d.ts","sourceRoot":"","sources":["../../../src/test/factories/auth-user.factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AAExE,eAAO,MAAM,cAAc,eAAgB,OAAO,CAAC,QAAQ,CAAC,KAAG,QAI7D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-user.factory.js","sourceRoot":"","sources":["../../../src/test/factories/auth-user.factory.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,SAA6B,EAAY,EAAE,CAAC,CAAC;IAC1E,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,WAAW;IACjB,GAAG,SAAS;CACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import type { AuthUser } from '../../interfaces/auth-user.interface.js';
|
|
3
|
+
export declare const createExecutionContext: (metadataValues?: Record<string, string[]>, user?: AuthUser) => ExecutionContext;
|
|
4
|
+
//# sourceMappingURL=context.helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.helper.d.ts","sourceRoot":"","sources":["../../../src/test/helpers/context.helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yCAAyC,CAAC;AAExE,eAAO,MAAM,sBAAsB,oBACjB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,SACjC,QAAQ,KACd,gBAiBF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { createMock } from '@golevelup/ts-jest';
|
|
3
|
+
export const createExecutionContext = (metadataValues = {}, user) => {
|
|
4
|
+
const metadataMock = createMock({
|
|
5
|
+
get: jest.fn((key) => metadataValues[key] ?? []),
|
|
6
|
+
set: jest.fn(),
|
|
7
|
+
});
|
|
8
|
+
const rpcContext = { user };
|
|
9
|
+
const rpcArgumentsHost = createMock();
|
|
10
|
+
rpcArgumentsHost.getContext.mockImplementation((key) => {
|
|
11
|
+
return key === 'metadata' || key === undefined ? metadataMock : rpcContext;
|
|
12
|
+
});
|
|
13
|
+
return createMock({
|
|
14
|
+
getType: () => 'rpc',
|
|
15
|
+
switchToRpc: () => rpcArgumentsHost,
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=context.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.helper.js","sourceRoot":"","sources":["../../../src/test/helpers/context.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIhD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,iBAA2C,EAAE,EAC7C,IAAe,EACG,EAAE;IACpB,MAAM,YAAY,GAAG,UAAU,CAAW;QACxC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACxD,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE;KACf,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,CAAC;IAE5B,MAAM,gBAAgB,GAAG,UAAU,EAA+C,CAAC;IACnF,gBAAgB,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC,GAAY,EAAW,EAAE;QACvE,OAAO,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAmB;QAClC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK;QACpB,WAAW,EAAE,GAAG,EAAE,CAAC,gBAAgB;KACpC,CAAC,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc-internal.guard.int.spec.d.ts","sourceRoot":"","sources":["../../../src/test/integration/grpc-internal.guard.int.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, beforeAll, jest } from '@jest/globals';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import * as jose from 'jose';
|
|
4
|
+
import { Test } from '@nestjs/testing';
|
|
5
|
+
import { GrpcInternalGuard } from '../../guards/grpc-internal.guard.js';
|
|
6
|
+
import { JwtService } from '../../services/jwt.service.js';
|
|
7
|
+
import { AUTH_OPTIONS } from '../../constants/index.js';
|
|
8
|
+
import { createAuthUser } from '../factories/auth-user.factory.js';
|
|
9
|
+
import { createExecutionContext } from '../helpers/context.helper.js';
|
|
10
|
+
import { UnauthorizedError } from '@volontariapp/errors';
|
|
11
|
+
import { INTERNAL_TOKEN_METADATA_KEY } from '../../constants/index.js';
|
|
12
|
+
describe('GrpcInternalGuard (Integration)', () => {
|
|
13
|
+
let guard;
|
|
14
|
+
let jwtService;
|
|
15
|
+
let internalPrivate;
|
|
16
|
+
let internalPublic;
|
|
17
|
+
let gatewayPublic;
|
|
18
|
+
const config = {
|
|
19
|
+
internalPrivateKeyPath: 'internal-private-path',
|
|
20
|
+
internalPublicKeyPath: 'internal-public-path',
|
|
21
|
+
gatewayPublicKeyPath: 'gateway-public-path',
|
|
22
|
+
internalExpiresIn: '1h',
|
|
23
|
+
gatewayExpiresIn: '1h',
|
|
24
|
+
};
|
|
25
|
+
beforeAll(async () => {
|
|
26
|
+
const internalKeys = await jose.generateKeyPair('RS256', { extractable: true });
|
|
27
|
+
internalPrivate = await jose.exportPKCS8(internalKeys.privateKey);
|
|
28
|
+
internalPublic = await jose.exportSPKI(internalKeys.publicKey);
|
|
29
|
+
const gatewayKeys = await jose.generateKeyPair('RS256', { extractable: true });
|
|
30
|
+
gatewayPublic = await jose.exportSPKI(gatewayKeys.publicKey);
|
|
31
|
+
});
|
|
32
|
+
beforeEach(async () => {
|
|
33
|
+
jest.restoreAllMocks();
|
|
34
|
+
jest.spyOn(fs, 'readFileSync').mockImplementation((path) => {
|
|
35
|
+
if (path === 'internal-private-path')
|
|
36
|
+
return internalPrivate;
|
|
37
|
+
if (path === 'internal-public-path')
|
|
38
|
+
return internalPublic;
|
|
39
|
+
if (path === 'gateway-public-path')
|
|
40
|
+
return gatewayPublic;
|
|
41
|
+
throw new Error('File not found');
|
|
42
|
+
});
|
|
43
|
+
const module = await Test.createTestingModule({
|
|
44
|
+
providers: [
|
|
45
|
+
GrpcInternalGuard,
|
|
46
|
+
{
|
|
47
|
+
provide: JwtService,
|
|
48
|
+
useFactory: (opts) => new JwtService(opts),
|
|
49
|
+
inject: [AUTH_OPTIONS],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
provide: AUTH_OPTIONS,
|
|
53
|
+
useValue: config,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
}).compile();
|
|
57
|
+
guard = module.get(GrpcInternalGuard);
|
|
58
|
+
jwtService = module.get(JwtService);
|
|
59
|
+
});
|
|
60
|
+
it('should allow access with a valid internal token', async () => {
|
|
61
|
+
const user = createAuthUser();
|
|
62
|
+
const token = await jwtService.signInternal(user);
|
|
63
|
+
const context = createExecutionContext({
|
|
64
|
+
[INTERNAL_TOKEN_METADATA_KEY]: [token],
|
|
65
|
+
});
|
|
66
|
+
const canActivate = await guard.canActivate(context);
|
|
67
|
+
expect(canActivate).toBe(true);
|
|
68
|
+
const rpcContext = context.switchToRpc().getContext();
|
|
69
|
+
expect(rpcContext.user).toEqual(expect.objectContaining({
|
|
70
|
+
id: user.id,
|
|
71
|
+
role: user.role,
|
|
72
|
+
}));
|
|
73
|
+
});
|
|
74
|
+
it('should deny access with an invalid token', async () => {
|
|
75
|
+
const context = createExecutionContext({
|
|
76
|
+
[INTERNAL_TOKEN_METADATA_KEY]: ['invalid-token'],
|
|
77
|
+
});
|
|
78
|
+
await expect(guard.canActivate(context)).rejects.toThrow(UnauthorizedError);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=grpc-internal.guard.int.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc-internal.guard.int.spec.js","sourceRoot":"","sources":["../../../src/test/integration/grpc-internal.guard.int.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc-internal.guard.unit.spec.d.ts","sourceRoot":"","sources":["../../../src/test/unit/grpc-internal.guard.unit.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
|
2
|
+
import { GrpcInternalGuard } from '../../guards/grpc-internal.guard.js';
|
|
3
|
+
import { createAuthUser } from '../factories/auth-user.factory.js';
|
|
4
|
+
import { createExecutionContext } from '../helpers/context.helper.js';
|
|
5
|
+
import { createMock } from '@golevelup/ts-jest';
|
|
6
|
+
import { INTERNAL_TOKEN_METADATA_KEY } from '../../constants/index.js';
|
|
7
|
+
import { UnauthorizedError } from '@volontariapp/errors';
|
|
8
|
+
describe('GrpcInternalGuard (Unit)', () => {
|
|
9
|
+
let guard;
|
|
10
|
+
let jwtService;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
jest.restoreAllMocks();
|
|
13
|
+
jwtService = createMock();
|
|
14
|
+
guard = new GrpcInternalGuard(jwtService);
|
|
15
|
+
});
|
|
16
|
+
it('should return true if context is not rpc', async () => {
|
|
17
|
+
const context = createMock();
|
|
18
|
+
context.getType.mockReturnValue('http');
|
|
19
|
+
const result = await guard.canActivate(context);
|
|
20
|
+
expect(result).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
it('should throw UnauthorizedError if metadata is missing internal token', async () => {
|
|
23
|
+
const context = createExecutionContext({});
|
|
24
|
+
await expect(guard.canActivate(context)).rejects.toThrow(UnauthorizedError);
|
|
25
|
+
});
|
|
26
|
+
it('should throw UnauthorizedError if token is invalid', async () => {
|
|
27
|
+
const context = createExecutionContext({
|
|
28
|
+
[INTERNAL_TOKEN_METADATA_KEY]: ['invalid-token'],
|
|
29
|
+
});
|
|
30
|
+
const verifySpy = jest
|
|
31
|
+
.spyOn(jwtService, 'verifyInternal')
|
|
32
|
+
.mockRejectedValue(new Error('Invalid'));
|
|
33
|
+
await expect(guard.canActivate(context)).rejects.toThrow(UnauthorizedError);
|
|
34
|
+
expect(verifySpy).toHaveBeenCalledWith('invalid-token');
|
|
35
|
+
});
|
|
36
|
+
it('should set user in context and return true for valid token', async () => {
|
|
37
|
+
const user = createAuthUser();
|
|
38
|
+
const context = createExecutionContext({
|
|
39
|
+
[INTERNAL_TOKEN_METADATA_KEY]: ['valid-token'],
|
|
40
|
+
});
|
|
41
|
+
const verifySpy = jest.spyOn(jwtService, 'verifyInternal').mockResolvedValue(user);
|
|
42
|
+
const result = await guard.canActivate(context);
|
|
43
|
+
expect(result).toBe(true);
|
|
44
|
+
const rpcContext = context.switchToRpc().getContext();
|
|
45
|
+
expect(rpcContext.user).toEqual(user);
|
|
46
|
+
expect(verifySpy).toHaveBeenCalledWith('valid-token');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=grpc-internal.guard.unit.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc-internal.guard.unit.spec.js","sourceRoot":"","sources":["../../../src/test/unit/grpc-internal.guard.unit.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc-internal.interceptor.unit.spec.d.ts","sourceRoot":"","sources":["../../../src/test/unit/grpc-internal.interceptor.unit.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
|
2
|
+
import { GrpcInternalInterceptor } from '../../interceptors/grpc-internal.interceptor.js';
|
|
3
|
+
import { createAuthUser } from '../factories/auth-user.factory.js';
|
|
4
|
+
import { createMock } from '@golevelup/ts-jest';
|
|
5
|
+
import { of } from 'rxjs';
|
|
6
|
+
describe('GrpcInternalInterceptor (Unit)', () => {
|
|
7
|
+
let interceptor;
|
|
8
|
+
let jwtService;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
jest.restoreAllMocks();
|
|
11
|
+
jwtService = createMock();
|
|
12
|
+
interceptor = new GrpcInternalInterceptor(jwtService);
|
|
13
|
+
});
|
|
14
|
+
it('should call next.handle() if user is not in request', (done) => {
|
|
15
|
+
const context = createMock();
|
|
16
|
+
const httpHost = context.switchToHttp();
|
|
17
|
+
jest.spyOn(httpHost, 'getRequest').mockReturnValue({});
|
|
18
|
+
const next = createMock();
|
|
19
|
+
next.handle.mockReturnValue(of({ success: true }));
|
|
20
|
+
const signSpy = jest.spyOn(jwtService, 'signInternal');
|
|
21
|
+
interceptor.intercept(context, next).subscribe((result) => {
|
|
22
|
+
expect(result).toEqual({ success: true });
|
|
23
|
+
expect(signSpy).not.toHaveBeenCalled();
|
|
24
|
+
done();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
it('should sign internal token if user is present', (done) => {
|
|
28
|
+
const user = createAuthUser();
|
|
29
|
+
const context = createMock();
|
|
30
|
+
const httpHost = context.switchToHttp();
|
|
31
|
+
jest.spyOn(httpHost, 'getRequest').mockReturnValue({ user });
|
|
32
|
+
const next = createMock();
|
|
33
|
+
next.handle.mockReturnValue(of({ success: true }));
|
|
34
|
+
const signSpy = jest.spyOn(jwtService, 'signInternal').mockResolvedValue('signed-token');
|
|
35
|
+
interceptor.intercept(context, next).subscribe((result) => {
|
|
36
|
+
expect(result).toEqual({ success: true });
|
|
37
|
+
expect(signSpy).toHaveBeenCalledWith(user);
|
|
38
|
+
done();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=grpc-internal.interceptor.unit.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc-internal.interceptor.unit.spec.js","sourceRoot":"","sources":["../../../src/test/unit/grpc-internal.interceptor.unit.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,iDAAiD,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAE1B,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,IAAI,WAAoC,CAAC;IACzC,IAAI,UAAsB,CAAC;IAE3B,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,UAAU,GAAG,UAAU,EAAc,CAAC;QACtC,WAAW,GAAG,IAAI,uBAAuB,CAAC,UAAU,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,CAAC,IAAI,EAAE,EAAE;QACjE,MAAM,OAAO,GAAG,UAAU,EAAoB,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAG,UAAU,EAAe,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QAEvD,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE;YACxD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YACvC,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,CAAC,IAAI,EAAE,EAAE;QAC3D,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,UAAU,EAAoB,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7D,MAAM,IAAI,GAAG,UAAU,EAAe,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAEzF,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE;YACxD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.service.unit.spec.d.ts","sourceRoot":"","sources":["../../../src/test/unit/jwt.service.unit.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, beforeAll, jest } from '@jest/globals';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import * as jose from 'jose';
|
|
4
|
+
import { JwtService } from '../../services/jwt.service.js';
|
|
5
|
+
import { createAuthUser } from '../factories/auth-user.factory.js';
|
|
6
|
+
describe('JwtService (Unit)', () => {
|
|
7
|
+
let jwtService;
|
|
8
|
+
let internalPrivate;
|
|
9
|
+
let internalPublic;
|
|
10
|
+
let gatewayPrivate;
|
|
11
|
+
let gatewayPublic;
|
|
12
|
+
const config = {
|
|
13
|
+
internalPrivateKeyPath: 'internal-private-path',
|
|
14
|
+
internalPublicKeyPath: 'internal-public-path',
|
|
15
|
+
gatewayPublicKeyPath: 'gateway-public-path',
|
|
16
|
+
internalExpiresIn: '1h',
|
|
17
|
+
gatewayExpiresIn: '1h',
|
|
18
|
+
};
|
|
19
|
+
beforeAll(async () => {
|
|
20
|
+
const internalKeys = await jose.generateKeyPair('RS256', { extractable: true });
|
|
21
|
+
internalPrivate = await jose.exportPKCS8(internalKeys.privateKey);
|
|
22
|
+
internalPublic = await jose.exportSPKI(internalKeys.publicKey);
|
|
23
|
+
const gatewayKeys = await jose.generateKeyPair('RS256', { extractable: true });
|
|
24
|
+
gatewayPublic = await jose.exportSPKI(gatewayKeys.publicKey);
|
|
25
|
+
gatewayPrivate = await jose.exportPKCS8(gatewayKeys.privateKey);
|
|
26
|
+
});
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
jest.restoreAllMocks();
|
|
29
|
+
jest.spyOn(fs, 'readFileSync').mockImplementation((path) => {
|
|
30
|
+
if (path === 'internal-private-path')
|
|
31
|
+
return internalPrivate;
|
|
32
|
+
if (path === 'internal-public-path')
|
|
33
|
+
return internalPublic;
|
|
34
|
+
if (path === 'gateway-public-path')
|
|
35
|
+
return gatewayPublic;
|
|
36
|
+
if (path === 'gateway-private-path')
|
|
37
|
+
return gatewayPrivate;
|
|
38
|
+
throw new Error('File not found');
|
|
39
|
+
});
|
|
40
|
+
jwtService = new JwtService(config);
|
|
41
|
+
});
|
|
42
|
+
describe('signInternal', () => {
|
|
43
|
+
it('should sign a token with the internal private key', async () => {
|
|
44
|
+
const user = createAuthUser();
|
|
45
|
+
const token = await jwtService.signInternal(user);
|
|
46
|
+
expect(typeof token).toBe('string');
|
|
47
|
+
expect(token.length).toBeGreaterThan(0);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('verifyInternal', () => {
|
|
51
|
+
it('should verify a valid internal token', async () => {
|
|
52
|
+
const user = createAuthUser();
|
|
53
|
+
const token = await jwtService.signInternal(user);
|
|
54
|
+
const payload = await jwtService.verifyInternal(token);
|
|
55
|
+
expect(payload.id).toBe(user.id);
|
|
56
|
+
expect(payload.role).toBe(user.role);
|
|
57
|
+
});
|
|
58
|
+
it('should throw when token is invalid', async () => {
|
|
59
|
+
await expect(jwtService.verifyInternal('invalid-token')).rejects.toThrow();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('verifyExternal', () => {
|
|
63
|
+
it('should verify a valid external token', async () => {
|
|
64
|
+
const user = createAuthUser();
|
|
65
|
+
const gatewaySvc = new JwtService({
|
|
66
|
+
...config,
|
|
67
|
+
internalPrivateKeyPath: 'gateway-private-path',
|
|
68
|
+
});
|
|
69
|
+
const token = await gatewaySvc.signInternal(user);
|
|
70
|
+
const payload = await jwtService.verifyExternal(token);
|
|
71
|
+
expect(payload.id).toBe(user.id);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=jwt.service.unit.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.service.unit.spec.js","sourceRoot":"","sources":["../../../src/test/unit/jwt.service.unit.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volontariapp/auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-next.20260407092728",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"provenance": true
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"prepublishOnly": "yarn build",
|
|
31
31
|
"build": "tsc -p tsconfig.json",
|
|
32
32
|
"lint": "eslint src/",
|
|
33
|
-
"test": "
|
|
33
|
+
"test": "node --experimental-vm-modules $(yarn bin jest)",
|
|
34
|
+
"test:watch": "node --experimental-vm-modules $(yarn bin jest) --watch"
|
|
34
35
|
},
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"@volontariapp/errors": "0.2.0",
|
|
@@ -45,11 +46,17 @@
|
|
|
45
46
|
"@nestjs/microservices": "^10.0.0 || ^11.0.0"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
49
|
+
"@golevelup/ts-jest": "^0.6.1",
|
|
48
50
|
"@grpc/grpc-js": "^1.12.0",
|
|
51
|
+
"@jest/globals": "^30.3.0",
|
|
49
52
|
"@nestjs/common": "^11.0.0",
|
|
50
53
|
"@nestjs/core": "^11.0.0",
|
|
51
54
|
"@nestjs/microservices": "^11.0.0",
|
|
55
|
+
"@nestjs/testing": "^11.0.1",
|
|
56
|
+
"@types/jest": "^30.0.0",
|
|
52
57
|
"@types/node": "^24.1.0",
|
|
58
|
+
"jest": "^30.3.0",
|
|
59
|
+
"ts-jest": "^29.4.6",
|
|
53
60
|
"typescript": "5.7.3"
|
|
54
61
|
}
|
|
55
62
|
}
|