@moss-dev/moss-auth-guard 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.guard.d.ts +9 -0
- package/dist/auth.guard.js +69 -0
- package/dist/auth.guard.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/org-id.decorator.d.ts +4 -0
- package/dist/org-id.decorator.js +12 -0
- package/dist/org-id.decorator.js.map +1 -0
- package/dist/project-id.decorator.d.ts +4 -0
- package/dist/project-id.decorator.js +12 -0
- package/dist/project-id.decorator.js.map +1 -0
- package/dist/require-auth.decorator.d.ts +8 -0
- package/dist/require-auth.decorator.js +13 -0
- package/dist/require-auth.decorator.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from "@nestjs/common";
|
|
2
|
+
import { JwtService } from "@nestjs/jwt";
|
|
3
|
+
import { Reflector } from "@nestjs/core";
|
|
4
|
+
export declare class MossAuthGuard implements CanActivate {
|
|
5
|
+
private readonly jwtService;
|
|
6
|
+
private readonly reflector;
|
|
7
|
+
constructor(jwtService: JwtService, reflector: Reflector);
|
|
8
|
+
canActivate(ctx: ExecutionContext): boolean;
|
|
9
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MossAuthGuard = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const jwt_1 = require("@nestjs/jwt");
|
|
15
|
+
const core_1 = require("@nestjs/core");
|
|
16
|
+
const require_auth_decorator_js_1 = require("./require-auth.decorator.js");
|
|
17
|
+
const SCOPE_RANK = {
|
|
18
|
+
read: 1,
|
|
19
|
+
write: 2,
|
|
20
|
+
admin: 3,
|
|
21
|
+
};
|
|
22
|
+
let MossAuthGuard = class MossAuthGuard {
|
|
23
|
+
jwtService;
|
|
24
|
+
reflector;
|
|
25
|
+
constructor(jwtService, reflector) {
|
|
26
|
+
this.jwtService = jwtService;
|
|
27
|
+
this.reflector = reflector;
|
|
28
|
+
}
|
|
29
|
+
canActivate(ctx) {
|
|
30
|
+
const req = ctx.switchToHttp().getRequest();
|
|
31
|
+
const authHeader = req.headers["authorization"];
|
|
32
|
+
if (!authHeader?.startsWith("Bearer ")) {
|
|
33
|
+
throw new common_1.UnauthorizedException("Authorization header with Bearer token is required");
|
|
34
|
+
}
|
|
35
|
+
const token = authHeader.slice(7);
|
|
36
|
+
let payload;
|
|
37
|
+
try {
|
|
38
|
+
payload = this.jwtService.verify(token, {
|
|
39
|
+
algorithms: ["HS256"],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
throw new common_1.UnauthorizedException("Invalid or expired token");
|
|
44
|
+
}
|
|
45
|
+
if (typeof payload.sub !== "string" || !payload.sub) {
|
|
46
|
+
throw new common_1.UnauthorizedException("Invalid token payload");
|
|
47
|
+
}
|
|
48
|
+
req.projectId = payload.sub;
|
|
49
|
+
req.orgId = payload.org ?? "";
|
|
50
|
+
req.scope = payload.scope ?? "";
|
|
51
|
+
// Scope enforcement
|
|
52
|
+
const requiredScope = this.reflector.getAllAndOverride(require_auth_decorator_js_1.REQUIRE_AUTH_SCOPE, [ctx.getHandler(), ctx.getClass()]);
|
|
53
|
+
if (requiredScope && requiredScope !== true) {
|
|
54
|
+
const tokenScopeRank = SCOPE_RANK[payload.scope] ?? 0;
|
|
55
|
+
const requiredScopeRank = SCOPE_RANK[requiredScope] ?? 0;
|
|
56
|
+
if (tokenScopeRank < requiredScopeRank) {
|
|
57
|
+
throw new common_1.UnauthorizedException("Insufficient scope");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
exports.MossAuthGuard = MossAuthGuard;
|
|
64
|
+
exports.MossAuthGuard = MossAuthGuard = __decorate([
|
|
65
|
+
(0, common_1.Injectable)(),
|
|
66
|
+
__metadata("design:paramtypes", [jwt_1.JwtService,
|
|
67
|
+
core_1.Reflector])
|
|
68
|
+
], MossAuthGuard);
|
|
69
|
+
//# sourceMappingURL=auth.guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../src/auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AACxB,qCAAyC;AACzC,uCAAyC;AACzC,2EAGqC;AAQrC,MAAM,UAAU,GAA8B;IAC5C,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACT,CAAC;AAGK,IAAM,aAAa,GAAnB,MAAM,aAAa;IAEL;IACA;IAFnB,YACmB,UAAsB,EACtB,SAAoB;QADpB,eAAU,GAAV,UAAU,CAAY;QACtB,cAAS,GAAT,SAAS,CAAW;IACpC,CAAC;IAEJ,WAAW,CAAC,GAAqB;QAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAKrC,CAAC;QAEL,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,8BAAqB,CAC7B,oDAAoD,CACrD,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,OAAmB,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAa,KAAK,EAAE;gBAClD,UAAU,EAAE,CAAC,OAAO,CAAC;aACtB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,8BAAqB,CAAC,0BAA0B,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACpD,MAAM,IAAI,8BAAqB,CAAC,uBAAuB,CAAC,CAAC;QAC3D,CAAC;QAED,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;QAC5B,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;QAC9B,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QAEhC,oBAAoB;QACpB,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAEpD,8CAAkB,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAE1D,IAAI,aAAa,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC5C,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC,KAAkB,CAAC,IAAI,CAAC,CAAC;YACnE,MAAM,iBAAiB,GAAG,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,cAAc,GAAG,iBAAiB,EAAE,CAAC;gBACvC,MAAM,IAAI,8BAAqB,CAAC,oBAAoB,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAtDY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAGoB,gBAAU;QACX,gBAAS;GAH5B,aAAa,CAsDzB"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OrgId = exports.ProjectId = exports.REQUIRE_AUTH_SCOPE = exports.RequireAuth = exports.MossAuthGuard = void 0;
|
|
4
|
+
var auth_guard_js_1 = require("./auth.guard.js");
|
|
5
|
+
Object.defineProperty(exports, "MossAuthGuard", { enumerable: true, get: function () { return auth_guard_js_1.MossAuthGuard; } });
|
|
6
|
+
var require_auth_decorator_js_1 = require("./require-auth.decorator.js");
|
|
7
|
+
Object.defineProperty(exports, "RequireAuth", { enumerable: true, get: function () { return require_auth_decorator_js_1.RequireAuth; } });
|
|
8
|
+
Object.defineProperty(exports, "REQUIRE_AUTH_SCOPE", { enumerable: true, get: function () { return require_auth_decorator_js_1.REQUIRE_AUTH_SCOPE; } });
|
|
9
|
+
var project_id_decorator_js_1 = require("./project-id.decorator.js");
|
|
10
|
+
Object.defineProperty(exports, "ProjectId", { enumerable: true, get: function () { return project_id_decorator_js_1.ProjectId; } });
|
|
11
|
+
var org_id_decorator_js_1 = require("./org-id.decorator.js");
|
|
12
|
+
Object.defineProperty(exports, "OrgId", { enumerable: true, get: function () { return org_id_decorator_js_1.OrgId; } });
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,yEAIqC;AAHnC,wHAAA,WAAW,OAAA;AACX,+HAAA,kBAAkB,OAAA;AAGpB,qEAAsD;AAA7C,oHAAA,SAAS,OAAA;AAClB,6DAA8C;AAArC,4GAAA,KAAK,OAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OrgId = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
/**
|
|
6
|
+
* Extracts req.orgId — set by MossAuthGuard after successful JWT verification.
|
|
7
|
+
*/
|
|
8
|
+
exports.OrgId = (0, common_1.createParamDecorator)((_data, ctx) => {
|
|
9
|
+
const req = ctx.switchToHttp().getRequest();
|
|
10
|
+
return req.orgId;
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=org-id.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-id.decorator.js","sourceRoot":"","sources":["../src/org-id.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AAExE;;GAEG;AACU,QAAA,KAAK,GAAG,IAAA,6BAAoB,EACvC,CAAC,KAAc,EAAE,GAAqB,EAAU,EAAE;IAChD,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAqB,CAAC;IAC/D,OAAO,GAAG,CAAC,KAAK,CAAC;AACnB,CAAC,CACF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProjectId = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
/**
|
|
6
|
+
* Extracts req.projectId — set by MossAuthGuard after successful JWT verification.
|
|
7
|
+
*/
|
|
8
|
+
exports.ProjectId = (0, common_1.createParamDecorator)((_data, ctx) => {
|
|
9
|
+
const req = ctx.switchToHttp().getRequest();
|
|
10
|
+
return req.projectId;
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=project-id.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-id.decorator.js","sourceRoot":"","sources":["../src/project-id.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AAExE;;GAEG;AACU,QAAA,SAAS,GAAG,IAAA,6BAAoB,EAC3C,CAAC,KAAc,EAAE,GAAqB,EAAU,EAAE;IAChD,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAyB,CAAC;IACnE,OAAO,GAAG,CAAC,SAAS,CAAC;AACvB,CAAC,CACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type AuthScope = "read" | "write" | "admin";
|
|
2
|
+
export declare const REQUIRE_AUTH_SCOPE = "REQUIRE_AUTH_SCOPE";
|
|
3
|
+
/**
|
|
4
|
+
* Marks a route as requiring authentication.
|
|
5
|
+
* @param scope Optional minimum scope required. Defaults to any valid token.
|
|
6
|
+
* Hierarchy: admin ⊃ write ⊃ read
|
|
7
|
+
*/
|
|
8
|
+
export declare const RequireAuth: (scope?: AuthScope) => import("@nestjs/common").CustomDecorator<string>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequireAuth = exports.REQUIRE_AUTH_SCOPE = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.REQUIRE_AUTH_SCOPE = "REQUIRE_AUTH_SCOPE";
|
|
6
|
+
/**
|
|
7
|
+
* Marks a route as requiring authentication.
|
|
8
|
+
* @param scope Optional minimum scope required. Defaults to any valid token.
|
|
9
|
+
* Hierarchy: admin ⊃ write ⊃ read
|
|
10
|
+
*/
|
|
11
|
+
const RequireAuth = (scope) => (0, common_1.SetMetadata)(exports.REQUIRE_AUTH_SCOPE, scope ?? true);
|
|
12
|
+
exports.RequireAuth = RequireAuth;
|
|
13
|
+
//# sourceMappingURL=require-auth.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-auth.decorator.js","sourceRoot":"","sources":["../src/require-auth.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAA6C;AAGhC,QAAA,kBAAkB,GAAG,oBAAoB,CAAC;AAEvD;;;;GAIG;AACI,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAE,EAAE,CAC/C,IAAA,oBAAW,EAAC,0BAAkB,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC;AADpC,QAAA,WAAW,eACyB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@moss-dev/moss-auth-guard",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared NestJS auth guard and decorators for Moss microservices",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc -p tsconfig.json",
|
|
15
|
+
"test": "jest"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@nestjs/common": "^11.0.0",
|
|
19
|
+
"@nestjs/core": "^11.0.0",
|
|
20
|
+
"@nestjs/jwt": "^11.0.0",
|
|
21
|
+
"reflect-metadata": "^0.2.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@nestjs/common": "^11.0.0",
|
|
25
|
+
"@nestjs/core": "^11.0.0",
|
|
26
|
+
"@nestjs/jwt": "^11.0.0",
|
|
27
|
+
"@nestjs/testing": "^11.0.0",
|
|
28
|
+
"@types/jest": "^29.0.0",
|
|
29
|
+
"jest": "^29.0.0",
|
|
30
|
+
"reflect-metadata": "^0.2.0",
|
|
31
|
+
"rxjs": "^7.8.0",
|
|
32
|
+
"ts-jest": "^29.0.0",
|
|
33
|
+
"typescript": "^5.0.0"
|
|
34
|
+
},
|
|
35
|
+
"jest": {
|
|
36
|
+
"moduleFileExtensions": [
|
|
37
|
+
"js",
|
|
38
|
+
"json",
|
|
39
|
+
"ts"
|
|
40
|
+
],
|
|
41
|
+
"rootDir": "src",
|
|
42
|
+
"testRegex": ".*\\.spec\\.ts$",
|
|
43
|
+
"transform": {
|
|
44
|
+
"^.+\\.(t|j)s$": "ts-jest"
|
|
45
|
+
},
|
|
46
|
+
"moduleNameMapper": {
|
|
47
|
+
"^(\\.{1,2}/.*)\\.js$": "$1"
|
|
48
|
+
},
|
|
49
|
+
"testEnvironment": "node"
|
|
50
|
+
}
|
|
51
|
+
}
|