Skip to content

Commit 97dc956

Browse files
committed
Challenge-Response Authentication
1 parent bd9b4d7 commit 97dc956

28 files changed

+538
-329
lines changed

app/Auth/NexusWebGuard.php

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ public function user()
4646
}
4747
$credentials = $this->request->cookie();
4848
if ($this->validate($credentials)) {
49-
$user = $this->user;
49+
$user = $this->provider->retrieveByCredentials($credentials);
5050
if ($this->provider->validateCredentials($user, $credentials)) {
51-
return $user;
51+
if ($user->checkIsNormal()) {
52+
return $this->user = $user;
53+
}
5254
}
5355
}
5456
}
@@ -62,29 +64,13 @@ public function user()
6264
*/
6365
public function validate(array $credentials = [])
6466
{
65-
$required = ['c_secure_pass', 'c_secure_uid', 'c_secure_login'];
67+
$required = ['c_secure_pass'];
6668
foreach ($required as $value) {
6769
if (empty($credentials[$value])) {
6870
return false;
6971
}
7072
}
71-
$b_id = base64($credentials["c_secure_uid"],false);
72-
$id = intval($b_id ?? 0);
73-
if (!$id || !is_valid_id($id) || strlen($credentials["c_secure_pass"]) != 32) {
74-
return false;
75-
}
76-
$user = $this->provider->retrieveById($id);
77-
if (!$user) {
78-
return false;
79-
}
80-
try {
81-
$user->checkIsNormal();
82-
$this->user = $user;
83-
return true;
84-
} catch (\Throwable $e) {
85-
do_log($e->getMessage());
86-
return false;
87-
}
73+
return true;
8874
}
8975

9076
public function logout()

