Cakephp 4: JWT Authorization fails in Browser, Postman works - php

I'm having trouble migrating my Backend CakePHP App, from CakePHP 3.9 to CakePHP 4.
The App serves as an API for my sveltejs/sapper Javascript Application.
As for the JWT Authentication I'm using the admad/cakephp-jwt-auth plugin.
The App before Migration works perfectly from the browser as the frontend.
Testing my API in Postman works for both CakePHP 3 and 4 versions.
After migration however, requests sent from the browser (sveltejs/sapper) and where Authentication is needed (Authorization header containing the Bearer token) result in an error:
Error 401 "Authorization failed
My CORS Middleware (ozee31/cakephp-cors plugin) also seems to be working since requests that don't need to be authorized just work as expected, also from the browser - unplugging CORS middleware result in an CORS error in the browser for those requests.
Also, my server is populating $_SERVER['HTTP_AUTHORIZATION']
Has anyone successfully implemented a similar setup, especially when it comes to CakePHP 4 and HTTP_AUTHORIZATION header yet?

I created a own JWT plugin for CakePHP 4 that worked as a component.
https://github.com/WireCore/CakePHP_JWT
It's currently in alpha but you can try if it solved your problem.
You can install it with composer composer require wirecore/cakephp_jwt and add it in your Application.php via $this->addPlugin('Wirecore/CakePHP_JWT'); You find more details in the README

Cors error can be fixed in following way .
In AppController.php
private function setCorsHeaders()
{
$this->response = $this->response->cors($this->request)
->allowOrigin(['*'])
->allowMethods(['*'])
->allowHeaders(['x-xsrf-token', 'Origin', 'Content-Type', 'X-Auth-Token', 'authorization'])
->allowCredentials(['true'])
->exposeHeaders(['Link'])
->maxAge(300)
->build();
}
public function beforeRender(EventInterface $event)
{
// .......
$this->setCorsHeaders();
}
public function beforeFilter(EventInterface $event)
{
// ......
if ($this->request->is('OPTIONS')) {
$this->setCorsHeaders();
return $this->response;
}
}
In config/Bootstrap.php add this line al last line og file.
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: *");

Related

All requests ends up in GET route. Laravel

I have a Laravel(8.83) application. API routes end up in GET requests always.
To check the problem I have deleted all the routes except one. Now I have just one route:
Route::put("cart/{id}", function(Request $request, $id) {
return $request->all();
});
Although I make PUT request on the postman, the result is: "The GET method is not supported for this route. Supported methods: PUT."
I have tried PUT, PATCH, POST, DELETE, and OPTIONS. All ended up in the same error.
Edit: 3 Oct 2022
I run php artisan optimize:clear and composer dump-autoload several times. None resolved the issue.
The project is in production, deployed on a server. I have made a request from a Vue.JS web app client, and the result is the same. I don't think the problem is caused by Postman.
The request method is probably getting modified in Postman or in webserver config, or in .htaccess.
Here's one thread on a similar issue in Postman - Postman support
For a reference to a working .htaccess - Laravel .htaccess GitHub

Laravel7 CORS : blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'

Use case: VueJS/Laravel app has inventory. Calling Magento2 using SOAP API to update Qty from VueJS/Laravel.
Error as shared below:
Access to XMLHttpRequest at
'http://xx.yyy.abc.123/rest/V1/integration/admin/token?username=admin&password=xxxxx'
from origin 'http://192.168.0.x' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
Note: I am a beginner in this domain. I might be asking stupid questions. Please bear with me and requesting help here.
Tools/Apps used:
Laravel Framework 7.9.2 /Running on http://192.168.0.x
VueJS /Running on http://192.168.0.x
Magento2 /Running on http://xx.yyy.abc.123
Postman (Tool used to test SOAP API)
Debugging efforts:
URL http://xx.yyy.abc.123/rest/V1/integration/admin/token?username=admin&password=xxxxx
Tried from postman: It works, Apended token into postmane and got the response.
Making AXIOS call from VueJS/Laravel application to Magento2:(Failed)
Origin: http://192.168.0.x
Magento2: http://xx.yyy.abc.123
axios.post("http://xx.yyy.abc.123/rest/V1/integration/admin/token?username=admin&password=xxxxx",
{
})
.then((response) =>
{
console.log("response.data",response.data);
this.apiResponse = response.data;
//this.getproduct();
})
.catch(error =>
{
alert('ERROR GETCATEGORY!!!! No Data found');
console.log(error.response);
});
Checked for 2 days now about CORS error and found that this is enabled by default in Laravel 7. Not sure why I am seeing this error even after using Laravel 7. There are very few answers or solutions specific to VueJS with Laravel 7.
Question:
What does this error means. I thought it is just calling from webpage1 to webpage2, it does not seem to work.
Do I need to make any changes on my VueJS/Laravel application. Am I missing anything further.
Please do let me know if you need any more information to help me in this regards.
Thanks for your help.
Regards,
I had got the same CORS error while working on a Vue.js project. I finally solved this issue just today in the morning. You can resolve this either by building a proxy server or another way would be to disable the security settings of your browser (eg, CHROME) for accessing cross origin apis. Both these solutions had worked for me. The later solution is the easiest solutoion and does not require any mock server or a proxy server to be build. Both these solutions can be resolved at the front end.
You can disable your browser (CHROME) security settings for accessing apis out of the origin by typing the below command on the terminal:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir="/tmp/chrome_dev_session" --disable-web-security
After running the above command on your terminal, a new chrome window with security settings disabled will open up. Now, run your program (npm run serve / npm run dev) again and this time you will not get any CORS error and would be able to GET request using axios.
Hope this helps!

