Laravel - Delete Cookie in Middleware - laravel

I have a middleware in my project that call in every request. It will check if Request has a specific cookie, then delete another cookie. But it seems Cookies are not forgotten or set in Laravel until return in the response. something like
return response('view')->withCookie($cookie); that is not possible in middlewares.
Also I tried Cookie::queue(Cookie::forget('myCookie')); nothing happened and cookie is shown in my browser.
This is my middleware handle method:
public function handle(Request $request, Closure $next)
{
if (! $request->cookie('clear_token')) {
cookie()->forget('access_token'); # not worked
Cookie::queue(Cookie::forget('access_token')); # not worked
}
return $next($request);
}

You can change the response in middleware too:
https://laravel.com/docs/5.0/middleware
<?php namespace App\Http\Middleware;
class AfterMiddleware implements Middleware {
public function handle(\Illuminate\Http\Request $request, \Closure $next)
{
$response = $next($request);
// Forget cookie
return $response;
}
}

Related

Laravel - change route in middleware

Let's say I have this kind of URLs :
example.com/en/
example.com/en/login
example.com/fr/login
I would like to use a middleware to set the language and then return the route to be handled without the language part. So the router would get / or /login, without any language stuff.
public function handle(Request $request, Closure $next) {
app()->setLocale($request->segment(1));
// $request->server->set('REQUEST_URI', substr($_SERVER['REQUEST_URI'], 4));// not working
return $next($request);
}
I would suggest to store the language in session and use a middleware to setLocale.
Working example
SetLocale.php middleware
public function handle($request, Closure $next)
{
if (Session::has('language'))
{
App::setLocale(strtolower(Session::get('language')));
}
return $next($request);
}
Controller function to set language to session
public function setLanguage(string $language)
{
if (Session::has('language'))
{
Session::forget('language');
}
Session::put('language', $language);
return redirect()->back();
}
So now on everything that happens on the website, the middleware will check the language and set it to what's in session.
Also don't forget to specify the middleware in $middlewareGroups in app\Http\Kernel.php
You can create a form anywhere on website for the user to choose his language preference with a route to the controller function.

Custom Auth Middleware not redirecting properly for unauthorized user

