all(), [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'confirmed', Password::defaults()], ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } $user = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), ]); $token = $user->createToken('auth_token')->plainTextToken; return response()->json([ 'message' => __('auth.registered'), 'user' => $user, 'token' => $token, ], 201); } public function login(Request $request) { $validator = Validator::make($request->all(), [ 'email' => ['required', 'string', 'email'], 'password' => ['required', 'string'], ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } $user = User::where('email', $request->email)->first(); if (!$user || !Hash::check($request->password, $user->password)) { return response()->json([ 'message' => __('auth.failed'), ], 401); } // Check if 2FA is enabled if ($user->isTwoFactorEnabled()) { return response()->json([ 'requires_2fa' => true, 'user_id' => $user->id, 'message' => __('auth.2fa_required'), ]); } $token = $user->createToken('auth_token')->plainTextToken; return response()->json([ 'message' => __('auth.logged_in'), 'user' => $user, 'token' => $token, ]); } public function verify2FA(Request $request) { $validator = Validator::make($request->all(), [ 'user_id' => ['required', 'integer', 'exists:users,id'], 'code' => ['required', 'string', 'size:6'], ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } $user = User::find($request->user_id); if (!$user || !$user->isTwoFactorEnabled()) { return response()->json(['message' => __('auth.2fa_not_enabled')], 400); } $google2fa = app('pragmarx.google2fa'); $secret = $user->getTwoFactorSecret(); $valid = $google2fa->verifyKey($secret, $request->code); if (!$valid) { // Check recovery codes $recoveryCodes = $user->two_factor_recovery_codes ?? []; if (in_array($request->code, $recoveryCodes)) { // Remove used recovery code $user->two_factor_recovery_codes = array_diff($recoveryCodes, [$request->code]); $user->save(); $valid = true; } } if (!$valid) { return response()->json(['message' => __('auth.2fa_invalid')], 401); } $token = $user->createToken('auth_token')->plainTextToken; return response()->json([ 'message' => __('auth.logged_in'), 'user' => $user, 'token' => $token, ]); } public function logout(Request $request) { $request->user()->currentAccessToken()->delete(); return response()->json([ 'message' => __('auth.logged_out'), ]); } public function user(Request $request) { return response()->json([ 'user' => $request->user(), ]); } }