Unable to retrieve cookies set by Laravel - laravel-5

According to the official docs on cookies:
By default, all cookies generated by Laravel are encrypted and signed so that they can't be modified or read by the client. If you would like to disable encryption for a subset of cookies generated by your application, you may use the $except property of the App\Http\Middleware\EncryptCookies middleware, which is located in the app/Http/Middleware directory
In my controller that sends a response with cookies, I set a cookie with return response("Success", 200)->cookie('api_token', $api_token, 2, '/');, where $api_token is a string generated by Str::random(80). I have a route in web.php that is protected by middleware that checks if the cookie is valid. However, using $request->cookie('api_token'); in the middleware returns nothing, but I have to make an exception in the EncryptCookies for api_token to make this work.
I'm not sure why my cookie isn't being encrypted, even if I use a laravel function to set it. Am I misunderstanding which cookies are "generated" by Laravel?

Set Cookies :
public function setCookie(Request $request){
$minutes = 60;
$response = new Response('Set Cookie');
$response->withCookie(cookie('name', 'MyValue', $minutes));
return $response;
}
Get Cookies :
public function getCookie(Request $request){
$value = $request->cookie('name');
echo $value;
}

Related

How can write test for laravel api route with auth.basic middleware

My laravel project has an API route by auth.basic middleware which is used id of the authenticated user in the controller. when I call it in postman it works well and I get 401 when the username or password is incorrect, but in laravel APITest which extends from DuskTestCase, authentication does not take place so I get 500 instead of 401 when the user's informations were incorrect. However, by correct information, I have the same error because auth() is null.
it is written like below, which is wrong?
api.php route:
Route::get('/xxxxxx/xxxxxx/xxxxxxx', 'xxxxx#xxxx')->middleware('auth.basic');
APITest:
$response = $this->withHeaders(['Authorization' => 'Basic '. base64_encode("{$username}:{$password}")])->get("/xxxxxx/xxxxxx/xxxxxxx");
You can use actingAs() method for authentication in tests.
An example from docs:
public function testApplication()
{
$user = factory(App\User::class)->create();
$this->actingAs($user)
->withSession(['foo' => 'bar'])
->visit('/')
->see('Hello, '.$user->name);
}
Another example that you can use for an API:
$user = User::factory()->create();
$response = $this->actingAs($user)->json('GET', $this->uri);
$response->assertOk();
For more information: https://laravel.com/docs/5.1/testing#sessions-and-authentication

How to set middleware to kc finder

I have set Session after I login
session_start();
$_SESSION['ckfinder_auth'] = true;
where can I set middleware in this path
/templateEditor/kcfinder/browse.php?opener=ckeditor&type=images&CKEditor=editor1&CKEditorFuncNum=1&langCode=en
When you work with Laravel, it's best to write your own codes based on Laravel.
For example, To store data in the session, you will typically use the putmethod or the session helper:
// Via a request instance...
$request->session()->put('key', 'value');
or
// Via the global helper...
session(['key' => 'value']);
for retrieving an item from the session, you can use get :
$value = $request->session()->get('key', 'default value');
or global session helper :
$value = session('key', 'default value');
To determine if an item is present in the session, you may use the has method:
if ($request->session()->has('users')) {
//
}
I suggest you read the Laravel document first (session , middleware)
You have to create a new middleware and add it to the Kernel.php file
php artisan make:middleware <middleware_name>
Change the handle($request, Closure $next) as per your requirements.
Update the /App/Http/Kernel.php file by adding your middleware to protected $routeMiddleware = [] array
Now you have setup adding middleware. Simple add this middleware to the routes by calling
Routes::middleware(['middleware_name'])->get(function(){
return view('your_view');
});

JWT::getToken() doesn't get the proper token

I'm using JWT-Auth for authentication. I have created a middleware that checks if token is expired and then it refreshes the token and update the header. But in my controller getToken() does not get the new token but returns the expired one. I have checked the value of header in my controller and it has the new token.
This is how I do it in my middleware:
$new_token = JWTAuth::refresh($token);
$request->headers->set('Authorization', 'Bearer '.$new_token);
$response = $next($request);
and this is in my controller:
$token = JWTAuth::getToken();
After looking at their code. I found a setToken() function which solved my issue. I modified my code like this:
$new_token = JWTAuth::refresh($token);
JWTAuth::setToken($new_token);
$response = $next($request);
$response->header('Authorization','Bearer '.$new_token);
return $response;
Change version of JWT package 5.12 to 5.11 in composer.json file then its work properly.
I was also stuck in same issue before few days
https://github.com/tymondesigns/jwt-auth/issues/1198