Laravel 419 Error - VerifyCsrfToken issue

I have multiple Laravel sites hosted on the same server. With the latest site I've created, the contact form refuses to submit without throwing a 419 error. I have set up the routing in my web.php file just like the other websites, which have live, working contact forms, and I'm generating and sending the token exactly the same way - with {{ csrf_field() }}.
I found an answer to a similar question stating that you can disable Csrf checking by adding entries to the $except array in app/Http/Middleware/VerifyCsrfToken.php. I have verified that this does indeed resolve the 419 error:
protected $except = [
'contact',
'contact*',
];
But of course I wish to keep the Csrf functionality, and I only updated the $except array for troubleshooting value.
Does anyone know what may be different about the new Laravel environment that would have this 419 behavior despite passing the generated token? I have tried updating a number of ENV settings and toggling different things, but nothing other than modifying the $except array has had any influence on the issue.
Update
Since there has been a bit of discussion so far, I figured I'd provide some additional info and code.
First, this is an ajax form, but don't jump out of your seat just yet. I have been testing the form both with and without ajax. If I want to test with ajax, I just click the button that's hooked up to the jQuery listener. If not, I change or remove the button's ID, or run $("#formName").submit(); in the console window.
The above (ajax, old-fashioned submit, and the jquery selector with .submit();) all result in the exact same response - a 419 error.
And for the sake of completeness, here's my ajax code which is working on all of the other websites I'm hosting. I define a postData array to keep it all tidy, and I added a console.log() statement directly after it to (again) confirm that token is generated just fine and is being passed correctly with the request.
var postData = {
name: $("#name").val(),
email: $("#email").val(),
message: $("#message").val(),
_token: $("input[name=_token]").val()
};
console.log(postData);
$.post("/contact", postData, function (data) {
...
Any ideas? Could there be a configuration issue with my ENV or another file?
Progress Update!
Because the other sites are working just fine, I cloned an old site and simply overwrote the files that I changed for the new website, and bam! It's working now. Doing a little bit more digging, I ran php artisan --version on the cloned version of the site versus the non-working version, and here are the results:
Working Version: Laravel Framework 5.7.3
Non-working Version: Laravel Framework 5.7.9
Perhaps this is a bug with Laravel? Or perhaps some packages on my server are out of date and need to be updated to work with the new version of Laravel?
TLDR: This post contains lots of potential issues and fixes; it is intended for those scouring for related bonus information when stuck.
I just encountered this error using Laravel Sanctum in what looks like improperly setup middleware. Sanctum uses the auth:sanctum middleware for the guard, which is some kind of extension of the auth guard of which Laravel uses as the default, but session is handled by the web middleware group.
I can't exactly verbalize some of this internal-Laravel stuff; I am more experienced with JavaScript than PHP at the moment.
In my api.php file, I had the login/register/logout routes, and in my Kernel.php file, I copied \Illuminate\Session\Middleware\StartSession::class, from the web group into the api group.
I had to do that to fix my login unit test that was throwing an error about "Session store not on request". Copying that allowed me my postJson request to work in the unit test, but sometime later, I started seeing 419 CSRF error posting from the JavaScript app (which is bad because it worked fine earlier).
I started chasing some filesystem permission red-herring in the /storage/framework/sessions folder, but the issue wasn't that (for me).
I later figured out that with Laravel Sanctum and the default AuthenticatesUsers trait, you must use the web guard for auth, and the auth:sanctum middleware for protected routes. I was trying to use the api guard for auth routes and that was central to my 419 errors with the AuthenticatesUsers trait.
If anyone gets 419 while CSRF was working or should work, I recommend doing some \Log::debug() investigations at all the key points in your system where you need these to work:
Auth::check()
Auth::user()
Auth::logout()
If you get strange behaviour with those, based on my observations, there is something wrong with your config related to sessions or something wrong with your config related to web, api guards.
The guards have bearing on the AuthManager guard which maintains state over multiple requests and over multiple unit tests.
This is the best description I found, which took over a week for me to discover:
Method Illuminate\Auth\RequestGuard::logout does not exist Laravel Passport
As a random final example, if your session is somehow generating the CSRF token using data from the web middleware group while your routes are set to use api, they may interpret the received CSRF incorrectly.
Besides that, open Chrome dev tools and goto the Applications tab, and look at the cookies. Make sure you have the XSRF-TOKEN cookie as unsecure (ie: not httpOnly).
That will allow you to have an Axios request interceptor such as this:
import Cookies from 'js-cookie';
axios.interceptors.request.use(async (request) => {
try {
const csrf = Cookies.get('XSRF-TOKEN');
request.withCredentials = true;
if (csrf) {
request.headers.common['XSRF-TOKEN'] = csrf;
}
return request;
} catch (err) {
throw new Error(`axios# Problem with request during pre-flight phase: ${err}.`);
}
});
That is how my current Laravel/Vue SPA is working successfully.
In the past, I also used this technique here:
app.blade.php (root layout file, document head)
<meta name="csrf-token" content="{{ csrf_token() }}">
bootstrap.js (or anywhere)
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
const token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
In my opinion, most problems will stem from an incorrect value in one or more of these files:
./.env
./config/auth.php
./config/session.php
Pay close attention to stuff like SESSION_DOMAIN, SESSION_LIFETIME, and SESSION_DRIVER, and like I said, filesystem permissions.
Check your nginx access.log and/or error.log file; they might contain a hint.
just found your issue on the framework repo.
It is not a laravel issue, your installation is missing write permissions on the storage folder, thus laravel can't write session, logs, etc.
You get a 419 error because you can't write to the files, thus you can't create a sessionn, thus you can't verify the csrf token.
Quick fix: chmod -R 777 storage
Right fix: move your installation to a folder where nginx/apache/your user can actually write.
If you are using nginx/apache, move you app there and give the right permissions on the project (chown -R www-data: /path-to-project)
If you are using php artisan serve, change it's permissions to your user: chown -R $(whoami) /path-to-project
You get it, let writers write and you're good.
Probably your domain in browser address bar does not match domain key in config/session.php config file or SESSION_DOMAIN in your env file.
I had the same issue, but the problem in my case was https. The form was on http page, but the action was on https. As a result, the session is different, which is causing the csrf error.
run this command
php artisan key:generate
I used the same app name for staging and prod, being staging a subdomain of prod. After changing name of app in staging it worked
We had this issue, it turned out that our sessions table wasn't correct for the version of Laravel we were using. I'd recommend looking to see if it's being populated or remaining empty (like ours was).
If it's empty, even when you have people visiting the site, I'd say that's what the issue is.
(If you're not using a database to store your sessions, obviously I'd suggest checking wherever you are instead.)

HTTP status code being overwritten

I am developing a REST api using PHP and Yii2. I have created a custom class for creating (POST) an entity. in that class I have the following code:
if (!$this->AuthenticateRegister($username, $token)) {
throw new ForbiddenHttpException("Invalid token");
}
When I try this locally (WAMP on windows) every thing works fine and I get the proper HTTP status code
But when I upload the code on the host (cpanel) I always get 200 in response
since the HTTP status codes are needed on the client side, how can I resolve this issue?

IONIC Content-Type is not allowed by Access-Control-Allow-Headers

I was working on an angularJS, IONIC project with CI backend.
I was sending parameters to the server using POST Method, and receiving it using the CodeIgniter Input class and everything was working OK.
Now that app going to be native Android, the developer should send parameters as JSON array. So I changed my backend API function to receive it like:
$data = json_decode(file_get_contents('php://input'), true);
$email = $data->email;
It works great but the problem now is when I try to access the function using IONIC app I get an php error.
XMLHttpRequest cannot load
http://192.168.1.122/project/index.php/api/login.
Request header field Content-Type is not allowed by Access-Control-Allow-Headers.
on my API I allowed all CORS
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
...But I still get the same error.
Can I get any other solution around this point.
Thanks for your help.
You have to add cordova-plugin-whitelist plugin to implements a whitelist policy for navigating the application webview on Cordova 4.0
ionic plugin add cordova-plugin-whitelist
then
ionic build <platform>
Source

Categories