@@ -75,25 +75,23 @@ class AuthService {
75
75
// For dashboard login, first validate the user exists and has permissions.
76
76
if (isDashboardLogin) {
77
77
final user = await _findUserByEmail (email);
78
+
79
+ // For dashboard login, the user must exist AND have permission.
80
+ // If either condition fails, throw the appropriate exception.
78
81
if (user == null ) {
79
82
_log.warning ('Dashboard login failed: User $email not found.' );
80
83
throw const UnauthorizedException (
81
84
'This email address is not registered for dashboard access.' ,
82
85
);
83
- }
84
-
85
- // Use the PermissionService to check for the specific dashboard login permission.
86
- if (! _permissionService.hasPermission (
87
- user,
88
- Permissions .dashboardLogin,
89
- )) {
86
+ } else if (! _permissionService.hasPermission (user, Permissions .dashboardLogin)) {
90
87
_log.warning (
91
88
'Dashboard login failed: User ${user .id } lacks required permission (${Permissions .dashboardLogin }).' ,
92
89
);
93
90
throw const ForbiddenException (
94
91
'Your account does not have the required permissions to sign in.' ,
95
92
);
96
93
}
94
+
97
95
_log.info ('Dashboard user ${user .id } verified successfully.' );
98
96
}
99
97
@@ -105,11 +103,13 @@ class AuthService {
105
103
await _emailRepository.sendOtpEmail (recipientEmail: email, otpCode: code);
106
104
_log.info ('Initiated email sign-in for $email , code sent.' );
107
105
} on HtHttpException {
108
- // Propagate known exceptions from dependencies
106
+ // Propagate known exceptions from dependencies or from this method's logic.
107
+ // This ensures that specific errors like ForbiddenException are not
108
+ // masked as a generic server error.
109
109
rethrow ;
110
- } catch (e) {
111
- // Catch unexpected errors during orchestration
112
- _log.severe ('Error during initiateEmailSignIn for $email : $e ' );
110
+ } catch (e, s ) {
111
+ // Catch unexpected errors during orchestration.
112
+ _log.severe ('Error during initiateEmailSignIn for $email : $e ' , e, s );
113
113
throw const OperationFailedException (
114
114
'Failed to initiate email sign-in process.' ,
115
115
);
@@ -166,13 +166,25 @@ class AuthService {
166
166
// This closes the loophole where a non-admin user could request a code
167
167
// via the app flow and then use it to log into the dashboard.
168
168
if (isDashboardLogin) {
169
+ if (user.email != email) {
170
+ // This is a critical security check. If the user found by email
171
+ // somehow has a different email than the one provided, it's a
172
+ // sign of a serious issue (like the data layer bug we fixed).
173
+ // We throw a generic error to avoid revealing information.
174
+ _log.severe (
175
+ 'CRITICAL: Mismatch between requested email ($email ) and found '
176
+ 'user email (${user .email }) during dashboard login for user '
177
+ 'ID ${user .id }.' ,
178
+ );
179
+ throw const UnauthorizedException ('User account does not exist.' );
180
+ }
169
181
if (! _permissionService.hasPermission (
170
182
user,
171
183
Permissions .dashboardLogin,
172
184
)) {
173
185
_log.warning (
174
- 'Dashboard login failed: User ${user .id } lacks required permission '
175
- 'during code verification.' ,
186
+ 'Dashboard login failed: User ${user .id } lacks required '
187
+ 'permission during code verification.' ,
176
188
);
177
189
throw const ForbiddenException (
178
190
'Your account does not have the required permissions to sign in.' ,
@@ -254,14 +266,14 @@ class AuthService {
254
266
'Created default UserContentPreferences for user: ${user .id }' ,
255
267
);
256
268
}
257
- } on HtHttpException catch (e) {
258
- _log. severe ( 'Error finding/creating user for $ email : $ e ' );
259
- throw const OperationFailedException (
260
- 'Failed to find or create user account.' ,
261
- ) ;
262
- } catch (e) {
269
+ } on HtHttpException {
270
+ // Propagate known exceptions from dependencies or from this method's logic.
271
+ // This ensures that specific errors like ForbiddenException are not
272
+ // masked as a generic server error.
273
+ rethrow ;
274
+ } catch (e, s ) {
263
275
_log.severe (
264
- 'Unexpected error during user lookup/creation for $email : $e ' ,
276
+ 'Unexpected error during user lookup/creation for $email : $e ' , e, s,
265
277
);
266
278
throw const OperationFailedException ('Failed to process user account.' );
267
279
}
0 commit comments