Can't redirect user in Laravel - php

I am trying to redirect user to different url after certain event has fired but I keep receiving this error:
Symfony\Component\HttpFoundation\Response::setContent(): Argument #1 ($content) must be of type ?string, Illuminate\Routing\Redirector given, called in /var/www/html/vendor/laravel/framework/src/Illuminate/Http/Response.php on line 72
I have event listener in EventServiceProvider:
\Slides\Saml2\Events\SignedIn::class => [
SamlLoginListener::class.'#handle',
]
and then in SamlLoginListener:
public function handle(SignedIn $event)
{
$messageId = $event->auth->getLastMessageId();
// your own code preventing reuse of a $messageId to stop replay attacks
$samlUser = $event->auth->getSaml2User();
$user_data = [
'id' => $samlUser->getUserId(),
'attributes' => $samlUser->getAttributes(),
'assertion' => $samlUser->getRawSamlAssertion()
];
AuthController::saml_login($user_data);
}
Then In the AuthController::saml_login I tried all of these but the response was allways the same error:
return redirect()->away($frontend_url, 302, [
'X-SSO-AUTH-TOKENS' => json_encode($data),
]);
//
$response = new RedirectResponse($redirect_url, 302, [
'X-SSO-AUTH-TOKENS' => json_encode($data),
]);
return $response;
//
return redirect($redirect_url, 302, [
'X-SSO-AUTH-TOKENS' => json_encode($data),
]);
I decided to try it again by just returning 'ok' but still received the same error. I tried clearing the cache - no result.
Here is the full error trace: https://pastebin.com/4eZYni0w

The answer to the problem is in the error message. Your error is saying that the redirect helper method expects a string, but you're passing an object.
Not sure what version of Laravel you're using but in Laravel, Redirect responses are instances of the Illuminate\Http\RedirectResponse class and contain the proper headers needed to redirect the user to another URL.
you can try:
return redirect('/frontend_route');
Redirect to named route:
return redirect()->route('frontend_route');
If this your route has parameters like in your case, here's what to do:
return redirect()->route('frontend_route', ['X-SSO-AUTH-TOKENS' => json_encode($data)]);
Hope this helps.
source: Redirects in Laravel 8

I ended up doing this and it worked:
header("Location: " . $redirect_url);
header("X-SSO-AUTH-TOKENS: " . json_encode($data));
exit();

Related

Request header not set in test

I have a test which is trying to login and get details. I need to pass a bearer token in request header for this operation. Please see the below code. I could see that the header seldom has the headers that I set. Can anyone give me a pointer to fix this issue?
I am using Laravel 7.2.2, PHP 7.4,
And I am running php artisan test
Code:
public function a_user_can_get_details()
{
$this->create_user();
$response = $this->json('POST',
'/api/login',
[
"email" => "john.doe#example.com",
"password" => "john123"
]);
$response->assertSuccessful();
$token = Str::replaceLast('"', '', Str::replaceFirst('"', '', $response->getContent()));
$headers = [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $token
];
$response = $this->withHeaders($headers)
->get('api/user');
$response->assertSuccessful();
$this->assertCount(1, User::all());
}
And here is the error I am getting. Actually, the test must pass. That is the right user name and password:
Response status code [403] is not a successful status code. Failed asserting that false is true.
at tests/Feature/UserTest.php:141
137|
138| $response = $this->withHeaders($headers)
139| ->get('api/user');
140|
> 141| $response->assertSuccessful();
142| $this->assertCount(1, User::all());
143|
144| }
145|
I solved this issue.
Cause: I had added a middleware condition in Spatie Permissions to check for a permission for that specific route. I had to remove that to get this working.
Instead of that, I now, check the logged in status of the user. So that the route could be hit and needed checks are done inside the route.
Thanks all for the questions/comments which helped me to solve this.

How to send a request to another controller in Laravel using Guzzle

