diff --git a/app/Http/Controllers/API/AuthController.php b/app/Http/Controllers/API/AuthController.php index 5ab92b3f..94bd779a 100644 --- a/app/Http/Controllers/API/AuthController.php +++ b/app/Http/Controllers/API/AuthController.php @@ -17,12 +17,14 @@ use App\User; use Carbon\Carbon; use GuzzleHttp\Client; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use mervick\aesEverywhere\AES256; +use RobThree\Auth\TwoFactorAuth; class AuthController extends Controller { @@ -33,7 +35,7 @@ class AuthController extends Controller */ public function __construct() { - $this->middleware('auth:api', ['except' => ['login', 'forceChangePassword']]); + $this->middleware('auth:api', ['except' => ['login', 'forceChangePassword', 'setupTwoFactorAuthentication']]); } /** @@ -91,6 +93,36 @@ public function login(Request $request) return response()->json(['message' => 'Kullanıcı adı veya şifreniz yanlış.'], 401); } + if (auth('api')->user()->otp_enabled) { + $tfa = app('pragmarx.google2fa'); + + + if (auth('api')->user()->google2fa_secret == null) { + $secret = $tfa->generateSecretKey(); + return response()->json([ + 'message' => 'İki faktörlü doğrulama için Google Authenticator uygulaması ile QR kodunu okutunuz.', + 'secret' => $secret, + 'image' => $tfa->getQRCodeInline( + "Liman", + auth('api')->user()->email, + $secret, + 400 + ), + ], 402); + } + + if (! $request->token) { + return response()->json(['message' => 'İki faktörlü doğrulama gerekmektedir.'], 406); + } else { + if (! $tfa->verifyGoogle2FA( + auth('api')->user()->google2fa_secret, + $request->token + )) { + return response()->json(['message' => 'İki faktörlü doğrulama başarısız.'], 406); + } + } + } + if (auth('api')->user()->forceChange) { return response()->json(['message' => 'Şifrenizi değiştirmeniz gerekmektedir.'], 405); } @@ -98,6 +130,39 @@ public function login(Request $request) return $this->createNewToken($token, $request); } + /** + * Setup Two Factor Authentication + * + * @return JsonResponse + */ + public function setupTwoFactorAuthentication(Request $request) + { + $validator = Validator::make($request->all(), [ + 'email' => 'required|string', + 'password' => 'required|string', + 'secret' => 'required' + ]); + + if ($validator->fails()) { + return response()->json($validator->errors(), 422); + } + + $token = auth('api')->attempt([ + 'email' => $validator->validated()["email"], + 'password' => $validator->validated()["password"], + ]); + if (! $token) { + return response()->json(['message' => 'Kullanıcı adı veya şifreniz yanlış.'], 401); + } + + User::find(auth('api')->user()->id)->update([ + 'otp_enabled' => true, + 'google2fa_secret' => $request->secret + ]); + + return response()->json(['message' => '2FA kurulumu başarıyla yapıldı.']); + } + /** * Log the user out (Invalidate the token). * diff --git a/app/Http/Controllers/API/ProfileController.php b/app/Http/Controllers/API/ProfileController.php index 4b24f979..847cf56d 100644 --- a/app/Http/Controllers/API/ProfileController.php +++ b/app/Http/Controllers/API/ProfileController.php @@ -55,8 +55,15 @@ public function setInformation(Request $request) $user->update([ 'name' => $request->name, 'email' => $request->email, + 'otp_enabled' => (bool) $request->otp_enabled, ]); + if (! (bool) $request->otp_enabled) { + $user->update([ + 'google2fa_secret' => null + ]); + } + return response()->json([ 'message' => 'Bilgiler başarıyla güncellendi.', 'user' => $user, diff --git a/app/Http/Controllers/API/Settings/TweaksController.php b/app/Http/Controllers/API/Settings/TweaksController.php index 9d2a748e..26180db4 100644 --- a/app/Http/Controllers/API/Settings/TweaksController.php +++ b/app/Http/Controllers/API/Settings/TweaksController.php @@ -18,7 +18,6 @@ public function getConfiguration() { return response()->json([ 'APP_LANG' => env('APP_LANG'), - 'OTP_ENABLED' => (bool) env('OTP_ENABLED', 'false'), 'APP_NOTIFICATION_EMAIL' => env('APP_NOTIFICATION_EMAIL'), 'APP_URL' => env('APP_URL'), 'EXTENSION_TIMEOUT' => env('EXTENSION_TIMEOUT', 30), @@ -48,7 +47,6 @@ public function saveConfiguration(Request $request) setEnv([ 'APP_LANG' => $request->APP_LANG, - 'OTP_ENABLED' => (bool) $request->OTP_ENABLED, 'APP_NOTIFICATION_EMAIL' => $request->APP_NOTIFICATION_EMAIL, 'APP_URL' => $request->APP_URL, 'EXTENSION_TIMEOUT' => $request->EXTENSION_TIMEOUT, @@ -63,7 +61,6 @@ public function saveConfiguration(Request $request) 'edit', [ 'APP_LANG' => $request->APP_LANG, - 'OTP_ENABLED' => (bool) $request->OTP_ENABLED, 'APP_NOTIFICATION_EMAIL' => $request->APP_NOTIFICATION_EMAIL, 'APP_URL' => $request->APP_URL, 'EXTENSION_TIMEOUT' => $request->EXTENSION_TIMEOUT, diff --git a/app/Http/Controllers/API/Settings/UserController.php b/app/Http/Controllers/API/Settings/UserController.php index 90c967aa..32d58161 100644 --- a/app/Http/Controllers/API/Settings/UserController.php +++ b/app/Http/Controllers/API/Settings/UserController.php @@ -25,7 +25,8 @@ class UserController extends Controller */ public function index() { - return User::all(); + return User::orderBy('last_login_at', 'desc') + ->get(); } /** diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 76b50882..b70d12f8 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -54,8 +54,7 @@ class Kernel extends HttpKernel 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'extension' => \App\Http\Middleware\Extension::class, 'block_except_limans' => \App\Http\Middleware\BlockExceptLimans::class, - 'google2fa' => \PragmaRX\Google2FALaravel\Middleware::class, - 'check_google_two_factor' => \App\Http\Middleware\CheckGoogleTwoFactor::class, + 'google2fa' => \PragmaRX\Google2FALaravel\MiddlewareStateless::class, 'upload_token_check' => \App\Http\Middleware\LimanTokenUploadCheck::class, ]; diff --git a/app/Http/Middleware/CheckGoogleTwoFactor.php b/app/Http/Middleware/CheckGoogleTwoFactor.php deleted file mode 100644 index 8456d92f..00000000 --- a/app/Http/Middleware/CheckGoogleTwoFactor.php +++ /dev/null @@ -1,30 +0,0 @@ -user()->google2fa_secret) { - return redirect()->route('registerGoogleAuth'); - } - } - - return $next($request); - } -} diff --git a/app/User.php b/app/User.php index f6acdf73..5feed400 100644 --- a/app/User.php +++ b/app/User.php @@ -49,7 +49,8 @@ class User extends Authenticatable implements JWTSubject 'last_login_at', 'last_login_ip', 'locale', - 'google2fa_secret' + 'google2fa_secret', + 'otp_enabled' ]; /** diff --git a/composer.lock b/composer.lock index 84e1eb09..be8e28fb 100644 --- a/composer.lock +++ b/composer.lock @@ -11264,5 +11264,5 @@ "ext-zip": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/config/google2fa.php b/config/google2fa.php index d4d1a684..22deb9dd 100644 --- a/config/google2fa.php +++ b/config/google2fa.php @@ -5,7 +5,7 @@ /* * Enable / disable Google2FA. */ - 'enabled' => env('OTP_ENABLED', false), + 'enabled' => env('OTP_ENABLED', true), /* * Lifetime in minutes. @@ -27,7 +27,7 @@ /* * Guard. */ - 'guard' => '', + 'guard' => 'api', /* * 2FA verified session var. @@ -37,7 +37,7 @@ /* * One Time Password request input name. */ - 'otp_input' => 'one_time_password', + 'otp_input' => 'token', /* * One Time Password Window. diff --git a/database/migrations/2023_10_13_091138_add_2fa_enabled_column_to_users_table.php b/database/migrations/2023_10_13_091138_add_2fa_enabled_column_to_users_table.php new file mode 100644 index 00000000..1c449f7a --- /dev/null +++ b/database/migrations/2023_10_13_091138_add_2fa_enabled_column_to_users_table.php @@ -0,0 +1,32 @@ +boolean('otp_enabled')->default(false)->after('locale'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + // + }); + } +}; diff --git a/routes/api.php b/routes/api.php index c50fcf5e..939aede9 100644 --- a/routes/api.php +++ b/routes/api.php @@ -26,6 +26,7 @@ 'prefix' => 'auth' ], function () { Route::post('/login', [AuthController::class, 'login']); + Route::post('/setup_mfa', [AuthController::class, 'setupTwoFactorAuthentication']); Route::post('/register', [AuthController::class, 'register']); Route::post('/logout', [AuthController::class, 'logout']); Route::post('/refresh', [AuthController::class, 'refresh']); diff --git a/storage/build_tools/DEBIAN/postinst b/storage/build_tools/DEBIAN/postinst index a7b2bc43..d2aa4705 100644 --- a/storage/build_tools/DEBIAN/postinst +++ b/storage/build_tools/DEBIAN/postinst @@ -189,8 +189,8 @@ fi if [ -f "/etc/systemd/system/liman-ui.service" ]; then echo "Liman User Interface Service Already Added."; ENVIRONMENT_SET=$(cat /etc/systemd/system/liman-ui.service | grep Environment >/dev/null && echo 1 || echo 0) - if [ $ENVIRONMENT_SET == "0" ]; then - sed -i '/\[Service\]/a Environment="HOSTNAME=127.0.0.1"' /etc/systemd/system/liman-ui.service + if [ $ENVIRONMENT_SET == "1" ]; then + sed -i '/Environment="HOSTNAME=127.0.0.1"/d' /etc/systemd/system/liman-ui.service fi else echo """ @@ -204,7 +204,6 @@ Restart=always RestartSec=1 User=liman WorkingDirectory=/liman/ui -Environment="HOSTNAME=127.0.0.1" ExecStart=/usr/bin/node server.js [Install] diff --git a/storage/build_tools/rhel/liman.spec b/storage/build_tools/rhel/liman.spec index a9843eb2..02f02acc 100644 --- a/storage/build_tools/rhel/liman.spec +++ b/storage/build_tools/rhel/liman.spec @@ -188,10 +188,6 @@ fi # Create UI Systemd Service if [ -f "/etc/systemd/system/liman-ui.service" ]; then echo "Liman User Interface Service Already Added."; - ENVIRONMENT_SET=$(cat /etc/systemd/system/liman-ui.service | grep Environment >/dev/null && echo 1 || echo 0) - if [ $ENVIRONMENT_SET == "0" ]; then - sed -i '/\[Service\]/a Environment="HOSTNAME=127.0.0.1"' /etc/systemd/system/liman-ui.service - fi else echo """ [Unit]