mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-10 07:34:06 -08:00
Merge pull request #11358 from snipe/fixes/missing_token_lang
Fixed missing password.token string and checked for user existing before attempting to send reset email
This commit is contained in:
commit
89c234b1c2
|
@ -146,7 +146,13 @@ AWS_DEFAULT_REGION=null
|
|||
# --------------------------------------------
|
||||
LOGIN_MAX_ATTEMPTS=5
|
||||
LOGIN_LOCKOUT_DURATION=60
|
||||
RESET_PASSWORD_LINK_EXPIRES=900
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: FORGOTTEN PASSWORD SETTINGS
|
||||
# --------------------------------------------
|
||||
RESET_PASSWORD_LINK_EXPIRES=15
|
||||
PASSWORD_CONFIRM_TIMEOUT=10800
|
||||
PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN=50
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MISC
|
||||
|
|
|
@ -24,6 +24,7 @@ class Kernel extends ConsoleKernel
|
|||
$schedule->command('snipeit:backup')->weekly();
|
||||
$schedule->command('backup:clean')->daily();
|
||||
$schedule->command('snipeit:upcoming-audits')->daily();
|
||||
$schedule->command('auth:clear-resets')->everyFifteenMinutes();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -136,13 +136,12 @@ class LoginController extends Controller
|
|||
|
||||
// Better logging
|
||||
if (!$saml->isEnabled()) {
|
||||
\Log::warning("SAML page requested, but SAML does not seem to enabled.");
|
||||
\Log::debug("SAML page requested, but SAML does not seem to enabled.");
|
||||
} else {
|
||||
\Log::warning("SAML page requested, but samlData seems empty.");
|
||||
}
|
||||
}
|
||||
|
||||
\Log::warning("Something else went wrong while trying to login as SAML user");
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\SaveUserRequest;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
|
@ -63,6 +61,14 @@ class ResetPasswordController extends Controller
|
|||
|
||||
public function showResetForm(Request $request, $token = null)
|
||||
{
|
||||
|
||||
$credentials = $request->only('email', 'token');
|
||||
|
||||
if (is_null($this->broker()->getUser($credentials))) {
|
||||
\Log::debug('Password reset form FAILED - this token is not valid.');
|
||||
return redirect()->route('password.request')->with('error', trans('passwords.token'));
|
||||
}
|
||||
|
||||
return view('auth.passwords.reset')->with(
|
||||
[
|
||||
'token' => $token,
|
||||
|
@ -73,38 +79,53 @@ class ResetPasswordController extends Controller
|
|||
|
||||
public function reset(Request $request)
|
||||
{
|
||||
|
||||
$broker = $this->broker();
|
||||
|
||||
$messages = [
|
||||
'password.not_in' => trans('validation.disallow_same_pwd_as_user_fields'),
|
||||
];
|
||||
|
||||
$request->validate($this->rules(), $request->all(), $this->validationErrorMessages());
|
||||
|
||||
// Check to see if the user even exists
|
||||
$user = User::where('username', '=', $request->input('username'))->first();
|
||||
\Log::debug('Checking if '.$request->input('username').' exists');
|
||||
// Check to see if the user even exists - we'll treat the response the same to prevent user sniffing
|
||||
if ($user = User::where('username', '=', $request->input('username'))->where('activated', '1')->whereNotNull('email')->first()) {
|
||||
\Log::debug($user->username.' exists');
|
||||
|
||||
|
||||
// handle the password validation rules set by the admin settings
|
||||
if (strpos(Setting::passwordComplexityRulesSaving('store'), 'disallow_same_pwd_as_user_fields') !== false) {
|
||||
$request->validate(
|
||||
[
|
||||
'password' => 'required|notIn:["'.$user->email.'","'.$user->username.'","'.$user->first_name.'","'.$user->last_name.'"',
|
||||
], $messages);
|
||||
}
|
||||
|
||||
|
||||
// set the response
|
||||
$response = $broker->reset(
|
||||
$this->credentials($request), function ($user, $password) {
|
||||
$this->resetPassword($user, $password);
|
||||
});
|
||||
|
||||
// Check if the password reset above actually worked
|
||||
if ($response == \Password::PASSWORD_RESET) {
|
||||
\Log::debug('Password reset for '.$user->username.' worked');
|
||||
return redirect()->guest('login')->with('success', trans('passwords.reset'));
|
||||
}
|
||||
|
||||
\Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
|
||||
return redirect()->back()->withInput($request->only('email'))->with('error', trans('passwords.token'));
|
||||
|
||||
$broker = $this->broker();
|
||||
if (strpos(Setting::passwordComplexityRulesSaving('store'), 'disallow_same_pwd_as_user_fields') !== false) {
|
||||
$request->validate(
|
||||
[
|
||||
'password' => 'required|notIn:["'.$user->email.'","'.$user->username.'","'.$user->first_name.'","'.$user->last_name.'"',
|
||||
], $messages);
|
||||
}
|
||||
|
||||
$response = $broker->reset(
|
||||
$this->credentials($request), function ($user, $password) {
|
||||
$this->resetPassword($user, $password);
|
||||
}
|
||||
);
|
||||
|
||||
return $response == \Password::PASSWORD_RESET
|
||||
? $this->sendResetResponse($request, $response)
|
||||
: $this->sendResetFailedResponse($request, $response);
|
||||
\Log::debug('Password reset for '.$request->input('username').' FAILED - user does not exist or does not have an email address - but make it look like it succeeded');
|
||||
return redirect()->guest('login')->with('success', trans('passwords.reset'));
|
||||
|
||||
}
|
||||
|
||||
protected function sendResetFailedResponse(Request $request, $response)
|
||||
{
|
||||
return redirect()->back()
|
||||
->withInput(['username'=> $request->input('username')])
|
||||
->withErrors(['username' => trans($response), 'password' => trans($response)]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -75,12 +75,22 @@ class RouteServiceProvider extends ServiceProvider
|
|||
/**
|
||||
* Configure the rate limiters for the application.
|
||||
*
|
||||
* https://laravel.com/docs/8.x/routing#rate-limiting
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configureRateLimiting()
|
||||
{
|
||||
|
||||
// Rate limiter for API calls
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
|
||||
return Limit::perMinute(config('app.api_throttle_per_minute'))->by(optional($request->user())->id ?: $request->ip());
|
||||
});
|
||||
|
||||
// Rate limiter for forgotten password requests
|
||||
RateLimiter::for('forgotten_password', function (Request $request) {
|
||||
return Limit::perMinute(config('auth.password_reset.max_attempts_per_min'))->by(optional($request->user())->id ?: $request->ip());
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,14 +98,27 @@ return [
|
|||
'email' => 'auth.emails.password',
|
||||
'table' => 'password_resets',
|
||||
'expire' => env('RESET_PASSWORD_LINK_EXPIRES', 900),
|
||||
'throttle' => 60,
|
||||
'throttle' => [
|
||||
'max_attempts' => env('LOGIN_MAX_ATTEMPTS', 5),
|
||||
|
||||
'lockout_duration' => env('LOGIN_LOCKOUT_DURATION', 60),
|
||||
]
|
||||
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Resetting Password Requests
|
||||
|--------------------------------------------------------------------------
|
||||
| This sets the throttle for forgotten password requests
|
||||
|
|
||||
*/
|
||||
'password_reset' => [
|
||||
'max_attempts_per_min' => env('PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN', 50),
|
||||
],
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Confirmation Timeout
|
||||
|
@ -117,6 +130,6 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'password_timeout' => 10800,
|
||||
'password_timeout' => env('PASSWORD_CONFIRM_TIMEOUT', 10800),
|
||||
|
||||
];
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'sent' => 'Success: If that email address exists in our system, a password recovery email has been sent.',
|
||||
'user' => 'No matching active user found with that email.',
|
||||
'sent' => 'If a matching user with a valid email address exists in our system, a password recovery email has been sent.',
|
||||
'user' => 'If a matching user with a valid email address exists in our system, a password recovery email has been sent.',
|
||||
'token' => 'This password reset token is invalid or expired, or does not match the username provided.',
|
||||
'reset' => 'Your password has been reset!',
|
||||
];
|
||||
|
|
|
@ -14,11 +14,8 @@ return array(
|
|||
*/
|
||||
|
||||
"password" => "Passwords must be six characters and match the confirmation.",
|
||||
|
||||
"user" => "Username or email address is incorrect",
|
||||
|
||||
"token" => "This password reset token is invalid.",
|
||||
|
||||
"sent" => "If a matching email address was found, a password reminder has been sent!",
|
||||
"token" => 'This password reset token is invalid or expired, or does not match the username provided.',
|
||||
'sent' => 'If a matching user with a valid email address exists in our system, a password recovery email has been sent.',
|
||||
|
||||
);
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
@if (($snipeSettings) && ($snipeSettings->logo!=''))
|
||||
<center>
|
||||
<img id="login-logo" src="{{ Storage::disk('public')->url('').e($snipeSettings->logo) }}">
|
||||
<a href="{{ config('app.url') }}"><img id="login-logo" src="{{ Storage::disk('public')->url('').e($snipeSettings->logo) }}"></a>
|
||||
</center>
|
||||
@endif
|
||||
<!-- Content -->
|
||||
|
|
|
@ -16,7 +16,7 @@ use Illuminate\Support\Facades\Route;
|
|||
|
|
||||
*/
|
||||
|
||||
Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:'.config('app.api_throttle_per_minute').',1']], function () {
|
||||
Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], function () {
|
||||
|
||||
|
||||
Route::get('/', function () {
|
||||
|
|
|
@ -20,6 +20,8 @@ use App\Http\Controllers\StatuslabelsController;
|
|||
use App\Http\Controllers\SuppliersController;
|
||||
use App\Http\Controllers\ViewAssetsController;
|
||||
use App\Http\Controllers\Auth\LoginController;
|
||||
use App\Http\Controllers\Auth\ForgotPasswordController;
|
||||
use App\Http\Controllers\Auth\ResetPasswordController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
|
@ -426,6 +428,39 @@ Route::group(['middleware' => 'web'], function () {
|
|||
[LoginController::class, 'postTwoFactorAuth']
|
||||
);
|
||||
|
||||
|
||||
|
||||
Route::post(
|
||||
'password/email',
|
||||
[ForgotPasswordController::class, 'sendResetLinkEmail']
|
||||
)->name('password.email')->middleware('throttle:forgotten_password');
|
||||
|
||||
Route::get(
|
||||
'password/reset',
|
||||
[ForgotPasswordController::class, 'showLinkRequestForm']
|
||||
)->name('password.request')->middleware('throttle:forgotten_password');
|
||||
|
||||
|
||||
Route::post(
|
||||
'password/reset',
|
||||
[ResetPasswordController::class, 'reset']
|
||||
)->name('password.update')->middleware('throttle:forgotten_password');
|
||||
|
||||
Route::get(
|
||||
'password/reset/{token}',
|
||||
[ResetPasswordController::class, 'showResetForm']
|
||||
)->name('password.reset');
|
||||
|
||||
|
||||
Route::post(
|
||||
'password/email',
|
||||
[ForgotPasswordController::class, 'sendResetLinkEmail']
|
||||
)->name('password.email')->middleware('throttle:forgotten_password');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Route::get(
|
||||
'/',
|
||||
[
|
||||
|
@ -446,7 +481,7 @@ Route::group(['middleware' => 'web'], function () {
|
|||
)->name('logout');
|
||||
});
|
||||
|
||||
Auth::routes();
|
||||
//Auth::routes();
|
||||
|
||||
Route::get(
|
||||
'/health',
|
||||
|
|
Loading…
Reference in a new issue