I have created a custom auth controller for recognising unauthorized user and redirect them to login path. If logged in the middlewre is working absolutely fine, but showing error if not logged in. Here is my code
Middleware:
class CheckUserAuthenticated
{
public function handle($request, Closure $next)
{
if(auth()->check()) {
$user_id = auth()->user()->id;
define('authenticated_user_id' ,$user_id);
return $next($request);
}
return redirect('login'); // this code is not working
}
}
Error:
try this hope it help
public function handle($request, Closure $next)
{
if(auth()->check()) {
$user_id = auth()->user()->id;
define('authenticated_user_id' ,$user_id);
return $next($request);
}
return redirect('/login'); OR return redirect(route('login'));
}
class CheckUserAuthenticated
{
public function handle($request, Closure $next)
{
if(auth()->check()) {
$user_id = auth()->user()->id;
define('authenticated_user_id' ,$user_id);
return $next($request);
}
// return redirect('login'); // this code is not working
return redirect()->guest('/login');
}
}
redirect()->guest() will redirect if there is no authenticated user.
Example: If an authenticated user is logged in, it won't redirect them as they aren't a guest. If a user isn't logged in, the redirect will happen.
The issue is in circular routing, you are calling from one route, and then return to the same route from the middleware, so your request never reaches the endpoint.
if you call middleware on the...
Route::get('login')->middleware('auth);
...then middleware can not route to 'login' on the fail...
return redirect('login');
... because it will create the loop that never ends. The middleware should reroute to something else, or be placed on other route like 'admin'...
You probably have the middleware on the 'login', that creates the loop, just remove it.

Conditionally set a URL to redirect to after authentication

In my app, a post author can set an otherwise public post to private. If an unauthenticated user tries to visit that post, they will be prompted to login.
After they authenticate, I want to redirect them back to the original post URL, so they can read that private post.
This behavior is normally handled by Laravel's default auth middleware. However, because the posts are often public, I can't use that in this case.
Here's my current, non-functioning middleware:
public function handle($request, Closure $next)
{
$post = $request->route('post');
if ($post->isPrivate()) {
$request->session()->setPreviousUrl($request->url());
return redirect()->guest('login');
}
return $next($request);
}
My hope is that I can set a custom URL to redirect to (/posts/{id}). However, when I try to login, I'm redirected to my default $redirectTo property (/dashboard).
Is this something that's feasible? Am I even thinking about this in the correct way?
#adam, thanks for the assist!
For anyone else looking, here's my final code:
Middleware:
public function handle($request, Closure $next)
{
if (auth()->check()) {
return $next($request);
}
$post = $request->route('post');
if ($post->isPrivate()) {
$request->session()->setPreviousUrl($request->path());
return redirect()->guest('login');
}
return $next($request);
}
LoginController:
protected function authenticated(Request $request, $user)
{
if ($request->session()->has('url.intended')) {
return redirect($request->session()->get('url.intended'));
}
}

Laravel Middleware changing header before passing to controller

I'm trying to change the header of my request before passing it to the controller using a middleware but it seems $next($request) executes the code in my controller. Is there a way to change the header then send the updated request to my controller?
My middleware:
class JWTAuthenticator
{
public function handle($request, Closure $next)
{
$token =JWTAuth::getToken();
$my_new_token = JWTAuth::refresh($token);
//it runs here
$response = $next($request);
//it runs this part after executing the controller
$response->header('Authorization','Bearer '.$my_new_token);
return $response;
}
This is how the middleware is assigned to my route:
Route::get('/{user}', 'v1\UserController#find')->middleware('jwt_auth');
That way you are excecuting the $response->header('Authorization','Bearer '.$my_new_token); sentence after the request was attended.
Change your code as follows:
class JWTAuthenticator
{
public function handle($request, Closure $next)
{
$token =JWTAuth::getToken();
$my_new_token = JWTAuth::refresh($token);
$request->headers->set('Authorization','Bearer '.$my_new_token);
return $next($request);
}

Laravel 5.3 Middleware Request Merge Not Return Any Value

All my code is working on Laravel 5.2. Now I try to upgrade to Laravel 5.3 it breaks on middleware.
// Verify Middleware
public function handle($request, Closure $next)
{
// I already make sure the data is exists
$user = User::find('abc');
if (!$user) {
return responseHandler()->unauthorized('Unauthorized');
}
$request->merge(['user_id' => $user->id, 'device' => $device]);
return $next($request);
}
// User Controller
public function __construct(Request $request)
{
var_dump($request->all());
$this->user_id = $request->user_id;
$this->device = $request->device;
}
public function getProfile(Request $request)
{
$data = User::find($this->user_id);
$result = Fractal::item($data, new UserTransformer)->getArray();
return responseHandler()->success(0, $result, 'user');
}
The problem is $this->user_id is always null. But if I request from getProfile function it return correctly.
var_dump result only the login info. it not received any merge request from middleware
On Laravel 5.2 this code is working properly. Any solution?.
Reference-: https://www.laravel.com/docs/5.3/upgrade#upgrade-5.3.0
Session In The Constructor
In previous versions of Laravel, you could access session variables or the authenticated user in your controller's constructor. This was never intended to be an explicit feature of the framework. In Laravel 5.3, you can't access the session or authenticated user in your controller's constructor because the middleware has not run yet.
As an alternative, you may define a Closure based middleware directly in your controller's constructor. Before using this feature, make sure that your application is running Laravel 5.3.4 or above:
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
class ProjectController extends Controller
{
/**
* All of the current user's projects.
*/
protected $projects;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->projects = Auth::user()->projects;
return $next($request);
});
}
}
Of course, you may also access the request session data or authenticated user by type-hinting the Illuminate\Http\Request class on your controller action:
It seems you can't access the session data in Controller constructor because the middleware not run yet.
Refer laravel change log here
you can't access the session or authenticated user in your
controller's constructor because the middleware has not run yet.
In your case you can call session with request object
public function getProfile(Request $request)
{
$data = User::find($request->session()->get('user_id'));
$result = Fractal::item($data, new UserTransformer)->getArray();
return responseHandler()->success(0, $result, 'user');
}

Resources