I am trying to send a POST request using Guzzle to a route defined in my routes/web.php from a model. Both the model and the controller are defined in the same Laravel application. The controller action linked to the route returns a JSON response and works fine when called from javascript using Ajax. However, when I try to do this using Guzzle, I have the following error:
GuzzleHttp \ Exception \ ClientException (419)
Client error: `POST https://dev.application.com/login` resulted in a `419 unknown status` response
When searching for a solution, I read that it may be caused by a missing csrf token, so I added it to my reuqest, but I still get the same error.
Here's the model code that uses Guzzle to send the request:
$client = new Client();
$response = $client->post(APPLICATION_URL.'login', [
'headers' => [
'X-CSRF-Token' => csrf_token()
],
'form_params' => [
'socialNetwork' => 'L',
'id_token' => $id
],
]);
APPLICATION_URL is simply the base URL of the application, starting with https://.
Am I missing something? Thanks in advance!
Don't send requests internally in your app, forward the call by dispatching post requests to routes instead
This method seems faster than using an HTTP client library like Guzzle
Your code should look something like this
$request = Request::create(APPLICATION_URL . 'login', 'POST', [
'socialNetwork' => 'L',
'id_token' => $id
]);
$request->headers->set('X-CSRF-TOKEN', csrf_token());
$response = app()->handle($request);
$response = json_decode($response->getContent(), true);
Update
You have to manually handle the response from internally dispatched routes, here's an example to get started
web.php
use Illuminate\Http\Request;
Route::get('/', function () {
$request = Request::create('/test', 'POST', ['var' => 'bar']);
$request->headers->set('X-CSRF-TOKEN', csrf_token());
$response = app()->handle($request);
$responseContent = json_decode($response->getContent(), true);
return $responseContent;
});
Route::post('test', function () {
$upperCaseVar = strtoupper(request()->var);
return response(['foo' => $upperCaseVar]);
});
Access / route by GET request and get response from /test as if it's POST request
Result
{
"foo": "BAR"
}
Hope this helps

Slim3 Cannot use object of type Slim\Http\Response as array