app/Auth/NexusWebUserProvider.php

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,15 @@ public function updateRememberToken(Authenticatable $user, $token)
6161
*/
6262
public function retrieveByCredentials(array $credentials)
6363
{
64-
if (!empty($credentials['c_secure_uid'])) {
65-
$b_id = base64($credentials["c_secure_uid"],false);
66-
return $this->query->find($b_id);
64+
list($tokenJson, $signature) = explode('.', base64_decode($credentials["c_secure_pass"]));
65+
if (empty($tokenJson) || empty($signature)) {
66+
return null;
6767
}
68+
$tokenData = json_decode($tokenJson, true);
69+
if (!isset($tokenData['user_id'])) {
70+
return null;
71+
}
72+
return $this->retrieveById($tokenData['user_id']);
6873
}
6974

7075
/**
@@ -76,20 +81,9 @@ public function retrieveByCredentials(array $credentials)
7681
*/
7782
public function validateCredentials(Authenticatable $user, array $credentials)
7883
{
79-
if ($credentials["c_secure_login"] == base64("yeah")) {
80-
/**
81-
* Not IP related
82-
* @since 1.8.0
83-
*/
84-
if ($credentials["c_secure_pass"] != md5($user->passhash)) {
85-
return false;
86-
}
87-
} else {
88-
if ($credentials["c_secure_pass"] !== md5($user->passhash)) {
89-
return false;
90-
}
91-
}
92-
return true;
84+
list($tokenJson, $signature) = explode('.', base64_decode($credentials["c_secure_pass"]));
85+
$expectedSignature = hash_hmac('sha256', $tokenJson, $user->auth_key);
86+
return hash_equals($expectedSignature, $signature);
9387
}
9488

9589
public function rehashPasswordIfRequired(Authenticatable $user, #[\SensitiveParameter] array $credentials, bool $force = false)

app/Console/Commands/Test.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ public function __construct()
4949
*/
5050
public function handle()
5151
{
52-
$r = config('nexus.ammds_secret');
53-
// $r = SearchBox::query()->find(4)->ss()->orWhere("mode", 0)->get();
54-
dd($r);
52+
$result = getLogFile();
53+
dd($result);
5554
}
5655

5756
}

app/Http/Controllers/AuthenticateController.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Illuminate\Support\Facades\Auth;
1717
use Illuminate\Support\Facades\Cookie;
1818
use Illuminate\Validation\Rule;
19+
use Nexus\Database\NexusDB;
1920

2021
class AuthenticateController extends Controller
2122
{
@@ -53,17 +54,18 @@ public function passkeyLogin($passkey)
5354
{
5455
$deadline = Setting::get('security.login_secret_deadline');
5556
if ($deadline && $deadline > now()->toDateTimeString()) {
56-
$user = User::query()->where('passkey', $passkey)->first(['id', 'passhash']);
57+
$user = User::query()->where('passkey', $passkey)->first(['id', 'passhash', 'secret', 'auth_key']);
5758
if ($user) {
5859
$ip = getip();
5960
/**
6061
* Not IP related
6162
* @since 1.8.0
6263
*/
6364
// $passhash = md5($user->passhash . $ip);
64-
$passhash = md5($user->passhash);
65-
do_log(sprintf('passhash: %s, ip: %s, md5: %s', $user->passhash, $ip, $passhash));
66-
logincookie($user->id, $passhash,false, get_setting('system.cookie_valid_days', 365) * 86400, true, true, true);
65+
// $passhash = md5($user->passhash);
66+
// do_log(sprintf('passhash: %s, ip: %s, md5: %s', $user->passhash, $ip, $passhash));
67+
// logincookie($user->id, $passhash,false, get_setting('system.cookie_valid_days', 365) * 86400, true, true, true);
68+
logincookie($user->id, $user->auth_key);
6769
$user->last_login = now();
6870
$user->save();
6971
$userRep = new UserRepository();
@@ -126,6 +128,29 @@ public function ammdsApprove(Request $request)
126128
}
127129
}
128130

131+
public function challenge(Request $request)
132+
{
133+
try {
134+
$request->validate([
135+
'username' => 'required|string',
136+
]);
137+
$username = $request->username;
138+
$challenge = mksecret();
139+
NexusDB::cache_put(get_challenge_key($username), $challenge,300);
140+
$user = User::query()->where("username", $username)->first(['secret']);
141+
return $this->success([
142+
"challenge" => $challenge,
143+
'secret' => $user->secret ?? mksecret(),
144+
]);
145+
} catch (\Exception $exception) {
146+
$msg = $exception->getMessage();
147+
$params = $request->all();
148+
do_log(sprintf("challenge fail: %s, params: %s", $msg, nexus_json_encode($params)));
149+
return $this->fail($params, $msg);
150+
}
151+
}
152+
153+
129154

130155

131156

app/Models/Setting.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,9 @@ public static function getDefaultLang()
105105
return self::get("main.defaultlang");
106106
}
107107

108+
public static function getIsUseChallengeResponseAuthentication(): bool
109+
{
110+
return self::get("security.use_challenge_response_authentication") == "yes";
111+
}
112+
108113
}

app/Models/User.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ protected function serializeDate(\DateTimeInterface $date): string
194194
* @var array
195195
*/
196196
protected $hidden = [
197-
'secret', 'passhash', 'passkey'
197+
'secret', 'passhash', 'passkey', 'auth_key'
198198
];
199199

200200
/**

app/Providers/AuthServiceProvider.php

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ class AuthServiceProvider extends ServiceProvider
5353
*/
5454
public function boot()
5555
{
56+
//some plugin use this guard
5657
Auth::viaRequest('nexus-cookie', function (Request $request) {
57-
return $this->getUserByCookie($request->cookie());
58+
return get_user_from_cookie($request->cookie(), false);
5859
});
5960

6061
Auth::extend('nexus-web', function ($app, $name, array $config) {
@@ -72,33 +73,4 @@ public function boot()
7273

7374
}
7475

75-
private function getUserByCookie($cookie)
76-
{
77-
if (empty($cookie["c_secure_pass"]) || empty($cookie["c_secure_uid"]) || empty($cookie["c_secure_login"])) {
78-
return null;
79-
}
80-
$b_id = base64($cookie["c_secure_uid"],false);
81-
$id = intval($b_id ?? 0);
82-
if (!$id || !is_valid_id($id) || strlen($cookie["c_secure_pass"]) != 32) {
83-
return null;
84-
}
85-
$user = User::query()->find($id);
86-
if (!$user) {
87-
return null;
88-
}
89-
if ($cookie["c_secure_login"] == base64("yeah")) {
90-
/**
91-
* Not IP related
92-
* @since 1.8.0
93-
*/
94-
if ($cookie["c_secure_pass"] != md5($user->passhash)) {
95-
return null;
96-
}
97-
} else {
98-
if ($cookie["c_secure_pass"] !== md5($user->passhash)) {
99-
return null;
100-
}
101-
}
102-
return $user;
103-
}
10476
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('users', function (Blueprint $table) {
15+
$table->string("passhash", 255)->default("")->nullable(false)->change();
16+
});
17+
}
18+
19+
/**
20+
* Reverse the migrations.
21+
*/
22+
public function down(): void
23+
{
24+
//
25+
}
26+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('users', function (Blueprint $table) {
15+
$table->string("auth_key", 255)->default("")->nullable(false)->after("secret");
16+
});
17+
}
18+
19+
/**
20+
* Reverse the migrations.
21+
*/
22+
public function down(): void
23+
{
24+
Schema::table('users', function (Blueprint $table) {
25+
$table->dropColumn("auth_key");
26+
});
27+
}
28+
};

0 commit comments

Comments
 (0)