Laravel change password reset response - php

I'm building an API in Laravel 5.3 and I've to change the default response when a password is being reset.
So how would I do this without making changes to the framework. What I want is this:
In my ResetPasswords trait located here \Illuminate\Foundation\Auth\ResetPasswords
The default response is:
/**
* Get the response for a successful password reset.
*
* #param string $response
* #return \Illuminate\Http\Response
*/
protected function sendResetResponse($response)
{
return redirect($this->redirectPath())
->with('status', trans($response));
}
/**
* Get the response for a failed password reset.
*
* #param \Illuminate\Http\Request
* #param string $response
* #return \Illuminate\Http\Response
*/
protected function sendResetFailedResponse(Request $request, $response)
{
return redirect()->back()
->withInput($request->only('email'))
->withErrors(['email' => trans($response)]);
}
What I want is this:
/**
* Get the response for a successful password reset.
*
* #param string $response
* #return \Illuminate\Http\Response
*/
protected function sendResetResponse($response)
{
return response()->json(['success' => trans($response)]);
}
/**
* Get the response for a failed password reset.
*
* #param \Illuminate\Http\Request
* #param string $response
* #return \Illuminate\Http\Response
*/
protected function sendResetFailedResponse(Request $request, $response)
{
return response()->json(['error' => trans($response)], 401);
}
So how can I accomplish that without making changes to the framework?

Copy the methods in your second codeblock to your ResetPasswordController. This will override the Trait's methods in the controller using it.
By doing so you are not making changes to the Laravel framework and your changes won't be lost on a next composer install.

Related

Authenticated user gets changed after request randomly

