|
1 | | -import { Injectable, CanActivate, ExecutionContext, Logger } from "@nestjs/common"; |
2 | | -import { Observable } from "rxjs"; |
| 1 | +import { |
| 2 | + Injectable, |
| 3 | + CanActivate, |
| 4 | + ExecutionContext, |
| 5 | + Logger, |
| 6 | + UnauthorizedException, |
| 7 | + ForbiddenException, |
| 8 | +} from "@nestjs/common"; |
3 | 9 | import { CognitoJwtVerifier } from "aws-jwt-verify"; |
4 | 10 |
|
5 | 11 |
|
@@ -27,24 +33,23 @@ export class VerifyUserGuard implements CanActivate { |
27 | 33 | } |
28 | 34 |
|
29 | 35 | async canActivate(context: ExecutionContext): Promise<boolean> { |
30 | | - try { |
31 | | - const request = context.switchToHttp().getRequest(); |
32 | | - const accessToken = request.cookies["access_token"]; |
33 | | - if (!accessToken) { |
34 | | - this.logger.error("No access token found in cookies"); |
35 | | - return false; |
36 | | - } |
37 | | - const result = await this.verifier.verify(accessToken); |
| 36 | + const request = context.switchToHttp().getRequest(); |
| 37 | + const accessToken = request.cookies["access_token"]; |
| 38 | + if (!accessToken) { |
| 39 | + this.logger.error("No access token found in cookies"); |
| 40 | + throw new UnauthorizedException("Missing access token"); |
| 41 | + } |
38 | 42 |
|
| 43 | + try { |
| 44 | + await this.verifier.verify(accessToken); |
39 | 45 | return true; |
40 | 46 | } catch (error) { |
41 | | - console.error("Token verification failed:", error); // Debug log |
42 | | - return false; |
| 47 | + this.logger.error("Token verification failed:", error); |
| 48 | + throw new UnauthorizedException("Invalid or expired access token"); |
43 | 49 | } |
44 | 50 | } |
45 | 51 | } |
46 | 52 |
|
47 | | -@Injectable() |
48 | 53 | @Injectable() |
49 | 54 | export class VerifyAdminRoleGuard implements CanActivate { |
50 | 55 | private verifier: any; |
@@ -73,51 +78,56 @@ export class VerifyAdminRoleGuard implements CanActivate { |
73 | 78 | } |
74 | 79 |
|
75 | 80 | async canActivate(context: ExecutionContext): Promise<boolean> { |
76 | | - try { |
77 | | - const request = context.switchToHttp().getRequest(); |
78 | | - const accessToken = request.cookies["access_token"]; |
79 | | - const idToken = request.cookies["id_token"]; |
| 81 | + const request = context.switchToHttp().getRequest(); |
| 82 | + const accessToken = request.cookies["access_token"]; |
| 83 | + const idToken = request.cookies["id_token"]; |
80 | 84 |
|
81 | | - if (!accessToken) { |
82 | | - this.logger.error("No access token found in cookies"); |
83 | | - return false; |
84 | | - } |
| 85 | + if (!accessToken) { |
| 86 | + this.logger.error("No access token found in cookies"); |
| 87 | + throw new UnauthorizedException("Missing access token"); |
| 88 | + } |
85 | 89 |
|
86 | | - if (!idToken) { |
87 | | - this.logger.error("No ID token found in cookies"); |
88 | | - return false; |
89 | | - } |
| 90 | + if (!idToken) { |
| 91 | + this.logger.error("No ID token found in cookies"); |
| 92 | + throw new UnauthorizedException("Missing id token"); |
| 93 | + } |
90 | 94 |
|
| 95 | + try { |
91 | 96 | const [result, idResult] = await Promise.all([ |
92 | 97 | this.verifier.verify(accessToken), |
93 | 98 | this.idVerifier.verify(idToken), |
94 | 99 | ]); |
95 | 100 |
|
96 | | - const groups = result['cognito:groups'] || []; |
97 | | - const email = idResult['email']; |
| 101 | + const groups = result["cognito:groups"] || []; |
| 102 | + const email = idResult["email"]; |
98 | 103 |
|
99 | 104 | if (!email) { |
100 | 105 | this.logger.error("No email found in ID token claims"); |
101 | | - return false; |
| 106 | + throw new UnauthorizedException("Invalid id token"); |
102 | 107 | } |
103 | 108 |
|
104 | 109 | // Attach user info to request for use in controllers |
105 | 110 | request.user = { |
106 | 111 | email, |
107 | | - position: groups.includes('Admin') ? 'Admin' : (groups.includes('Employee') ? 'Employee' : 'Inactive') |
| 112 | + position: groups.includes("Admin") |
| 113 | + ? "Admin" |
| 114 | + : groups.includes("Employee") |
| 115 | + ? "Employee" |
| 116 | + : "Inactive", |
108 | 117 | }; |
109 | 118 |
|
110 | 119 | this.logger.log(`User groups from token: ${groups}`); |
111 | 120 |
|
112 | | - if (!groups.includes('Admin')) { |
| 121 | + if (!groups.includes("Admin")) { |
113 | 122 | this.logger.warn("Access denied: User is not an Admin"); |
114 | | - return false; |
| 123 | + throw new ForbiddenException("Admin access required"); |
115 | 124 | } |
116 | 125 |
|
117 | 126 | return true; |
118 | 127 | } catch (error) { |
| 128 | + if (error instanceof ForbiddenException) throw error; |
119 | 129 | this.logger.error("Token verification failed:", error); |
120 | | - return false; |
| 130 | + throw new UnauthorizedException("Invalid or expired token"); |
121 | 131 | } |
122 | 132 | } |
123 | 133 | } |
@@ -145,33 +155,33 @@ export class VerifyAdminOrEmployeeRoleGuard implements CanActivate { |
145 | 155 | } |
146 | 156 |
|
147 | 157 | async canActivate(context: ExecutionContext): Promise<boolean> { |
| 158 | + const request = context.switchToHttp().getRequest(); |
| 159 | + const accessToken = request.cookies["access_token"]; |
| 160 | + |
| 161 | + if (!accessToken) { |
| 162 | + this.logger.error("No access token found in cookies"); |
| 163 | + throw new UnauthorizedException("Missing access token"); |
| 164 | + } |
| 165 | + |
148 | 166 | try { |
149 | | - const request = context.switchToHttp().getRequest(); |
150 | | - const accessToken = request.cookies["access_token"]; |
151 | | - |
152 | | - if (!accessToken) { |
153 | | - this.logger.error("No access token found in cookies"); |
154 | | - return false; |
155 | | - } |
156 | | - |
157 | 167 | const result = await this.verifier.verify(accessToken); |
158 | | - const groups = result['cognito:groups'] || []; |
159 | | - |
160 | | - this.logger.log(`User groups from token: ${groups.join(', ')}`); |
161 | | - |
| 168 | + const groups = result["cognito:groups"] || []; |
| 169 | + |
| 170 | + this.logger.log(`User groups from token: ${groups.join(", ")}`); |
| 171 | + |
162 | 172 | // Check if user is either Admin or Employee |
163 | | - const isAuthorized = groups.includes('Admin') || groups.includes('Employee'); |
164 | | - |
| 173 | + const isAuthorized = groups.includes("Admin") || groups.includes("Employee"); |
| 174 | + |
165 | 175 | if (!isAuthorized) { |
166 | 176 | this.logger.warn("Access denied: User is not an Admin or Employee"); |
167 | | - return false; |
| 177 | + throw new ForbiddenException("Insufficient role permissions"); |
168 | 178 | } |
169 | | - |
| 179 | + |
170 | 180 | return true; |
171 | | - |
172 | 181 | } catch (error) { |
| 182 | + if (error instanceof ForbiddenException) throw error; |
173 | 183 | this.logger.error("Token verification failed:", error); |
174 | | - return false; |
| 184 | + throw new UnauthorizedException("Invalid or expired access token"); |
175 | 185 | } |
176 | 186 | } |
177 | 187 | } |
0 commit comments