YII2: bad Request (#400) Unable to verify your data submission? - yii2

When I try swith on CSRF validation, I am getting this error.
I have Html::csrfMetaTags() in main layout and it's working perfectly.
<meta name="csrf-param" content="_csrf-frontend">
<meta name="csrf-token" content="QmcxU050NEIzD2AaDScBdxQqHAkFM04XCT9AFhZNQSlyIlISYy1yMg==">
I use activeForm and I checked POST Query and found that csrf information is sending correctly.
_csrf-frontend:Ukp1TC5KYUgaEBQIWwg4cCI7OCZEf1YYERJMfkIuAH84DD8ObQlTEA==
My config section:
'request' => [
'cookieValidationKey' => 'LWCVTaYxV7aK6dqMWNKm1C7HMit6bJKa',
'csrfParam' => '_csrf-frontend',
'enableCsrfValidation' => true,
],
P.S. csrf-token data in meta name and data in post query is different, is this okay or not?

Are you sure that you're sending the parameters inside each form?
Inside your form you have to add a hidden parameter like this:
echo Html::hiddenInput(
Yii::$app->request->csrfParam,
Yii::$app->request->csrfToken
);
So each request receives the CSRF data,I haven't done at layout level.

Related

Yii2 ActiveForm Stripe token

In Yii2, we are using \Stripe\Charge::create following the site's documentation example:
https://stripe.com/docs/payments/accept-a-payment-charges
Everything works great as long we use straight HTML in the views, but when we embed the card-element in an ActiveForm, the stripe.js returns:
XMLHttpRequest cannot load https://api.stripe.com/v1/tokens due to
access control checks.
We would like to use ActiveForm to simplify the validation and handling of other fields on the form. Any help?
Best,
Joe
The error is CORS related, see CORS. Use the appropriate Access-Control as described there.
You can use Yii's build in behavior yii\filters\Cors in your controller.
Try first without any restriction:
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
],
];
}
If it works, than you can restrict the access by parametrising the behavior, something like that:
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
'Origin' => [https://api.stripe.com'],
'Access-Control-Request-Method' => ['POST', 'PUT'],
],
],
];
}
So, for anyone landing here, the only way I can get this to work is to remove the ActiveForm scaffolding. Real bummer because I've had to validate the non-Stripe input fields with Javascript, which is lot more work.
I do challenge anyone to post working code in Yii using ActiveForm that will return a token. I don't think it can be done...but I would love to be wrong.
Best,
Joe

Laravel 5.8 validation return to home after it fails while using Passport

I have a store() method.
public function create(StorePost $request)
{
$post = Post::create([
'title' => $request->title,
'description' => $request->description,
]);
return response()->json([
'post' => $post
], 201);
}
In my StorePost class, I validated the request.
public function rules()
{
return [
'title' => 'required|string|max:255',
'description' => 'required',
];
}
When I tested it with Postman with wrong entries, for example, if I fill 'description' with a null value, it returns to the home page without any response or error. How can I retrieve the validation errors?
I solved it just by adding 'Accept': 'application/json' in my request's header.
This happens because Laravel Form Request works both for API and non-API requests.
On requests made by a form, it will redirect back (to the original form url or home if not sent from a form) with an error bag on $errors variable available to the view.
On requests made by ajax (usually on APIs) usually have the header Accept: application/json, so Laravel automatically knows that you want the validation error bag as json on the response body instead of a redirect that makes no sense for an API.
Hope this can clarify thing to you.

Is it possible to set the path for all frontend AJAX request

My slugs looks like this:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<lang>/<p_page>/<p_category>/<p_product>' => 'splitter/manage-request',
'<lang>/<p_page>/<p_category>' => 'splitter/manage-request',
'<lang>/<p_page>' => 'splitter/manage-request',
'<lang>/' => 'splitter/manage-request',
'<lang>' => 'splitter/manage-request',
'' => 'splitter/manage-request',
],
],
I am sending all the requests to that SplitterController where I am parsing them. But I don't want the AJAXs to be send to it. Is it possible to give them some default route? To redirect them backend for example. I couldn't find information about it in the documentation? Appreciating links also is I missed it. Thank you!
According to my experience, there are probably the following options for your reference:
the first: The easiest way is to add a beforeAction() to your SplitterController, determine if it is an ajax request in beforeAction(), and redirect to your target address, for example:
public function beforeAction()
{
if (\Yii::$app->request->isAjax) {
return \Yii::$app->response->redirect($targetUrl);
}
return parent::beforeAction($action);
}
second: You can check if the request is an ajax request in the nginx configuration and then redirect to your target address
third: If you can't set up additional routing rules and configure the ajax request address, then you can consider implementing it by customizing UrlManager::parseRequest(), just check if it is an ajax request before it starts parsing the request, then redirect to your target. address
This answer is translated from Google Translate

Yii2 Make endpoint accessible through web and rest api

A customer has requested to have the exact same endpoints available through web interface as well as through REST API.
The same endpoint should be visible using web browser only when being logged in. When accessing it via REST API, a valid access token must be submitted.
The rule for this specific endpoint is defined as follows:
[
'class' => 'yii\rest\UrlRule',
'controller' => 'site',
'pluralize' => false,
'extraPatterns' => [
'POST upload-raw-data' => 'uploadRawData'
],
]
Now, when I try to access this endpoint, I've got these results:
Browser: no problem
Postman / POST: 404 error
Postman / GET: no problem
When trying the same with enableStrictParsing enabled, I've got 404 errors all around.
If I need to provide other parts of the code, I'll happily provide them.
I think I found the solution for my issue. The problem seems to have been the CSRF validation.
By disabling it for this specific action in beforeAction(), the POST call behaves as intended.
public function beforeAction($action) {
if ($action->id == 'upload-raw-data')
Yii::$app->controller->enableCsrfValidation = false;
return parent::beforeAction($action);
}
source: https://gist.github.com/guerreiro/9e9cb3154b9047f5d2a0

YII - Adding error code in form validation

I have a web-service and want to send a custom error-code and string in case form validation fails. We can specify error 'message' in form validation rules, but I want to add a numerical error code, that I can use later to get a text string. Extending CValidator is not an option as I want to use standard validators.
Ideally, I would like something like this in my rules() function.
array('page', 'numerical', 'integerOnly' => true, 'min' => 1, 'message' => '{attribute} is invalid', 'code' => 10079),
Later I return a JSON block like
{
'code': 10079,
'message' : 'page is invalid'
}
I am thinking of attaching a behavior to validators, but not quite able to figure out a way to make it work. Is there any other yii-way to do it?
instead of message , you just return the error code as message and on the view page just call a function to retrieve the appropriate error message.
provide $form->error(); as parameter to get errorMessage on the view page.