@next-nest-auth/nestauth 1.0.8 → 1.1.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/http-exception.filter.js +19 -3
- package/dist/http-exception.filter.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/nestauth-jwt.guard.d.ts +1 -0
- package/dist/nestauth-jwt.guard.js +10 -1
- package/dist/nestauth-jwt.guard.js.map +1 -1
- package/dist/nestauth-jwt.strategy.d.ts +1 -9
- package/dist/nestauth-jwt.strategy.js +13 -8
- package/dist/nestauth-jwt.strategy.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/http-exception.filter.ts +23 -8
- package/src/index.ts +2 -0
- package/src/nestauth-jwt.guard.ts +18 -1
- package/src/nestauth-jwt.strategy.ts +38 -19
package/package.json
CHANGED
|
@@ -4,27 +4,25 @@ import {
|
|
|
4
4
|
ArgumentsHost,
|
|
5
5
|
HttpException,
|
|
6
6
|
} from "@nestjs/common";
|
|
7
|
-
import { Request, Response } from "express";
|
|
8
7
|
|
|
9
8
|
@Catch()
|
|
10
9
|
export class HttpExceptionFilter implements ExceptionFilter {
|
|
11
10
|
catch(exception: any, host: ArgumentsHost) {
|
|
12
11
|
const ctx = host.switchToHttp();
|
|
13
|
-
const response = ctx.getResponse
|
|
14
|
-
const request = ctx.getRequest
|
|
12
|
+
const response = ctx.getResponse();
|
|
13
|
+
const request = ctx.getRequest();
|
|
15
14
|
|
|
16
15
|
let status = 500;
|
|
17
16
|
let message = "Internal Server Error";
|
|
18
17
|
|
|
19
|
-
// Check using instanceof or shape fallback
|
|
20
18
|
if (
|
|
21
19
|
exception instanceof HttpException ||
|
|
22
20
|
(exception?.status && exception?.response)
|
|
23
21
|
) {
|
|
24
22
|
status = exception.status ?? 500;
|
|
25
|
-
|
|
26
23
|
const exceptionResponse =
|
|
27
24
|
exception.response ?? exception.getResponse?.();
|
|
25
|
+
|
|
28
26
|
if (typeof exceptionResponse === "string") {
|
|
29
27
|
message = exceptionResponse;
|
|
30
28
|
} else if (
|
|
@@ -42,11 +40,28 @@ export class HttpExceptionFilter implements ExceptionFilter {
|
|
|
42
40
|
console.error("Unexpected error:", exception);
|
|
43
41
|
}
|
|
44
42
|
|
|
45
|
-
|
|
43
|
+
const responseBody = {
|
|
46
44
|
statusCode: status,
|
|
47
45
|
message,
|
|
48
|
-
path: request
|
|
46
|
+
path: request?.url,
|
|
49
47
|
app: "nestauth",
|
|
50
|
-
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Try to send response for Express or Fastify
|
|
51
|
+
try {
|
|
52
|
+
if (
|
|
53
|
+
typeof response.status === "function" &&
|
|
54
|
+
typeof response.json === "function"
|
|
55
|
+
) {
|
|
56
|
+
response.status(status).json(responseBody);
|
|
57
|
+
} else if (typeof response.send === "function") {
|
|
58
|
+
response.code?.(status); // Fastify specific
|
|
59
|
+
response.send(responseBody);
|
|
60
|
+
} else {
|
|
61
|
+
console.error("Unsupported response object:", response);
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error("Error while sending error response:", err);
|
|
65
|
+
}
|
|
51
66
|
}
|
|
52
67
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,17 +8,34 @@ import * as macaddress from "macaddress";
|
|
|
8
8
|
|
|
9
9
|
@Injectable()
|
|
10
10
|
export class NestAuthJwtGuard extends AuthGuard("jwt") {
|
|
11
|
+
// ✅ Custom error handling here
|
|
12
|
+
handleRequest(err: any, user: any, info: any, context: ExecutionContext) {
|
|
13
|
+
console.log("err, user, info, context1");
|
|
14
|
+
if (err || !user) {
|
|
15
|
+
throw new UnauthorizedException(
|
|
16
|
+
"Unauthorized: Invalid or missing token"
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
return user;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ✅ Make sure to return the result of `super.canActivate`
|
|
11
23
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
|
24
|
+
const can = (await super.canActivate(context)) as boolean;
|
|
25
|
+
if (!can) return false; // short-circuit if base guard fails
|
|
26
|
+
|
|
12
27
|
const request = context.switchToHttp().getRequest();
|
|
13
|
-
await super.canActivate(context);
|
|
14
28
|
const user = request.user;
|
|
29
|
+
|
|
15
30
|
if (!user) {
|
|
16
31
|
throw new UnauthorizedException("Unauthorized: Invalid token");
|
|
17
32
|
}
|
|
33
|
+
|
|
18
34
|
const currentMacId = await macaddress.one();
|
|
19
35
|
if (user.macId !== currentMacId) {
|
|
20
36
|
throw new UnauthorizedException("Unauthorized: Device mismatch");
|
|
21
37
|
}
|
|
38
|
+
|
|
22
39
|
return true;
|
|
23
40
|
}
|
|
24
41
|
}
|
|
@@ -1,28 +1,47 @@
|
|
|
1
1
|
import { ExtractJwt, Strategy } from "passport-jwt";
|
|
2
2
|
import { PassportStrategy } from "@nestjs/passport";
|
|
3
|
-
import { Inject, Injectable } from "@nestjs/common";
|
|
3
|
+
import { Inject, Injectable, UnauthorizedException } from "@nestjs/common";
|
|
4
4
|
import { JwtPayload } from "jsonwebtoken";
|
|
5
5
|
import * as macaddress from "macaddress";
|
|
6
6
|
|
|
7
7
|
@Injectable()
|
|
8
8
|
export class NestAuthJwtStrategy extends PassportStrategy(Strategy) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
constructor(@Inject("JWT_SECRET") jwtSecret: string) {
|
|
10
|
+
super({
|
|
11
|
+
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
12
|
+
ignoreExpiration: false,
|
|
13
|
+
secretOrKey: jwtSecret,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
async validate(payload: JwtPayload) {
|
|
18
|
+
// return {
|
|
19
|
+
// userId: payload.sub,
|
|
20
|
+
// macId: payload.macId ?? (await macaddress.one()),
|
|
21
|
+
// email: payload.email,
|
|
22
|
+
// role: payload.role,
|
|
23
|
+
// name: payload.name,
|
|
24
|
+
// username: payload.username,
|
|
25
|
+
// pic: payload.pic,
|
|
26
|
+
// };
|
|
27
|
+
|
|
28
|
+
if (!payload) {
|
|
29
|
+
throw new UnauthorizedException("Invalid token payload");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const macId = payload.macId ?? (await macaddress.one());
|
|
33
|
+
|
|
34
|
+
const userData: Record<string, any> = {
|
|
35
|
+
sub: payload.sub,
|
|
36
|
+
macId,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
for (const key of Object.keys(payload)) {
|
|
40
|
+
if (key !== "sub" && key !== "macId") {
|
|
41
|
+
userData[key] = payload[key];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return userData;
|
|
46
|
+
}
|
|
28
47
|
}
|