@tekcify/auth-backend 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -12
- package/{src/express/index.ts → dist/express/index.d.ts} +1 -0
- package/dist/express/index.d.ts.map +1 -0
- package/dist/express/index.js +6 -0
- package/dist/express/index.js.map +1 -0
- package/dist/express/middleware.d.ts +16 -0
- package/dist/express/middleware.d.ts.map +1 -0
- package/dist/express/middleware.js +39 -0
- package/dist/express/middleware.js.map +1 -0
- package/{src/index.ts → dist/index.d.ts} +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/nestjs/decorator.d.ts +2 -0
- package/dist/nestjs/decorator.d.ts.map +1 -0
- package/dist/nestjs/decorator.js +11 -0
- package/dist/nestjs/decorator.js.map +1 -0
- package/dist/nestjs/guard.d.ts +13 -0
- package/dist/nestjs/guard.d.ts.map +1 -0
- package/dist/nestjs/guard.js +56 -0
- package/dist/nestjs/guard.js.map +1 -0
- package/{src/nestjs/index.ts → dist/nestjs/index.d.ts} +1 -0
- package/dist/nestjs/index.d.ts.map +1 -0
- package/dist/nestjs/index.js +8 -0
- package/dist/nestjs/index.js.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/userinfo.d.ts +9 -0
- package/dist/userinfo.d.ts.map +1 -0
- package/dist/userinfo.js +16 -0
- package/dist/userinfo.js.map +1 -0
- package/dist/verify.d.ts +4 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +38 -0
- package/dist/verify.js.map +1 -0
- package/package.json +13 -10
- package/src/__tests__/verify.test.ts +0 -80
- package/src/express/middleware.ts +0 -61
- package/src/nestjs/decorator.ts +0 -12
- package/src/nestjs/guard.ts +0 -57
- package/src/types.ts +0 -24
- package/src/userinfo.ts +0 -26
- package/src/verify.ts +0 -36
- package/tsconfig.json +0 -11
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -9
package/README.md
CHANGED
|
@@ -28,9 +28,10 @@ You need the JWT access secret from your Tekcify Auth server. This should match
|
|
|
28
28
|
|
|
29
29
|
```env
|
|
30
30
|
JWT_ACCESS_SECRET=your-jwt-access-secret-here
|
|
31
|
-
AUTH_SERVER_URL=http://localhost:7001
|
|
32
31
|
```
|
|
33
32
|
|
|
33
|
+
**Note:** The auth server URL is centralized in `@tekcify/auth-core-client` package as `AUTH_SERVER_URL` (default: `http://localhost:7002`). Functions that communicate with the auth server use this constant automatically.
|
|
34
|
+
|
|
34
35
|
## NestJS Integration
|
|
35
36
|
|
|
36
37
|
### Step 1: Install Dependencies
|
|
@@ -255,7 +256,7 @@ import { introspectToken } from '@tekcify/auth-core-client';
|
|
|
255
256
|
|
|
256
257
|
const token = req.headers.authorization?.replace('Bearer ', '');
|
|
257
258
|
|
|
258
|
-
const result = await introspectToken(
|
|
259
|
+
const result = await introspectToken({
|
|
259
260
|
token: token!,
|
|
260
261
|
clientId: process.env.CLIENT_ID,
|
|
261
262
|
clientSecret: process.env.CLIENT_SECRET,
|
|
@@ -277,10 +278,7 @@ Fetch user information from the auth server:
|
|
|
277
278
|
```typescript
|
|
278
279
|
import { fetchUserInfo } from '@tekcify/auth-backend';
|
|
279
280
|
|
|
280
|
-
const userInfo = await fetchUserInfo(
|
|
281
|
-
process.env.AUTH_SERVER_URL!,
|
|
282
|
-
accessToken
|
|
283
|
-
);
|
|
281
|
+
const userInfo = await fetchUserInfo(accessToken);
|
|
284
282
|
|
|
285
283
|
console.log('Email:', userInfo.email);
|
|
286
284
|
console.log('Name:', userInfo.name);
|
|
@@ -426,15 +424,12 @@ verifyAccessToken(token: string, {
|
|
|
426
424
|
}): VerifiedToken
|
|
427
425
|
```
|
|
428
426
|
|
|
429
|
-
#### `fetchUserInfo(
|
|
427
|
+
#### `fetchUserInfo(accessToken)`
|
|
430
428
|
|
|
431
|
-
Fetches user information from the auth server
|
|
429
|
+
Fetches user information from the Tekcify auth server using the centralized `AUTH_SERVER_URL`.
|
|
432
430
|
|
|
433
431
|
```typescript
|
|
434
|
-
fetchUserInfo(
|
|
435
|
-
authServerUrl: string,
|
|
436
|
-
accessToken: string
|
|
437
|
-
): Promise<UserInfo>
|
|
432
|
+
fetchUserInfo(accessToken: string): Promise<UserInfo>
|
|
438
433
|
```
|
|
439
434
|
|
|
440
435
|
### Types
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAuthMiddleware = void 0;
|
|
4
|
+
var middleware_1 = require("./middleware");
|
|
5
|
+
Object.defineProperty(exports, "createAuthMiddleware", { enumerable: true, get: function () { return middleware_1.createAuthMiddleware; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":";;;AAAA,2CAAoD;AAA3C,kHAAA,oBAAoB,OAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import type { VerifyTokenOptions, UserPayload } from '../types';
|
|
3
|
+
export interface ExpressAuthOptions extends VerifyTokenOptions {
|
|
4
|
+
getUserInfo?: (userId: string) => Promise<{
|
|
5
|
+
email: string;
|
|
6
|
+
} | null>;
|
|
7
|
+
}
|
|
8
|
+
declare global {
|
|
9
|
+
namespace Express {
|
|
10
|
+
interface Request {
|
|
11
|
+
user?: UserPayload;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export declare function createAuthMiddleware(options: ExpressAuthOptions): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
16
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/express/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEhE,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CACrE;AAED,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,WAAW,CAAC;SACpB;KACF;CACF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,IAE5D,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAAC,CAsCjB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAuthMiddleware = createAuthMiddleware;
|
|
4
|
+
const verify_1 = require("../verify");
|
|
5
|
+
function createAuthMiddleware(options) {
|
|
6
|
+
return async (req, res, next) => {
|
|
7
|
+
const authHeader = req.headers.authorization;
|
|
8
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
9
|
+
res
|
|
10
|
+
.status(401)
|
|
11
|
+
.json({ message: 'Missing or invalid authorization header' });
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const token = authHeader.substring(7);
|
|
15
|
+
const verified = (0, verify_1.verifyAccessToken)(token, options);
|
|
16
|
+
if (!verified.valid) {
|
|
17
|
+
res.status(401).json({ message: 'Invalid or expired token' });
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
let email = '';
|
|
21
|
+
if (options.getUserInfo) {
|
|
22
|
+
const userInfo = await options.getUserInfo(verified.payload.sub);
|
|
23
|
+
if (!userInfo) {
|
|
24
|
+
res.status(401).json({ message: 'User not found' });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
email = userInfo.email;
|
|
28
|
+
}
|
|
29
|
+
req.user = {
|
|
30
|
+
userId: verified.payload.sub,
|
|
31
|
+
email,
|
|
32
|
+
scopes: Array.isArray(verified.payload.scopes)
|
|
33
|
+
? verified.payload.scopes
|
|
34
|
+
: [],
|
|
35
|
+
};
|
|
36
|
+
next();
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/express/middleware.ts"],"names":[],"mappings":";;AAiBA,oDA2CC;AA3DD,sCAA8C;AAgB9C,SAAgB,oBAAoB,CAAC,OAA2B;IAC9D,OAAO,KAAK,EACV,GAAY,EACZ,GAAa,EACb,IAAkB,EACH,EAAE;QACjB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAmC,CAAC;QAEnE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,GAAG;iBACA,MAAM,CAAC,GAAG,CAAC;iBACX,IAAI,CAAC,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAA,0BAAiB,EAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAEnD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAC;YAC9D,OAAO;QACT,CAAC;QAED,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC;gBACpD,OAAO;YACT,CAAC;YACD,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;QACzB,CAAC;QAED,GAAG,CAAC,IAAI,GAAG;YACT,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG;YAC5B,KAAK;YACL,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC5C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM;gBACzB,CAAC,CAAC,EAAE;SACP,CAAC;QAEF,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./verify"), exports);
|
|
19
|
+
__exportStar(require("./userinfo"), exports);
|
|
20
|
+
__exportStar(require("./nestjs"), exports);
|
|
21
|
+
__exportStar(require("./express"), exports);
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,2CAAyB;AACzB,6CAA2B;AAC3B,2CAAyB;AACzB,4CAA0B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator.d.ts","sourceRoot":"","sources":["../../src/nestjs/decorator.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,mDAOvB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CurrentUser = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.CurrentUser = (0, common_1.createParamDecorator)((data, ctx) => {
|
|
6
|
+
const request = ctx
|
|
7
|
+
.switchToHttp()
|
|
8
|
+
.getRequest();
|
|
9
|
+
return request.user;
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator.js","sourceRoot":"","sources":["../../src/nestjs/decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AAI3D,QAAA,WAAW,GAAG,IAAA,6BAAoB,EAC7C,CAAC,IAAa,EAAE,GAAqB,EAA2B,EAAE;IAChE,MAAM,OAAO,GAAG,GAAG;SAChB,YAAY,EAAE;SACd,UAAU,EAAoC,CAAC;IAClD,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC,CACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import type { VerifyTokenOptions } from '../types';
|
|
3
|
+
export interface JwtAuthGuardOptions extends VerifyTokenOptions {
|
|
4
|
+
getUserInfo?: (userId: string) => Promise<{
|
|
5
|
+
email: string;
|
|
6
|
+
} | null>;
|
|
7
|
+
}
|
|
8
|
+
export declare class JwtAuthGuard implements CanActivate {
|
|
9
|
+
private readonly options;
|
|
10
|
+
constructor(options: JwtAuthGuardOptions);
|
|
11
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/nestjs/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAEjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,UAAU,CAAC;AAEhE,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CACrE;AAED,qBACa,YAAa,YAAW,WAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,mBAAmB;IAEnD,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAsC/D"}
|
|
@@ -0,0 +1,56 @@
|
|
|
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.JwtAuthGuard = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const verify_1 = require("../verify");
|
|
15
|
+
let JwtAuthGuard = class JwtAuthGuard {
|
|
16
|
+
options;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
}
|
|
20
|
+
async canActivate(context) {
|
|
21
|
+
const request = context
|
|
22
|
+
.switchToHttp()
|
|
23
|
+
.getRequest();
|
|
24
|
+
const authHeader = request.headers.authorization;
|
|
25
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
26
|
+
throw new common_1.UnauthorizedException('Missing or invalid authorization header');
|
|
27
|
+
}
|
|
28
|
+
const token = authHeader.substring(7);
|
|
29
|
+
const verified = (0, verify_1.verifyAccessToken)(token, this.options);
|
|
30
|
+
if (!verified.valid) {
|
|
31
|
+
throw new common_1.UnauthorizedException('Invalid or expired token');
|
|
32
|
+
}
|
|
33
|
+
let email = '';
|
|
34
|
+
if (this.options.getUserInfo) {
|
|
35
|
+
const userInfo = await this.options.getUserInfo(verified.payload.sub);
|
|
36
|
+
if (!userInfo) {
|
|
37
|
+
throw new common_1.UnauthorizedException('User not found');
|
|
38
|
+
}
|
|
39
|
+
email = userInfo.email;
|
|
40
|
+
}
|
|
41
|
+
request.user = {
|
|
42
|
+
userId: verified.payload.sub,
|
|
43
|
+
email,
|
|
44
|
+
scopes: Array.isArray(verified.payload.scopes)
|
|
45
|
+
? verified.payload.scopes
|
|
46
|
+
: [],
|
|
47
|
+
};
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
exports.JwtAuthGuard = JwtAuthGuard;
|
|
52
|
+
exports.JwtAuthGuard = JwtAuthGuard = __decorate([
|
|
53
|
+
(0, common_1.Injectable)(),
|
|
54
|
+
__metadata("design:paramtypes", [Object])
|
|
55
|
+
], JwtAuthGuard);
|
|
56
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/nestjs/guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AAExB,sCAA8C;AAQvC,IAAM,YAAY,GAAlB,MAAM,YAAY;IACM;IAA7B,YAA6B,OAA4B;QAA5B,YAAO,GAAP,OAAO,CAAqB;IAAG,CAAC;IAE7D,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO;aACpB,YAAY,EAAE;aACd,UAAU,EAAoC,CAAC;QAClD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAmC,CAAC;QAEvE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,8BAAqB,CAC7B,yCAAyC,CAC1C,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAA,0BAAiB,EAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAExD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,IAAI,8BAAqB,CAAC,0BAA0B,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACtE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,8BAAqB,CAAC,gBAAgB,CAAC,CAAC;YACpD,CAAC;YACD,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;QACzB,CAAC;QAED,OAAO,CAAC,IAAI,GAAG;YACb,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG;YAC5B,KAAK;YACL,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC5C,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM;gBACzB,CAAC,CAAC,EAAE;SACP,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAzCY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;;GACA,YAAY,CAyCxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nestjs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CurrentUser = exports.JwtAuthGuard = void 0;
|
|
4
|
+
var guard_1 = require("./guard");
|
|
5
|
+
Object.defineProperty(exports, "JwtAuthGuard", { enumerable: true, get: function () { return guard_1.JwtAuthGuard; } });
|
|
6
|
+
var decorator_1 = require("./decorator");
|
|
7
|
+
Object.defineProperty(exports, "CurrentUser", { enumerable: true, get: function () { return decorator_1.CurrentUser; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nestjs/index.ts"],"names":[],"mappings":";;;AAAA,iCAAuC;AAA9B,qGAAA,YAAY,OAAA;AAErB,yCAA0C;AAAjC,wGAAA,WAAW,OAAA"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface TokenPayload {
|
|
2
|
+
sub: string;
|
|
3
|
+
type: 'access' | 'refresh' | 'temp';
|
|
4
|
+
scopes?: string[];
|
|
5
|
+
clientId?: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface VerifyTokenOptions {
|
|
9
|
+
secret: string;
|
|
10
|
+
issuer?: string;
|
|
11
|
+
audience?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface VerifiedToken {
|
|
14
|
+
payload: TokenPayload;
|
|
15
|
+
valid: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface UserPayload {
|
|
18
|
+
userId: string;
|
|
19
|
+
email: string;
|
|
20
|
+
scopes?: string[];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UserInfo, IntrospectResult } from '@tekcify/auth-core-client';
|
|
2
|
+
export declare function fetchUserInfo(accessToken: string): Promise<UserInfo>;
|
|
3
|
+
export interface IntrospectTokenOptions {
|
|
4
|
+
token: string;
|
|
5
|
+
clientId?: string;
|
|
6
|
+
clientSecret?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function introspectAccessToken(options: IntrospectTokenOptions): Promise<IntrospectResult>;
|
|
9
|
+
//# sourceMappingURL=userinfo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userinfo.d.ts","sourceRoot":"","sources":["../src/userinfo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG5E,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAE1E;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAM3B"}
|
package/dist/userinfo.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchUserInfo = fetchUserInfo;
|
|
4
|
+
exports.introspectAccessToken = introspectAccessToken;
|
|
5
|
+
const auth_core_client_1 = require("@tekcify/auth-core-client");
|
|
6
|
+
async function fetchUserInfo(accessToken) {
|
|
7
|
+
return (0, auth_core_client_1.getUserInfo)(accessToken);
|
|
8
|
+
}
|
|
9
|
+
async function introspectAccessToken(options) {
|
|
10
|
+
return (0, auth_core_client_1.introspectToken)({
|
|
11
|
+
token: options.token,
|
|
12
|
+
clientId: options.clientId,
|
|
13
|
+
clientSecret: options.clientSecret,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=userinfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userinfo.js","sourceRoot":"","sources":["../src/userinfo.ts"],"names":[],"mappings":";;AAGA,sCAEC;AAQD,sDAQC;AApBD,gEAAyE;AAElE,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,OAAO,IAAA,8BAAW,EAAC,WAAW,CAAC,CAAC;AAClC,CAAC;AAQM,KAAK,UAAU,qBAAqB,CACzC,OAA+B;IAE/B,OAAO,IAAA,kCAAe,EAAC;QACrB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TokenPayload, VerifyTokenOptions, VerifiedToken } from './types';
|
|
2
|
+
export declare function verifyAccessToken(token: string, options: VerifyTokenOptions): VerifiedToken;
|
|
3
|
+
export declare function decodeToken(token: string): TokenPayload | null;
|
|
4
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE/E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,kBAAkB,GAC1B,aAAa,CAqBf;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAM9D"}
|
package/dist/verify.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.verifyAccessToken = verifyAccessToken;
|
|
7
|
+
exports.decodeToken = decodeToken;
|
|
8
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
9
|
+
function verifyAccessToken(token, options) {
|
|
10
|
+
try {
|
|
11
|
+
const decoded = jsonwebtoken_1.default.verify(token, options.secret, {
|
|
12
|
+
issuer: options.issuer ?? 'tekcify-auth',
|
|
13
|
+
audience: options.audience ?? 'tekcify-api',
|
|
14
|
+
});
|
|
15
|
+
if (decoded.type !== 'access') {
|
|
16
|
+
return { payload: decoded, valid: false };
|
|
17
|
+
}
|
|
18
|
+
return { payload: decoded, valid: true };
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (error instanceof jsonwebtoken_1.default.JsonWebTokenError) {
|
|
22
|
+
return { payload: {}, valid: false };
|
|
23
|
+
}
|
|
24
|
+
if (error instanceof jsonwebtoken_1.default.TokenExpiredError) {
|
|
25
|
+
return { payload: {}, valid: false };
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function decodeToken(token) {
|
|
31
|
+
try {
|
|
32
|
+
return jsonwebtoken_1.default.decode(token);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":";;;;;AAGA,8CAwBC;AAED,kCAMC;AAnCD,gEAA+B;AAG/B,SAAgB,iBAAiB,CAC/B,KAAa,EACb,OAA2B;IAE3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;YAChD,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,cAAc;YACxC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,aAAa;SAC5C,CAAiB,CAAC;QAEnB,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAC5C,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,sBAAG,CAAC,iBAAiB,EAAE,CAAC;YAC3C,OAAO,EAAE,OAAO,EAAE,EAAkB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACvD,CAAC;QACD,IAAI,KAAK,YAAY,sBAAG,CAAC,iBAAiB,EAAE,CAAC;YAC3C,OAAO,EAAE,OAAO,EAAE,EAAkB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACvD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC;QACH,OAAO,sBAAG,CAAC,MAAM,CAAC,KAAK,CAAwB,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekcify/auth-backend",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Backend authentication helpers for Tekcify Auth. Provides middleware, guards, and utilities for validating JWT tokens and protecting API routes in NestJS and Express applications.",
|
|
5
5
|
"author": "Tekcify",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
|
-
"build": "tsc",
|
|
34
|
+
"build": "tsc -p tsconfig.build.json",
|
|
35
35
|
"clean": "rm -rf dist",
|
|
36
36
|
"lint": "eslint \"src/**/*.ts\" --max-warnings=0",
|
|
37
37
|
"test": "vitest run",
|
|
@@ -44,18 +44,22 @@
|
|
|
44
44
|
"jwt",
|
|
45
45
|
"auth"
|
|
46
46
|
],
|
|
47
|
+
"files": [
|
|
48
|
+
"dist",
|
|
49
|
+
"README.md"
|
|
50
|
+
],
|
|
47
51
|
"license": "MIT",
|
|
48
52
|
"dependencies": {
|
|
49
|
-
"@tekcify/auth-core-client": "
|
|
50
|
-
"jsonwebtoken": "^9.0.
|
|
53
|
+
"@tekcify/auth-core-client": ">=1.0.5",
|
|
54
|
+
"jsonwebtoken": "^9.0.3"
|
|
51
55
|
},
|
|
52
56
|
"devDependencies": {
|
|
53
|
-
"@nestjs/common": "^11.
|
|
54
|
-
"@nestjs/core": "^11.
|
|
55
|
-
"@types/express": "^5.0.
|
|
57
|
+
"@nestjs/common": "^11.1.9",
|
|
58
|
+
"@nestjs/core": "^11.1.9",
|
|
59
|
+
"@types/express": "^5.0.6",
|
|
56
60
|
"@types/jsonwebtoken": "^9.0.10",
|
|
57
|
-
"@types/node": "^
|
|
58
|
-
"typescript": "^5.
|
|
61
|
+
"@types/node": "^24.10.1",
|
|
62
|
+
"typescript": "^5.9.3",
|
|
59
63
|
"vitest": "^4.0.15"
|
|
60
64
|
},
|
|
61
65
|
"peerDependencies": {
|
|
@@ -63,4 +67,3 @@
|
|
|
63
67
|
"@nestjs/core": "^11.0.0"
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
|
-
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import jwt from 'jsonwebtoken';
|
|
3
|
-
import { verifyAccessToken } from '../verify';
|
|
4
|
-
|
|
5
|
-
describe('verifyAccessToken', () => {
|
|
6
|
-
const secret = 'test-secret';
|
|
7
|
-
const issuer = 'tekcify-auth';
|
|
8
|
-
const audience = 'tekcify-api';
|
|
9
|
-
|
|
10
|
-
it('should verify a valid access token', () => {
|
|
11
|
-
const payload = {
|
|
12
|
-
sub: 'user-123',
|
|
13
|
-
type: 'access',
|
|
14
|
-
scopes: ['read:profile'],
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const token = jwt.sign(payload, secret, {
|
|
18
|
-
issuer,
|
|
19
|
-
audience,
|
|
20
|
-
expiresIn: '1h',
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
const result = verifyAccessToken(token, { secret, issuer, audience });
|
|
24
|
-
|
|
25
|
-
expect(result.valid).toBe(true);
|
|
26
|
-
expect(result.payload.sub).toBe('user-123');
|
|
27
|
-
expect(result.payload.type).toBe('access');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should reject a refresh token', () => {
|
|
31
|
-
const payload = {
|
|
32
|
-
sub: 'user-123',
|
|
33
|
-
type: 'refresh',
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const token = jwt.sign(payload, secret, {
|
|
37
|
-
issuer,
|
|
38
|
-
audience,
|
|
39
|
-
expiresIn: '7d',
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const result = verifyAccessToken(token, { secret, issuer, audience });
|
|
43
|
-
|
|
44
|
-
expect(result.valid).toBe(false);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should reject an expired token', () => {
|
|
48
|
-
const payload = {
|
|
49
|
-
sub: 'user-123',
|
|
50
|
-
type: 'access',
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const token = jwt.sign(payload, secret, {
|
|
54
|
-
issuer,
|
|
55
|
-
audience,
|
|
56
|
-
expiresIn: '-1h',
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const result = verifyAccessToken(token, { secret, issuer, audience });
|
|
60
|
-
|
|
61
|
-
expect(result.valid).toBe(false);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should reject a token with wrong secret', () => {
|
|
65
|
-
const payload = {
|
|
66
|
-
sub: 'user-123',
|
|
67
|
-
type: 'access',
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const token = jwt.sign(payload, 'wrong-secret', {
|
|
71
|
-
issuer,
|
|
72
|
-
audience,
|
|
73
|
-
expiresIn: '1h',
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const result = verifyAccessToken(token, { secret, issuer, audience });
|
|
77
|
-
|
|
78
|
-
expect(result.valid).toBe(false);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { verifyAccessToken } from '../verify';
|
|
3
|
-
import type { VerifyTokenOptions, UserPayload } from '../types';
|
|
4
|
-
|
|
5
|
-
export interface ExpressAuthOptions extends VerifyTokenOptions {
|
|
6
|
-
getUserInfo?: (userId: string) => Promise<{ email: string } | null>;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
declare global {
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
11
|
-
namespace Express {
|
|
12
|
-
interface Request {
|
|
13
|
-
user?: UserPayload;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function createAuthMiddleware(options: ExpressAuthOptions) {
|
|
19
|
-
return async (
|
|
20
|
-
req: Request,
|
|
21
|
-
res: Response,
|
|
22
|
-
next: NextFunction,
|
|
23
|
-
): Promise<void> => {
|
|
24
|
-
const authHeader = req.headers.authorization as string | undefined;
|
|
25
|
-
|
|
26
|
-
if (!authHeader?.startsWith('Bearer ')) {
|
|
27
|
-
res
|
|
28
|
-
.status(401)
|
|
29
|
-
.json({ message: 'Missing or invalid authorization header' });
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const token = authHeader.substring(7);
|
|
34
|
-
const verified = verifyAccessToken(token, options);
|
|
35
|
-
|
|
36
|
-
if (!verified.valid) {
|
|
37
|
-
res.status(401).json({ message: 'Invalid or expired token' });
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
let email = '';
|
|
42
|
-
if (options.getUserInfo) {
|
|
43
|
-
const userInfo = await options.getUserInfo(verified.payload.sub);
|
|
44
|
-
if (!userInfo) {
|
|
45
|
-
res.status(401).json({ message: 'User not found' });
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
email = userInfo.email;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
req.user = {
|
|
52
|
-
userId: verified.payload.sub,
|
|
53
|
-
email,
|
|
54
|
-
scopes: Array.isArray(verified.payload.scopes)
|
|
55
|
-
? verified.payload.scopes
|
|
56
|
-
: [],
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
next();
|
|
60
|
-
};
|
|
61
|
-
}
|
package/src/nestjs/decorator.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
|
2
|
-
import type { Request } from 'express';
|
|
3
|
-
import type { UserPayload } from '../types';
|
|
4
|
-
|
|
5
|
-
export const CurrentUser = createParamDecorator(
|
|
6
|
-
(data: unknown, ctx: ExecutionContext): UserPayload | undefined => {
|
|
7
|
-
const request = ctx
|
|
8
|
-
.switchToHttp()
|
|
9
|
-
.getRequest<Request & { user?: UserPayload }>();
|
|
10
|
-
return request.user;
|
|
11
|
-
},
|
|
12
|
-
);
|