Get cookie within an Ajax API post request - Laravel 5.6 - ajax

After running an API call, in my controller, I'm trying to get the cookie value like this:
Cookie::get('gtdk')
It returns a empty value, although the cookie was already set in the browser.
Do I need to pass the cookie value as a parameter in the ajax call?
EDIT
It is also happening in a WEB route call - the cookie is not there when trying to read it in the Controller

Ok, so laravel encrypts the cookie names.
As the cookie was set using Javascript in the frontend, I could not read it by using Laravel methods.
Therefore, I've used it using PHP standard:
$_COOKIE['gtdk']
Another option is adding an exception for that cookie name in the the middleware.

Related

SPA Authentication Issues with Sanctum and Postman

I'm currently trying to test an SPA using Laravel 8.19.0 and Postman 7.36.1 but I keep getting an "Unauthenticated" response from a route that's guarded by "auth:sanctum", even though I have logged in correctly.
As far as I can understand, I've followed the documentation fully at https://laravel.com/docs/8.x/sanctum
in order to set Sanctum up to be used for SPA so I've done the following:
Installed Sanctum.
Published the Sanctum config.
Performed a migration.
Included the EnsureFrontendRequestsAreStateful middleware and 'EnsureFrontendRequestsAreStateful::class' to the Http Kernal.
Added my local domains (same top-level domain but 1 with the "test" sub domain and another with "api") to the "stateful domains" option in the Sanctum config file.
Set the "supports_credentials" option in the cors config to "true".
Set my top level domain, prefixed with a "." for the "domain" option in the session config.
Then, I've set Postman up using the guide at https://blog.codecourse.com/laravel-sanctum-airlock-with-postman/
so I've written a script to get the CSRF token from "/sanctum/csrf-cookie" then used said token as the value for the "X-XSRF-TOKEN" in the request header and I can succesfully log in. however, when I try to access a route afterwards that's guarded by the "auth:sanctum" guard, even with the referrer and 'X-XSRF-TOKEN' being set up in the request header I cannot access the route.
After debugging, I can see that $this->auth->guard($guard)->check() is returning false in the authenticate($request, array $guards) method where $guard = "sanctum" in \vendor\laravel\framework\src\Illuminate\Auth\Middleware\Authenticate.php on line 63 because $this->user() is null for the Illuminate\Auth\RequestGuard instance.
Any help or even ideas on things to check would be greatly appreciated as I'm unsure on what to do from here, short of spending a day digging deeper into the request guard object and its instantiation!
Thanks.
The issue a lot folk are seeing when using Postman with Sanctum SPA authentication is that you simply need to add an additional header to your requests, This can be "Referrer" or "Origin" and the value must match the domains set in the sanctum.php config file. e.g. localhost or mysite.test etc.
vendor/laravel/sanctum/src/Http/Middleware/EnsureFrontendRequestsAreStatefull.php in the fromFrontEnd() method is where you can see this requirement. Laravel V8.x and I believe also in Laravel V7.x
Issue has since been resolved and was caused by Postman only saving the "XSRF-TOKEN" and "laravel_session" cookies to the "test" subdomain after logging in (the login URL used this sub domain) and thus not passing them to the "api" subdomain when trying to access the route which was protected by "auth:sanctum". By adding the same cookies to the "api" subdomain via the "Manage Cookies" menu in Postman, the route can now be accessed as intended.

Redirecting to local post route

Short version
Do we need GuzzleHttp to redirect to local POST route? Can't we do this directly using redirect()?
Long version
Following this Laravel tutorial about using Passport authentication, the presenter talks about a way of hiding client_id to increase security (check at around 11:45 in the video).
The idea is to expose a new wrapper route that accepts only username and password fields and then the controller injects client_id on the server-side and makes a new call to Passport's original login route. This call is made using GuzzleHttp client. Response of the call is then returned by the wrapper route to the caller.
My question is: Do we really need to install and use Guzzle? Can't we redirect to Passport's login route using redirect() or some other built-in Laravel function?
You need Guzzle to make a HTTP request so that you can modify the response before sending it.
You will not be able to hide any data using redirect() because it will just tell the browser (client) to use the passport route directly.
To avoid making the HTTP a call you could get your route to run the code that the passport route runs and then modify the response that is generated. Making a local HTTP call should not be a problem though.

Why Laravel5.4 $request->cookie('key') is empty when PHP global var $_COOKIE has cookies

I am trying to read the cookies in Laravel5.4. So I get the cookies after successful validation with third party Authorization server. I am not making the cookies in laravel5.4, but I am reading the cookie value send to me from view/frontend. I can see the values of cookies in Chrome debugger environment as well as from PHP global variable $_COOKIE. They are all set correctly.
However, when I tried to read the same cookie using $request->cookie('key') from controller method... it shows nothing. I also tried Cookie facade to read the value and still nothing. This controller is handling a redirect route which is called by the third party oauth server and this server when it redirects to my URL, it also sets the cookies.
Am I not setting this redirect url route correctly in web.php file in Laravel5.4? This is how it is defined in web.php as below:
Route::get('login/okta/callback',
'Auth\LoginController#handleProviderCallback');
The request object is empty when I dumped the content but $_COOKIE has the data.
Laravel's cookie class encrypts and decrypts the values of its cookies (see the App\Http\Middleware\EncryptCookies middleware). When you have it look at a cookie it didn't set, it's going to try (and fail) to decrypt it.
If you've got a cookie set from outside Laravel, use $_COOKIE to work with it, or add the name of the cookie to the $except array in app/Http/Middleware/EncryptCookies.php so it isn't messed with.

Get a cookie in Laravel 5 middleware

I'm trying to retrieve a cookie from a middleware in Laravel 5.3 but it seems like $request->cookie('language') is empty. I'm guessing that it is only set after the middleware runs.
I read somewhere that I should use \Cookie::queued('language'), but it's still empty.
Is my only option using the $_COOKIE variable?
When do you set this cookie?
Remember that cookies are stored in the browser, so the user needs to get the response in order for you to be able to retrieve the cookie later.
You should be able to get the cookie after the cookie is being set by a response that's successfully sent to the user. Remember also that if you use dd(), that doesn't let the cookie get created, because it skips all cookie headers from being sent to the user.
Another problem you might face for trying to get cookies from middleware is that it might not get decrypted automatically, so you'll have to do it yourself.
Example:
\Crypt::decrypt(Cookie::get('language'))
If someone encounters this problem in 2019 with Laravel 5.8:
You will need to use \Crypt::decryptString(Cookie::get('language')) or \Crypt::decrypt(Cookie::get('language'), false).
Otherwise it will try to unserialize the string and then strange things happen.

Laravel 4: reading cookies set by javascript

If I set a cookie with javascript, how would I read it using Laravel 4?
The reason I'm asking is that the docs say:
All cookies created by the Laravel framework are encrypted and signed
with an authentication code, meaning they will be considered invalid
if they have been changed by the client.
Just use the native PHP command to retrieve cookies: $_COOKIE['cookie'])
Or perhaps you can set the cookie via an AJAX command (rather than JS doing it itself) - and have Laravel set the cookie supplied by JS on its behalf?
This link confirms setting cookies via AJAX - it will just be a variation of that.
In Laravel 5.6 (and maybe earlier versions too):
Specify the cookie name in the $except array within App\Http\Middleware\EncryptCookies.php.
It tells Laravel that those cookies aren't encrypted (and therefore don't need to be decrypted when read).
(P.S. Thanks to https://github.com/laravel/laravel/pull/460#issuecomment-377537771)

Resources