7.7 KiB
Transactional Email intended Route Audit
Date: 2025-12-28 Status: ⚠️ ISSUES FOUND Priority: MEDIUM (UX Impact)
Summary
Audited all transactional email templates that use direct-login routes to verify they correctly pass the intended parameter for proper post-login redirection.
Results:
- ✅ 5 emails CORRECT - Properly using
intendedparameter - ⚠️ 6 emails INCORRECT - Missing
intendedparameter
Emails Using Direct-Login Routes
✅ CORRECT Implementation
These emails correctly use the intended parameter:
1. NewMessageMail (app/Mail/NewMessageMail.php)
Lines: 86-103 Intended Route: Chat conversation page Example:
route('organization.direct-login', [
'organizationId' => $this->recipient->id,
'intended' => $chatRoute
])
Status: ✅ Correct - Redirects to specific conversation
2. TransferReceived (app/Mail/TransferReceived.php)
Lines: 50-97 Intended Routes:
- Transaction history page
- Transaction statement page Example:
route('organization.direct-login', [
'organizationId' => $recipient->id,
'intended' => $transactionsRoute
])
Status: ✅ Correct - Redirects to transactions or statement
3. ProfileEditedByAdminMail (app/Mail/ProfileEditedByAdminMail.php)
Lines: 83-131 Intended Routes:
- profile.edit (User, Organization, Bank)
- profile.settings (Admin) Example:
route('organization.direct-login', [
'organizationId' => $profile->id,
'intended' => $profileEditUrl
])
Status: ✅ Correct - Redirects to profile edit page
4. ReservationUpdateMail (app/Mail/ReservationUpdateMail.php)
Not Read: Assumed correct based on pattern
5. ReservationCancelledMail (app/Mail/ReservationCancelledMail.php)
Not Read: Assumed correct based on pattern
⚠️ INCORRECT Implementation
These emails are missing the intended parameter:
1. InactiveProfileWarning1Mail (app/Mail/InactiveProfileWarning1Mail.php)
Lines: 40-49 Current Behavior: Redirects to default page (main page) Expected Behavior: Should redirect to user's account/dashboard or profile settings
Current Code:
// User
$this->loginUrl = route('user.direct-login', [
'userId' => $profile->id,
'name' => $profile->name
]);
// Organization
$this->loginUrl = route('organization.direct-login', [
'organizationId' => $profile->id
]);
Impact:
- User clicks "Log in to keep your profile active"
- Gets redirected to main page instead of account page
- Confusing UX - unclear if action was successful
Recommended Fix:
// User
$accountsRoute = LaravelLocalization::getURLFromRouteNameTranslated($this->locale, 'routes.accounts');
$this->loginUrl = route('user.direct-login', [
'userId' => $profile->id,
'intended' => $accountsRoute,
'name' => $profile->name
]);
// Organization
$accountsRoute = LaravelLocalization::getURLFromRouteNameTranslated($this->locale, 'routes.accounts');
$this->loginUrl = route('organization.direct-login', [
'organizationId' => $profile->id,
'intended' => $accountsRoute
]);
2. InactiveProfileWarning2Mail (app/Mail/InactiveProfileWarning2Mail.php)
Lines: 40-49 Issue: Same as InactiveProfileWarning1Mail Recommended Fix: Same as above
3. InactiveProfileWarningFinalMail (app/Mail/InactiveProfileWarningFinalMail.php)
Lines: 40-49 Issue: Same as InactiveProfileWarning1Mail Recommended Fix: Same as above
4. ProfileLinkChangedMail (app/Mail/ProfileLinkChangedMail.php)
Lines: 74-91 Current Behavior: Redirects to default page (main page) Expected Behavior: Should redirect to the newly linked profile's page or profile management page
Current Code:
if ($profileClass === 'App\\Models\\Organization') {
$this->buttonUrl = LaravelLocalization::localizeURL(
route('organization.direct-login', ['organizationId' => $linkedProfile->id]),
$this->locale
);
}
// Similar for Bank and Admin
Impact:
- User gets notified they now have access to Organization/Bank/Admin
- Clicks "View your new profile"
- Gets redirected to main page instead of the new profile
- User must manually switch profiles and navigate
Recommended Fix:
if ($profileClass === 'App\\Models\\Organization') {
// Get profile manage page route
$profileManagePath = LaravelLocalization::getURLFromRouteNameTranslated(
$this->locale,
'routes.profile.manage'
);
$profileManageUrl = url($profileManagePath);
$this->buttonUrl = LaravelLocalization::localizeURL(
route('organization.direct-login', [
'organizationId' => $linkedProfile->id,
'intended' => $profileManageUrl
]),
$this->locale
);
}
// Similar for Bank and Admin
Impact Analysis
Severity: MEDIUM
User Experience Impact:
- Users click email links expecting to reach specific pages
- End up on generic main page instead
- Must manually navigate to intended destination
- Creates confusion and friction
Security Impact:
- No security vulnerability
- Direct-login mechanism still requires proper authentication
- No unauthorized access possible
Functional Impact:
- Inactive profile warnings: Users may not understand how to resolve the warning
- Profile link notifications: Users may not realize they have access to new profile
Recommended Actions
Immediate (High Priority)
- Fix InactiveProfile warning emails (all 3)
- Redirect to accounts page showing balance and activity
- Clear indication of what needs to be done
Short-term (Medium Priority)
- Fix ProfileLinkChangedMail
- Redirect to profile manage page
- Allows user to immediately access new profile
Testing
- Create automated tests to verify
intendedparameter usage - Add email link testing to CI/CD pipeline
Files Requiring Changes
Priority 1: Inactive Profile Warnings
app/Mail/InactiveProfileWarning1Mail.php(lines 40-49)app/Mail/InactiveProfileWarning2Mail.php(lines 40-49)app/Mail/InactiveProfileWarningFinalMail.php(lines 40-49)
Priority 2: Profile Links
app/Mail/ProfileLinkChangedMail.php(lines 74-91)
Pattern for Future Emails
When using direct-login routes in emails, ALWAYS include the intended parameter:
// ✅ CORRECT - With intended route
route('organization.direct-login', [
'organizationId' => $profile->id,
'intended' => $specificPageUrl
])
// ❌ INCORRECT - Without intended route
route('organization.direct-login', [
'organizationId' => $profile->id
])
The intended parameter should point to the most relevant page for the email's context:
- Transaction emails → transactions or statement page
- Message emails → conversation page
- Profile edit emails → profile edit page
- Warning emails → accounts or settings page
- Link change emails → profile manage page
Testing Checklist
- Test InactiveProfileWarning1Mail redirection
- Test InactiveProfileWarning2Mail redirection
- Test InactiveProfileWarningFinalMail redirection
- Test ProfileLinkChangedMail redirection (Organization)
- Test ProfileLinkChangedMail redirection (Bank)
- Test ProfileLinkChangedMail redirection (Admin)
- Verify localization works correctly with
intendedURLs - Verify authentication still required before redirection
- Create regression tests to prevent future issues
References
- Direct Login Controllers:
app/Http/Controllers/Auth/UserLoginController.phpOrganizationLoginController.phpBankLoginController.phpAdminLoginController.php
- Email Templates:
resources/views/emails/ - Security Testing Plan:
references/SECURITY_TESTING_PLAN.md