I am having trouble with adding error output to the JWT middleware set up.
I am getting this error: Cannot use object of type Slim\Http\Response as array
I am using Slim 3 and the slim-jwt-auth package, I am using the sample code in the docs found at https://github.com/tuupola/slim-jwt-auth#error
The difference being I'm calling \Slim\Middleware\JwtAuthentication instead of Tuupola\Middleware\JwtAuthentication. If I use that the class cannot be found. Everything was working fine until I wanted to add the error output to the middleware set up, here is my code:
$app->add(new \Slim\Middleware\JwtAuthentication([
"path" => "/mypath",
"passthrough" => "/mypath/get-auth",
"secret" => getenv("SKEY"),
"secure" => false,
"error" => function ($response, $args) {
$data = array();
$data["status"] = "error";
$data["message"] = $args["message"];
return $response
->withHeader("Content-Type", "application/json")
->getBody()->write(
json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
]));
The error output says it's coming from the line $data["message"] = $args["message"];.
Am I looking right at the problem and not seeing it?
The function signature for the "error" closure is:
function ($request, $response, $args): Response
You're missing the first parameter in your code, so when you use $args, you're getting the Response object.

Plivo - 404 error, call not found, when I try to record inbound call

I am trying to record the inbound call but so far I am only getting the 404 call not found error when record is activated.
This is my code so far (I am using Laravel and latest Plivo SDK):
public function __construct(Request $request)
{
$this->authId = config('AUTH_ID');
$this->authToken = config('AUTH_TOKEN');
$this->sourceNumber = config('sms.SMS_SOURCE_NUMBER');
$this->_answerURL = config('voiceCall.CALL_ANSWER_URL');
$this->_recordURL = config('voiceCall.INBOUND_RECORD_URL');
$this->_hangupURL = config('voiceCall.HANGUP_URL');
$this->_plivo = new RestClient($this->authId, $this->authToken);
$this->_response = new Response();
$this->_mp3Url = 'https://s3.amazonaws.com/plivocloud/Trumpet.mp3';
$this->_request = $request;
}
The answer method:
public function answer()
{
$response = $this->_response;
$response->addPlay($this->_mp3Url);
$response->addRecord([
'action' => $this->_recordURL,
'startOnDialAnswer' => "true",
'redirect' => "false",
'maxLength' => 600
]);
Log::useDailyFiles(storage_path().'/logs/debug.log');
Log::info([
'Record' => 'This is from inbound answer',
'Response' => $response
]);
return response($response->toXML(), 200)
->header('Content-Type', 'text/xml');
}
The record method:
public function record()
{
Log::useDailyFiles(storage_path().'/logs/debug.log');
$uuid = $this->_request->input('CallUUID');
Log::info(['This is Call UUID' => $uuid]);
$response = $this->_plivo->calls->startRecording($uuid);
Log::info([
'Record' => 'This is from record inbound record',
'Response' => $response,
'CallUUID' => $this->_request->input('CallUUID'),
'Request' => $this->_request->all(),
]);
}
The request is giving back the proper call uuid, and
$response = $this->_plivo->calls->startRecording($uuid);
is the code which is used in the docs. Does anyone have an idea what am I doing wrong here?
Plivo Sales Engineer here.
Is this an incoming call to your Plivo number? I see that you're returning an XML that contains a Play and Record element. This Record XML will take care of recording the call after the Play ends.
Are you making a Record API request to record this again? Which Call UUID are you passing to this API request?
For an inbound call, the Call UUID is sent to the answer URL. Are you using this Call UUID?

Yii2 blank page on redirect

I have a couple actions that I use redirects on but after transitioning to a new server all redirects now result in blank pages. I am not getting any errors in the logs and I already tried the suggestions in this question YII2 redirect causes blank page
When I echo var_dump(headers_sent()) it returns false. The Yii debug log displays the 405 status code also. Below is my action.
I've tried even using header("Location: http://www.google.com") and it also results in a blank page
public function actionDashboard()
{
if(strtotime(UserInfo::findOne(Yii::$app->user->Id)->active_until) < strtotime(date("Y-m-d H:i:s"))){
Yii::$app->session->setFlash('warning', 'Please subscribe below.');
return $this->redirect(['site/subscription'], 405);
}
$model = new Score();
$deadlines = new EDeadlines();
return $this->render('dashboard', [
'deadlines' => $deadlines,
'model' => $model,
]);
}
public function actionSubscription()
{
Stripe::setApiKey(Yii::$app->params['stripe_sk']);
$userInfo = UserInfo::findOne(Yii::$app->user->Id);
$userInfo->customer_id != NULL ? $customer = Customer::retrieve($userInfo->customer_id) : $customer = NULL;
$userPayments = StripeInvoice::find()
->where('customer_id=:customer_id', [':customer_id' => $userInfo['customer_id']])
->orderBy(['date' => SORT_DESC])
->all();
$redeem_ch = NULL;
$customer != NULL ? $account_balance = $customer->account_balance : $account_balance = 0;
if($account_balance <= -1000 && $userInfo->refund_redeemed == 0):
$redeem_ch = StripeInvoice::find()->where(['refunded' => 0, 'customer_id' => $userInfo->customer_id])->one();
$userInfo->redeem_charge = $redeem_ch->charge_id;
$userInfo->save();
endif;
return $this->render('subscription', [
'userInfo' => $userInfo,
'customer' => $customer,
'account_balance' => $account_balance,
'userPayments' => $userPayments,
'referral_count' => UserInfo::find()->where(['referrer_code' => $userInfo->your_referral_code])->count(),
]);
}
You're using incorrect status code - 405 is not for redirections:
The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed response status code indicates that the request method is known by the server but is not supported by the target resource.
The server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
You should remove this status from method call:
return $this->redirect(['site/subscription']);
Yii will use temporary redirection (302) which should be fine in this case.
Avoid array
return $this->redirect('site/subscription', 405);
and eventually use url::to
use yii\helpers\Url;
.....
return $this->redirect(Url::to(['/site/subscription'])', 405);
Be sure you effectively need 405 (405 Method Not Allowed) instead of (302 Found = default)

Categories