slim/csrf not rendering the custom error message.
why it is not outputting the cutstom error message
$container['csrf'] = function ($c) {
$guard = new \Slim\Csrf\Guard();
$guard->setFailureCallable(function ($request, $response, $next) {
$request = $request->withAttribute("csrf_status", "FAILED");
return $next($request, $response);
});
return $guard;
};
this is my post route
$app->post('/welcome',function($request,$response){
if ('FAILED' === $request->getAttribute('csrf_status')) {
return $response->write('fail to validate');
} else {
return $this->view->render($response,'welcome.php');
}
});
it is not outputting the custom error message. it just output
the default text error message(Failed CSRF check!).
Related
I am trying to setup google indexing api in codeigniter, I have done all steps on google cloud and search console part.
It works, but returning success message on all options event when url is not submited, that is why I want to get exact response from google instead of a created success message.
How can I display exact response from google return $stringBody;? or check for the correct response ?
Here is my controller :
namespace App\Controllers;
use App\Models\LanguageModel;
use App\Models\IndexingModel;
class IndexingController extends BaseController
{
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
$this->indexingModel = new IndexingModel();
}
public function GoogleUrl()
{
checkPermission('indexing_api');
$data['title'] = trans("indexing_api");
$data["selectedLangId"] = inputGet('lang');
if (empty($data["selectedLangId"])) {
$data["selectedLangId"] = $this->activeLang->id;
}
echo view('admin/includes/_header', $data);
echo view('admin/indexing_api', $data);
echo view('admin/includes/_footer');
}
/**
* indexing Tools Post
*/
public function indexingToolsPost()
{
checkPermission('indexing_api');
$slug = inputPost('slug');
$urltype = inputPost('urltype');
$val = \Config\Services::validation();
$val->setRule('slug', trans("slug"), 'required|max_length[500]');
if (!$this->validate(getValRules($val))) {
$this->session->setFlashdata('errors', $val->getErrors());
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)))->withInput();
} else {
$this->indexingModel->AddUrlToGoogle($slug, $urltype);
$this->session->setFlashdata('success', trans("msg_added"));
resetCacheDataOnChange();
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)));
}
$this->session->setFlashdata('error', trans("msg_error"));
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)))->withInput();
}
}
And This is my model :
namespace App\Models;
use CodeIgniter\Model;
use Google_Client;
class IndexingModel extends BaseModel {
public function AddUrlToGoogle($google_url, $Urltype){
require_once APPPATH . 'ThirdParty/google-api-php-client/vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfig(APPPATH . 'ThirdParty/google-api-php-client/xxxxxxxxx.json');
$client->addScope('https://www.googleapis.com/auth/indexing');
$httpClient = $client->authorize();
$endpoint = 'https://indexing.googleapis.com/v3/urlNotifications:publish';
$array = ['url' => $google_url, 'type' => $Urltype];
$content = json_encode($array);
$response = $httpClient->post($endpoint,['body' => $content]);
$body = $response->getBody();
$stringBody = (string)$body;
return $stringBody;
}
public function AddUrlToBing($google_url, $Urltype){
}
public function AddUrlToYandex($google_url, $Urltype){
}
}
This is a success response when I try it out of codeigniter and print_r($stringBody);
{ "urlNotificationMetadata": { "url": "https://example.com/some-text", "latestUpdate": { "url": "https://example.com/some-text", "type": "URL_UPDATED", "notifyTime": "2023-01-29T01:51:13.140372319Z" } } }
And this is an error response :
{ "error": { "code": 400, "message": "Unknown notification type. 'type' attribute is required.", "status": "INVALID_ARGUMENT" } }
But In codeigniter I get a text message "url submited" even if url not submited.
Currently you are not handling the actual response of IndexingModel->AddUrlToGoogle(). It seems your code has a validation before, so it claims, if no validation error occurs, its always a success.
So the first question to ask is, why your validation is not working here - or is it?
Secondly you could handle the actual response in any case:
IndexingController
class IndexingController extends BaseController
public function indexingToolsPost()
{
if (!$this->validate(getValRules($val))) {
// validation error
$this->session->setFlashdata('errors', $val->getErrors());
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)))->withInput();
} else {
// no validation error
$apiResponseBody = $this->indexingModel->AddUrlToGoogle($slug, $urltype);
if(array_key_exists('error', $apiResponseBody)) {
// its an error!
// either set the actual messsage
$this->session->setFlashdata('error', $apiResponseBody['error']['message']);
// OR translate it
$this->session->setFlashdata('error', trans($apiResponseBody['error']['message']));
} else {
// Its a success!
$this->session->setFlashdata('success', trans("msg_added"));
}
// ...
}
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)))->withInput();
}
And in the model, return the response as an array:
IndexingModel
public function AddUrlToGoogle($google_url, $Urltype) {
// ...
$response = $httpClient->post($endpoint,['body' => $content]);
return json_decode($response->getBody() ?? '', true); // return an array
}
I am using AuthBasic for API authentication in a Laravel project,
I have this problem: when the API request authentication is invalid instead of displaying the JSON response it returns the 401 default blade view template.
Here is the code:
app\Http\Middleware\AuthBasic.php
public function handle($request, Closure $next)
{
if (Auth::onceBasic()) {
return response()->json(["message", "Authentication Required!"], 401);
} else {
return $next($request);
}
}
Found the Solution:
app\Exceptions\Handler.php
public function render($request, Exception $exception)
{
if ($request->is('api/*') || $request->wantsJson())
{
$json = [
'success' => false,
'error' => [
'code' => $exception->getCode(),
'message' => $exception->getMessage(),
],
];
return response()->json($json, 401);
}
return parent::render($request, $exception);
}
Remove the 401 or change it to 200 from this line:
return response()->json(["message", "Authentication Required!"], 401);
See the reference, the second parameter is defining the http code to send the browser. [401] in you case.
https://laravel.com/api/5.7/Illuminate/Routing/ResponseFactory.html#method_json
This will fix your problem, probably!
public function handle($request, Closure $next)
{
$result = Auth::onceBasic();
if($result === 401)
return response()->json(["message", "Authentication Required!"]);
else
return $next($request);
}
So here is a half Solution for this problem:
vendor\laravel\framework\src\Illuminate\Auth\SessionGuard.php
public function onceBasic($field = 'email', $extraConditions = [])
{
$credentials = $this->basicCredentials($this->getRequest(), $field);
if (! $this->once(array_merge($credentials, $extraConditions))) {
//return $this->failedBasicResponse();
return response()->json(["Message" => "Authentication Required!"], 401);
}
}
So Instead of returning the Failed Basic Response it will return the JSON Message, but I don't want to make changes in Laravel Core Files, because in case of update they will get lost !
So Any Idea ?
I don’t used react-router, just simply used react with blade. Like
following:
articleManage.blade.php
#extends('layout')
#section('content')
<div id="articleManage"></div>
#stop
I try to use jwt authentication, and it works.
Here is my jwt auth middleware:
authJWT.php
try {
$token = JWTAuth::parseToken();
if (! $token->authenticate()) {
return response()->json(['user_not_found'], 404);
}
} catch (Exception $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
return response()->json(['error'=>'Token is Invalid 1']);
}else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
return response()->json(['error'=>'Token is Expired 2']);
}else{
return response()->json(['error'=>'Something is wrong 3']);
}
}
return $next($request);
Now I am stuck with redirection on middleware, cause it won’t work when I change it like this:
try {
$token = JWTAuth::parseToken();
if (! $token->authenticate()) {
return response()->json(['user_not_found'], 404);
}
} catch (Exception $e) {
……
return redirect('/');
}
return $next($request);
And this is the error message I got:
TypeError: Cannot read property 'map' of undefined
at ArticleManage.render (app.js:54105)
at app.js:50033
at measureLifeCyclePerf (app.js:49313)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (app.js:50032)
at ReactCompositeComponentWrapper._renderValidatedComponent (app.js:50059)
at ReactCompositeComponentWrapper._updateRenderedComponent (app.js:49983)
at ReactCompositeComponentWrapper._performComponentUpdate (app.js:49961)
at ReactCompositeComponentWrapper.updateComponent (app.js:49882)
at ReactCompositeComponentWrapper.performUpdateIfNecessary (app.js:49798)
at Object.performUpdateIfNecessary (app.js:2916)
Any idea how to redirect when token error?
10/17: this is my program flow
articleManage.js
let url = 'load-article';
let config = {
headers: {'Authorization': 'Bearer '+localStorage.getItem('token')}
};
axios.get(url,config).then(response=>{
this.setState({'articles':response.data.articles});
}).catch(function (error) {
console.log(error);
});
web.php
Route::get('/load-article', 'API\ArticleController#read')->middleware('jwt-auth');
ArticleController#read
public function read(Request $request){
$header = $request->header('Authorization');
$articles = Article::All();
return response()->json(['articles' => $articles]);
}
now I change middleware, cause I want to try redirection, then I get error.
public function handle($request, Closure $next)
{
// try {
// $token = JWTAuth::parseToken();
// if (! $token->authenticate()) {
// return response()->json(['user_not_found'], 404);
// }
// } catch (Exception $e) {
// if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
// return response()->json(['error'=>'Token is Invalid 1']);
// }else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
// return response()->json(['error'=>'Token is Expired 2']);
// }else{
// return response()->json(['error'=>'Something is wrong 3']);
// }
// }
// return $next($request);
return redirect('/');
}
Shot in the dark here, since you didn't post the whole articleManager component. But, make sure you're passing some sort of failure status code header on all error responses. Otherwise, Axios will read response()->json(['error'=>'Token is Invalid 1']) as a success and attempt to set state. Since response.data.articles is undefined, that's why you're getting the error. So change your middleware in authJWT.php to something like:
} catch (Exception $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException) {
return response()->json(['error'=>'Token is Invalid 1'], 500);
} else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException) {
return response()->json(['error'=>'Token is Expired 2'], 500);
} else {
return response()->json(['error'=>'Something is wrong 3'], 500);
}
}
How to print out data within function beforeAction? I want to make some verification before each action in a controller, therefore if some condition occurs in beforeAction I should print out data and prevent further execution, for example, JSON:
[
status: "error",
msg: "access denied"
]
I try to even inner redirect to another controller, but it doesn't work.
public function beforeAction($action)
{
$request = Yii::$app->request;
if ( ! checkByToken($request->get('token')) && $this->getRoute() != 'web/abonent/token_error') {
\Yii::$app->runAction('web/abonent/token_error');
return true;
}
return parent::beforeAction($action); // TODO: Change the autogenerated stub
}
But maybe there an another concept of doing so. I just need to check the condition before any actions and print our result or let the action execute.
To prevent further execution:
public function beforeAction($action) {
return false; // key point
}
To print out data within beforeAction:
public function beforeAction($action) {
// set response format = json:
Yii::$app->response->format = Response::FORMAT_JSON;
// then, set the response data:
Yii::$app->response->data = [
'status' => 'error',
'msg' => 'access denied'
];
return false;
}
I think will be better
public function beforeAction($action)
{
$request = Yii::$app->request;
if ( ! checkByToken($request->get('token')) && $this->getRoute() != 'web/abonent/token_error') {
$action = 'error';
}
return parent::beforeAction($action); // TODO: Change the autogenerated stub
}
Action name must be 'actionError'
Hey guys i got some Problems with the Slim Middleware.
I created a Middleware that checks if the user is logged with Facebook and has a specific Email address. So now when i call the url with the PHPStorm RESTful Test tool i should not be able to post data to the server...
But the Redirect does not work so i will be able to send data to the server.
/**
* Admin Middleware
*
* Executed before /admin/ route
*/
$adminPageMiddleware = function ($request, $response, $next) {
FBLoginCtrl::getInstance();
$user = isset($_SESSION['user']) ? $_SESSION['user'] : new User();
if (!($user->getEmail() == ADMIN_USER_EMAIL)) {
$response = $response->withRedirect($this->router->pathFor('login'), 403);
}
$response = $next($request, $response);
return $response;
};
/**
* Milestone POST Method
*
* Create new Milestone
*/
$app->post('/admin/milestone', function (Request $request, Response $response) use ($app) {
$milestones = $request->getParsedBody();
$milestones = isset($milestones[0]) ? $milestones : array($milestones);
foreach ($milestones as $milestone) {
$ms = new Milestone();
$msRepo = new MilestoneRepository($ms);
$msRepo->setJsonData($milestone);
if (!$msRepo->createMilestone()) {
return $response->getBody()->write("Not Okay");
};
}
return $response->getBody()->write("Okay");
})->add($adminPageMiddleware);
So can anyone give me a hint what the problem could be?
I tried to add the same middleware to the get Route ... there it works :/ Strange stuff.
The problem is in your middleware logic.
if (!($user->getEmail() == ADMIN_USER_EMAIL)) {
return $response->withRedirect($this->router->pathFor('login'), 403); //We do not want to continue execution
}
$response = $next($request, $response);
return $response;
So now i ended up with this code:
class AdminRouteMiddleware
{
public function __invoke($request, $response, $next)
{
FBLoginCtrl::getInstance();
$user = isset($_SESSION['user']) ? $_SESSION['user'] : new User();
if (!($user->getEmail() == ADMIN_USER_EMAIL)) {
if ($_SERVER['REQUEST_METHOD'] == "GET") {
$response = $response->withRedirect('/login', 403);//want to use the route name instead of the url
} else {
$response->getBody()->write('{"error":Access Denied"}');
}
} else {
$response = $next($request, $response);
}
return $response;
}
}
/**
* Milestone POST Method
*
* Create new Milestone
*/
$app->post('/admin/milestone', function (Request $request, Response $response) use ($app) {
$milestones = $request->getParsedBody();
$milestones = isset($milestones[0]) ? $milestones : array($milestones);
foreach ($milestones as $milestone) {
$ms = new Milestone();
$msRepo = new MilestoneRepository($ms);
$msRepo->setJsonData($milestone);
if (!$msRepo->createMilestone()) {
return $response->getBody()->write("Not Okay");
};
}
return $response->getBody()->write("Okay");
})->add(new AdminRouteMiddleware());