Skip to content

Commit 77c0c4f

Browse files
feat: UserController MFA Integration, Device Trust Cookie Management, Audit Wiring, and 2FA Rate Limiting
1 parent a58c823 commit 77c0c4f

20 files changed

Lines changed: 1225 additions & 40 deletions
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php namespace App\Http\Controllers\Traits;
2+
/**
3+
* Copyright 2026 OpenStack Foundation
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
**/
14+
15+
use Auth\User;
16+
use Illuminate\Support\Facades\Config;
17+
use Illuminate\Support\Facades\Cookie;
18+
use Illuminate\Support\Facades\Request;
19+
use Utils\IPHelper;
20+
21+
/**
22+
* Trait MFACookieManager
23+
*
24+
* Reads and queues the trusted-device cookie. All trusted-device persistence
25+
* and validation lives in IDeviceTrustService — this trait contains NO Doctrine,
26+
* repository, or device-lookup logic; it only moves the raw token in and out of
27+
* the HTTP cookie.
28+
*
29+
* The consuming controller MUST expose an IDeviceTrustService instance as
30+
* $this->device_trust_service.
31+
*
32+
* @package App\Http\Controllers\Traits
33+
*/
34+
trait MFACookieManager
35+
{
36+
/**
37+
* Reads the raw trusted-device token from the request cookie.
38+
*
39+
* @return string|null
40+
*/
41+
protected function getCookieToken(): ?string
42+
{
43+
return Request::cookie(Config::get('two_factor.cookie_name', 'device_trust_token'));
44+
}
45+
46+
/**
47+
* Persists a trusted-device record (via IDeviceTrustService) and queues a
48+
* secure, HttpOnly cookie carrying the raw token for the configured lifetime.
49+
*
50+
* @param User $user
51+
* @return void
52+
*/
53+
protected function queueDeviceTrustCookie(User $user): void
54+
{
55+
$rawToken = $this->device_trust_service->trustDevice
56+
(
57+
$user,
58+
Request::header('User-Agent') ?? '',
59+
IPHelper::getUserIp()
60+
);
61+
62+
$name = Config::get('two_factor.cookie_name', 'device_trust_token');
63+
$lifetimeMinutes = intval(Config::get('two_factor.device_trust_lifetime_days', 30)) * 24 * 60;
64+
$path = Config::get('session.path');
65+
$domain = Config::get('session.domain');
66+
$secure = true;
67+
$httpOnly = true;
68+
$raw = false;
69+
$sameSite = 'lax';
70+
71+
// Same order as \Illuminate\Cookie\CookieJar::make()
72+
Cookie::queue
73+
(
74+
$name,
75+
$rawToken, // value
76+
$lifetimeMinutes,
77+
$path,
78+
$domain,
79+
$secure,
80+
$httpOnly,
81+
$raw,
82+
$sameSite
83+
84+
);
85+
}
86+
}

0 commit comments

Comments
 (0)