Laravel 5 - Remove Parameter From All Request Objects at Controller Level

I have URLs that look like:
http://example.com/api/user?id=45&name=mike&api_token=2348283
http://example.com/api/project?id=5&description=first&api_token=2348283
etc...
In my controllers, I have functions that look like:
public function user_get_endpoint(Request $request){
$request = $request->toArray();
return UserModel::where($request)->get()->toArray();
}
The above will currently break since the $request object contains a property called api_token which does not exist in the user table. I am using the api_token in a middleware to check for authentication.
I can manually unset the api_token property in each of my API functions by using unset($request['api_token'], but I'd like to avoid that if possible.
Is there anyway to do this application wide or at a class or controller level?
Laravel provides add and remove functions to add and remove new properties to the request object respectively.
$request->request->add(['api_token' => 'api_token']); // to add new property to $request
$request->request->remove('api_token'); // to remove property from $request
Perhaps you want global middleware?
First arrange for the middleware to run on all routes:
// routes.php
$app->middleware([
App\Http\Middleware\Apitoken::class
]);
Then define what the middleware should do:
// src/App/Http/Middleware/Apitoken.php
<?php
namespace App\Http\Middleware;
use Closure;
class Apitoken
{
public function handle($request, Closure $next)
{
unset($request['api_token']);
return $next($request);
}
}
Method 1
$request->except(['key1','key2',....])
provides an easy way to skip unwanted keys, similarly
Method 2
$request->only(['key3','key4',....])
provides an easy way to skip all others unwanted keys, I find both reasonably good for almost all scenarios
A solution that works for all HTTP Methods (not only for GET and HEAD) :
$except = ['api_token'];
$request = request();
$cleanup = $request->except($except);
$request->query = new \Symfony\Component\HttpFoundation\ParameterBag($cleanup);
Ideally, you should send your api_token in request headers instead of Uri params.
If you are using Laravel's auth:api Middleware for authentication then you can send api_token in headers as:
$response = $client->request('GET', '/api/user', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
]);
Then api_token will never come in your Uri params.
As #JanWillem said in the comments you can use except() which will remove the params you pass to it:
public function user_get_endpoint(Request $request){
return UserModel::where($request->except('api_token'))->get();
}
https://laravel.com/docs/5.2/requests#retrieving-input and then scroll down to Retrieving A Portion Of The Input Data
Furthermore, you don't have to use toArray() with the response as Laravel will automatically do this for you.
Hope this helps!

Setting Cookie in Laravel Custom Middleware

I want to set a cookie in a custom Laravel middleware. The idea is to set the cookie value any time a user visits my website through any landing page.
So what I did was I created a middleware named UUIDMiddleware. I am using this middleware along with web middleware in my routes. Below is its code from the middleware.
if($request->hasCookie('uuid'))
{
return $next($request);
}
else
{
$uuid = Uuid::generate();
$response = new Response();
return $response->withCookie(cookie()->forever('uuid', $uuid));
}
As you can see I am checking if cookie exists. If not, I am passing control to next request.
The problem is when setting a cookie using return $response, I cannot pass control to next request. How do I resolve this?
What happens in this case is if a cookie is not set, it sets a cookie and a blank screen shows up. If I refresh, I see the website with a cookie set.
There has to be a way to set cookie using middleware in the right way. How do I do it?
The response object in middleware is returned by the $next closure, so you could do something like this:
if($request->hasCookie('uuid')) {
return $next($request);
}
$uuid = Uuid::generate();
return $next($request)
->withCookie(cookie()->forever('uuid', $uuid));
If you're using Laravel 5.8 and like me you want a solution that allows you set the expiration time of the cookie instead of setting it to forever, you could also do something like this in the middleware:
public function handle($request, Closure $next)
{
$time = time() + 60 * 60 * 24; //One day
$res = $next($request);
return $res->cookie('cookie_name', $cookieValue, $time, "/");
}
This would set the cookie when the controller is done with the request and is returning a response.

Resources