I have an issue with laravel's authentication.
After some time, authenticated user changes to random one.
Client is using same internet for 3 devices(users) on a same network to use the site, and this particular bug would appear when they opened two tabs parallelly and used the site - the user on one tab would change to a user that is in those three, or even odder - a user with device that is on a different network and they would get a 419 status code.
I created a cronjob for optimize:clear command to run 2 / hour. Note: this occurs only on production server - i tried to reproduce this locally without success.
Below is my login controller, that is using trait https://laravel.com/api/6.x/Illuminate/Foundation/Auth/AuthenticatesUsers.html
from laravel 6.x, even though my laravel version in project is 7.0.
Only thing i modified from trait is the credentials used in login - instead of email i'm using username.
Since I got no way of solving this one, any help would be appreciated.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Foundation\Auth\RedirectsUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use RedirectsUsers, ThrottlesLogins;
/**
* Show the application's login form.
*
* #return \Illuminate\View\View
*/
public function showLoginForm()
{
return view('auth.login');
}
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
*
* #throws \Illuminate\Validation\ValidationException
*/
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*
* #throws \Illuminate\Validation\ValidationException
*/
protected function validateLogin(Request $request)
{
$request->validate([
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
/**
* Attempt to log the user into the application.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->filled('remember')
);
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
/**
* Send the response after the user was authenticated.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
if ($response = $this->authenticated($request, $this->guard()->user())) {
return $response;
}
return $request->wantsJson()
? new Response('', 204)
: redirect()->intended($this->redirectPath());
}
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
$mode = $user->viewmode;
return redirect()->route($mode . '-mode');
}
/**
* Get the failed login response instance.
*
* #param \Illuminate\Http\Request $request
* #return \Symfony\Component\HttpFoundation\Response
*
* #throws \Illuminate\Validation\ValidationException
*/
protected function sendFailedLoginResponse(Request $request)
{
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
]);
}
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'username';
}
/**
* Log the user out of the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
if ($response = $this->loggedOut($request)) {
return $response;
}
return $request->wantsJson()
? new Response('', 204)
: redirect('/');
}
/**
* The user has logged out of the application.
*
* #param \Illuminate\Http\Request $request
* #return mixed
*/
protected function loggedOut(Request $request)
{
//
}
/**
* Get the guard to be used during authentication.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}

prevent users from unauthorized access of web pages

How can I prevent the users to access my web pages via url browsing. I mean I need to check whether the user is logged in before accessing any web pages. The application should not allow to access the page to user just by url.
Shall I have to check in every controller for authentication or is there any other way?
Suppose I have a controller DistributorController. Now the methods inside this controllers are,
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Session;
use App\Distributor;
class DistributorController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
//
}
function fetchData()
{
$distributors = Distributor::all()->toArray();
return compact('distributors');
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('pages.distributors', $this->fetchData());
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
try{
// code block
}
catch (\Exception $e) {
// code block
}
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
In your web.php file where you define the routes, you can group the routes and surround them using the Auth middleware. You can read more here
I think you may check for the user session for example
if (!$_SESSION['id']){ // if user session is not found
header("location:http://yoursite.index.php"); //redirect anywhere
}
else {
// Your code 'view page'
}
Hope my answer solves it :)

How to create a REST JSON API using Laravel 5.5 or Laravel 5.4

Am just starting out with laravel and i wanted to create a simple rest api that accepts json data and returns a json data but didnt seem to know how to do this. I was wondering if anyone could help.
below is what i want my controller to look like or do:
class MembersController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
//return all members as json
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//leave this as empty
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// get user values as json
// save value to database
// return user data as json.
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//return single user dat as json
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//leave as empty
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//update value and return as json
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//delete value and also return deleted value as json
}
}
How can i achieve the above using laravel. Mostly 5.5 or 5.4.
I dont seem to find anything that could be of help anywhere.
This problem is not too hard; you can get the solution of such problem easily over the internet.
Anyway, you can accomplish this by using array and json_decode like below
$data = ['staus' => 'ok',
'id' => 10,
'name'=>'something',
'address'=>'something'
];
// encode this array to json strig you can use return or echo, print to generate the result
return json_encode($data);
If you want to convert the model objects to json then you can simply use toJson function like below which comes with laravel framework
return ModelName::all()->toJson();
// for a single record retrieval
return ModelName::find(1)->toJson();

login with mobile or email in laravel 5.3

we want to add a functionality where the user can login into our laravel application using their email address or using their mobile.
We are unable to do the same, there is one way we found, but we are not happy since it is inside vendor folder, which can be easily removed!
vendor folder path vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Lang;
trait AuthenticatesUsers
{
use RedirectsUsers, ThrottlesLogins;
/**
* Show the application's login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
return view('auth.login');
}
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', 'password' => 'required',
]);
}
/**
* Attempt to log the user into the application.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
protected function attemptLogin(Request $request)
{
// return $this->guard()->attempt(
// $this->credentials($request), $request->has('remember')
// );
if (Auth::attempt([
'mobile' => $request['username'],
'password' => $request['password']
],$request->has('remember'))
|| Auth::attempt([
'email' => $request['username'],
'password' => $request['password']
],$request->has('remember'))){
return true;
}
return false;
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
/**
* Send the response after the user was authenticated.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
//
}
/**
* Get the failed login response instance.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*/
protected function sendFailedLoginResponse(Request $request)
{
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors([
$this->username() => Lang::get('auth.failed'),
]);
}
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'username';
}
/**
* Log the user out of the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect('/');
}
/**
* Get the guard to be used during authentication.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
}
This is a trait, and your Authentication controller uses this trait. So, you can just override the attemptLogin method to achieve what you want.
In this case, the logic to determine whether to use a mobile number or email would fall under that method.
EDIT
Based on your comment, you need to, actually, copy the attemptLogin method to app/Http/Controllers/Auth/LoginController.php, instead of modifying the vendor files.
It seems you already have some kind of logic going on there. That should handle it.
You can add a custom trait for AuthenticatesUers.php.
Step 1) Create a Trait CustomAuthenticatesUsers.php in app/traits folder.
<?php
namespace App\Traits;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Lang;
use Illuminate\Foundation\Auth\RedirectsUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
trait CustomAuthenticatesUsers
{
use RedirectsUsers, ThrottlesLogins;
/**
* Show the application's login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
if(!session()->has('url.intended'))
{
session(['url.intended' => url()->previous()]);
}
return view('auth.login');
}
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', 'password' => 'required',
]);
}
/**
* Attempt to log the user into the application.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
protected function attemptLogin(Request $request)
{
// return $this->guard()->attempt(
// $this->credentials($request), $request->has('remember')
// );
if (Auth::attempt([
'mobile' => $request['username'],
'password' => $request['password']
],$request->has('remember'))
|| Auth::attempt([
'email' => $request['username'],
'password' => $request['password']
],$request->has('remember'))){
return true;
}
return false;
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
/**
* Send the response after the user was authenticated.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
//
}
/**
* Get the failed login response instance.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*/
protected function sendFailedLoginResponse(Request $request)
{
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors([
$this->username() => Lang::get('auth.failed'),
]);
}
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'username';
}
/**
* Log the user out of the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect('/');
}
/**
* Get the guard to be used during authentication.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
}
Step 2)Add the following Code in LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Traits\CustomAuthenticatesUsers;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use CustomAuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
}

Request Validation with Laravel 5.3

I am trying to validate my api call using laravel built-in request method.
I have used --resource to get make it REST.
OneTimePasswordController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use App\Models\OneTimePassword as Model;
use App\Http\Requests\OneTimePasswordReq;
class OneTimePasswordController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(UserController $user)
{
//
$otps = Model::get();
return response()->json($otps);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(OneTimePasswordReq $request)
{
$insert = Model::create($request->all());
return response()->json($insert);
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
$delete = Model::destroy($id);
return response()->json($delete);
}
}
OneTimePasswordReq
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
class OneTimePasswordReq extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'mobile' => 'required',
'code' => 'required',
];
}
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
/**
* Set custom messages for validator errors.
*
* #return array
*/
public function messages()
{
return [
'mobile.required'=>"Mobile field is required"
];
}
}
If i pass my params, with values, it gets inserted.
Now if i pass a post request with mobile field deleted, i expect a validation errors.
But the call is made to index method which fetches all data from the url.
My understanding is the request is rejected because the params is missing and the question is why its changing to index method and how do i get the errors?
Note : I am aware about $validator->fails() concept, which i don't want to put into my controller as laravel offers this.
As i tested it with postman, it was redirecting to the same route and picking as get.
If called with javascript code, the errors are displayed.
To check with postman, you need add in headers
X-Requested-With: XMLHttpRequest
Thanks to all supporters.

Categories