Unable to logout via an ajax request in Laravel - ajax

I am using Laravel 5.1 and I am trying to setup a simple login/logout system. I can easily login using:
Auth::attempt(['email' => $request->email, 'password' => $request->password]);
But if I try to logout via an ajax request using Auth::logout();, it does not log out the user. Manually going to the logout route in a browser tab however works just fine.
note: if my controller looks like this:
public function logout()
{
Auth::logout();
dd(Auth::user());
}
Then the request returns null. This should indicate the user has been logged out, but if I pass another request - I am still logged in.
Edit
Ajax call:
import request from 'superagent'
request.get(env.api + endpoint)
.withCredentials()
.set({
'X-Requested-With': 'XMLHttpRequest'
})
.end((err, res) => {
if (err) return reject(err);
return resolve(res.body);
})
EDIT
I found the source of my problem. It was a single route that looked like this:
Route::get('image/users/{image}', ['as' => 'fetch.users.images', 'uses' => 'Files#fetchUserImage']);
Changing the route path image/users/{image} solved my problem. Still curious as to why this caused an error with Auth? The route was not interfering with any of my other routes.
Edit
My above edit was wrong. It is to do with that route but its not the naming.
I am requesting an image from the route Route::get('image/users/{image}', ['as' => 'fetch.users.images', 'uses' => 'Files#fetchUserImage']); whose associated controller looks like this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Storage;
class Files extends Controller
{
public function __construct()
{
$this->middleware('basic');
}
public function fetchUserImage($image)
{
$image = 'users/images/' . $image;
if (Storage::disk('s3')->exists($image)) {
return response(Storage::disk('s3')->get($image), 200, ['Content-Type' => 'image/jpeg']);
} else {
return response('Image not found', 404);
}
}
}
I am requesting the image with JS like this:
let img = new Image();
img.onload = () => this.state.update ? this.setState({image: props.src}) : null;
img.src = this.props.src;
When Laravel returns 404 or false or anything that isn't an image, the JS sends the request again. After I logout, Laravel still has an image request to process and the response('Image not found', 404) gets triggered after my logout succeeds and then as the response contains the logged in session info, my browser gets indirectly logged back in.
Haven't come up with a fix for this yet. Not sure how to go about it.

Related

InertiaJs Redirect returns 302 but doesn't render

Really sorry if this has been covered before but I can't find a working solution and have even asked numerous work colleagues.
I have a form which sends a POST request to my MailController, validation and everything works just as expected, but on success, I want to redirect to a Thank you page. The Post request returns either a 200 or 302 depending on the method I try but every time it only sends the HTML to the response and doesn't render the component.
I can, however, navigate to that page if I visit the URL and it loads perfectly.
I've tried
to_route
Inertia::render
Redirect()
Redirect()->route()
Redirect::route()
even sending it in response, catching it in Axio's request in the component, and redirecting from there.
This is driving me nuts I just can't see what I'm doing wrong.
TIA for your help and suggestions
//controller
<?php
namespace App\Http\Controllers;
use ...
use Inertia\Inertia;
use...
class MailController extends Controller
{
public function sendEmail(Request $request)
{
$contact = $request->validate([
......
],[
.......
]);
Mail::to('email#email.co.uk')->send(new ContactEmail($contact));
return Redirect::route('thankyou');
// return response()->json([
// 'data' => $contact,
// 'message' => 'Message sent successfully.',
// 'redirect' => route('thankyou')
// ], 201);
}
}
// route
Route::get('/thankyou', function () {
return Inertia::render('Thankyou');
})->name('thankyou');
// submit function
submitContact: function () {
axios.post('/email', this.contact)
.then(response => {
console.log(response.data.redirect);
// if (response.data.redirect) {
// return Inertia.location(response.data.redirect);
// }
}).catch(err => {
const errors = err.response.data.errors;
if (err) {
Object.keys(errors).forEach(key => {
this.errors[key] = errors[key][0];
});
}
})
}

Foursquare API over Axios (Ajax) in Laravel not returning any data (500 internal server error)

So I'm trying to get company details via the Foursquare API after a user gives in a business name and a location name.
For example: "Huntrs" and "Brussel" should get this business' details via Foursquare API and then return them.
So far i'm trying to do this over Axios to make an Ajax call within the Laravel framework.
ajax.js - Axios call:
//Ajax function to get company details when the getCompanyDetails() function is called on a btn click
function getCompanyDetails(){
//Get company name and location from form
let businessName = document.querySelector('#businessName').innerHTML;
let businessLocation = document.querySelector('#businessLocation').innerHTML;
//Make the actual API GET request
axios.post('/getcompanydetails', {
params: {
businessName: businessName,
businessLocation: businessLocation
}
})
.then(res => {
console.log(res);
console.log(res.data);
//Add response data to empty form fields
})
.catch(function (error) {
//Log request error in console, maybe also show onpage?
console.log(error);
})
}
web.php - Routing
Route::post('/getcompanydetails', 'AjaxController#getCompanyDetails'); //Route for ajax call made from JS file ajax.js
AjaxController.php - Controller that handles Guzzle request to API for ajax calls
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Client;
class AjaxController extends Controller
{
//Make Foursquare API request with Guzzle!
public function getCompanyDetails() {
//Get params back from the Axios get Request
$params = json_decode(file_get_contents("php://input"),true);
$location = $params['businessLocation'];
$companyName = $params['businessName'];
//Setup actual Guzzle request
$client = new Client();
$result = $client->request('GET', 'https://api.foursquare.com/v2/venues/search', [
'query' => [
'client_id' => env('FOURSQUARE_CLIENT_ID'),
'client_secret' => env('FOURSQUARE_SECRET_ID'),
'v' => "20191009",
'near' => $location,
'query' => $companyName,
'limit' => 1
]
]);
//Return $result in JSON format to ajax.js
return response()->json($result);
}
}
As Saly 3301 said i had to check the network tab:
network -> preview tab in chrome dev tools
This said the businessLocation index was undefined.
Solution:
Within the ajax.js, I removed the params{} around my actual name and location parameters and that stops the 500 internal error.
As such:
axios.post('/getcompanydetails', {
businessName: businessName,
businessLocation: businessLocation
})

Laravel Ajax login, redirect to previous url after success

Suppose I have a page A where auth middleware is being used. Because of no login it gets redirected to login page.
On login page I have custom ajax login system. On succesful login I want to redirect to page A with same url so that action can be completed.
My code for login is like this:
public function postLogin(Request $request)
{
$auth = false;
$errors = [];
$inputs = $request->all();
$validator = $this->validator($inputs);
if ($validator->fails()) {
return response()->json([
'auth' => false,
'intended' => URL::previous(),
'errors' => $validator->errors()
]);
}
$user = User::where('email', $request->get('email'))->first();
if ($user && $user->is_active == 0) {
$errors[] = "This account has been deactivated";
} else if ($user && $user->confirm_token != null) {
$errors[] = "Please verify your email in order to login";
} else {
$credentials = ['email' => $request->get('email'), 'password' => $request->get('password'), 'is_active' => 1];
if (Auth::attempt($credentials, $request->has('remember'))) {
$auth = true;
} else {
$errors[] = "Email/Password combination not correct";
}
}
if ($request->ajax()) {
return response()->json([
'auth' => $auth,
'intended' => URL::previous(),
'errors' => $errors
]);
}
return redirect()->intended(URL::route('dashboard'));
}
I am trying to get previous url through url()->previous() but it returns login page url. Can someone guide me in this please. Any improvements/help will be appreciated.
I am using Laravel 5.4
I have a very similar problem here: Ajax Auth redirect on Laravel 5.6
As #aimme (https://stackoverflow.com/users/1409707/aimme) pointed out, Ajax calls are stateless, so basically you can't interact with backend.
His suggestion and my suggestion is to pass in the URL the intended page to redirect to, or maybe in your case you could to it via post parameters, e.g.:
return response()->json([
'auth' => false,
'intended' => $request->intended,
'errors' => $validator->errors()
]);
There is no need to do anything special for AJAX calls.
Redirect the same way you normally would on the back-end after a form submission.
return redirect()->route('dashboard');
On the front-end you just need to be sure that you use the redirected URL to change the window.location. This will cause the browser to refresh and go to the new page.
axios.post(url, formData).then(response => {
window.location = response.request.responseURL;
});
This code snippet is for the popular Axios library but the same thing can be done with jQuery or vanilla JavaScript.
It might help you
Instead of these return redirect()->intended(URL::route('dashboard'));
use
return redirect('dashboard');
Laravel 5.4 + support . not know for lower version
return redirect()->back();
This will redirect to previous page from where you came .
Ajax part
<script type="text/javascript">
var url = "<?php echo url()->previous(); ?>";
location.href = url;
</script>
OR simply javascript function
history.go(-1);
Check for above and working fine for me please check for your code .
If I understand your problem correctly, the problem is that you're confusing the previous URL for the intended URL when you're trying to provide a URL to redirect to in your JSON response. The previous URL actually refers to the HTTP Referrer, not the intended URL, which is set in the session by Laravel's auth middleware.
The HTTP referrer is the page that initiates a request. If you are currently on page /foo and you click a link to a page /bar, the HTTP Referrer on /bar will be /foo. The same thing happens when you initiate an AJAX request, the page you're on will be the referrer of the end point you're hitting. In your case your login page is initiating the request to your login handler, via AJAX.
When you try to visit a page protected by Laravel's auth middleare, it is at that point Laravel sets a value for the intended URL in the session, before redirecting you to the login page. Laravel stores the intended URL in the session as url.intended (As you will be able to see in Illuminate\Routing\Redirector::intended, which is what redirect()->intended() calls). So all you need to do is grab that from the session.
if ($request->ajax()) {
return response()->json([
'auth' => $auth,
'intended' => session()->pull('url.intended') ?: URL::route('dashboard'),
'errors' => $errors
]);
}
return redirect()->intended(URL::route('dashboard'));
Note: Using ->pull will remove the item from the session after it has been retrieved.
An easier way to do this would be just to grab the target URL from an intended RedirectResponse:
$redirect = redirect()->intended(URL::route('dashboard'))
if ($request->ajax()) {
return response()->json([
'auth' => $auth,
'intended' => $redirect->getTargetUrl(),
'errors' => $errors
]);
}
return $redirect;
I solved it by making a hidden field in form containing url()->previous() value because no other way I was getting previous page i.e Page A url. I tried almost all above answers.
URL::previous();
this method will help you get previous URL. and you can redirect user to there using jQuery somelike this:
window.location.href = url; // <- you can try your url here.
Good Luck !!
First of all when you got a request in backend save the redirect()->intended();
intended() checks if the session index url.intended exists and
redirects to it by default or else redirect to $default='/' which can
be overwritten.
then pass this URL when request success, example:
function testAjax(handleData) {
$.ajax({
url:"getvalue.php",
success:function(data) {
window.location.href = data.url;
}
});
}

laravel passport giving Unauthenticated error

I am using laravel passport but when I try to hit the post route that gives me user data it's giving me error like
{"message":"Unauthenticated."}
here is my controller method
public function getDetails()
{
$user = Auth::user();
return response()->json(['success' => $user], $this->successStatus);
}
api.php
Route::post('register', 'API\PassportController#register')-
>name('register');
Route::post('login', 'API\PassportController#login')->name('login');
//Route::post('details', 'API\PassportController#getDetails')->middleware('auth:api');
Route::group(['middleware' => 'auth:api'], function(){
Route::get('user', 'API\PassportController#user');
Route::post('details', 'API\PassportController#getDetails');
});
screenshot of postmen
please let me know what inputs you want from my side
Your codes look ok to me, but if I'm not mistaken you added your "Authorization" manually: please try this way from the image below, by clicking on Authorization tab, left next to Headers tab.
And make sure that your token is the one that is returned from the server when you make login request: see the image below.

Redirects an authenticated user back to the originally requested URL or the default URL in laravel

I am new at laravel and I want to achieve the following results, let's say a guest gets to the result page after searching for a term and then decides to login, how can I get the user to login and keep the same result page in laravel
I have the following code
in the filters.php I have the following:
Route::filter('guest', function()
{
if (Auth::check()) return Redirect::to('/');
});
then in the user controller I have the following
the show login function
public function login()
{
return View::make('users.login');
}
the handle login function
public function handleLogin()
{
$data = Input::only(['email', 'password']);
if(Auth::attempt(['email' => $data['email'], 'password' => $data['password']])){
return Redirect::to('/profile');
}
return Redirect::route('login')->withInput();
}
right now the default page after login goes to the profile page but I want the user to go back to wherever he was before login.
any help? thanks
I think that's what you looking for
return Redirect::back();
In Laravel 4, you can use Redirect::guest and Redirect::intended to achieve your target easily.
Redirect::guest put the current URL into the session before redirect to the target URL.
Redirect::intended check whether there is any URL saved in the session, redirect to that URL or a default location if it does not exist.
In action, your code can be:
if(Auth::attempt(['email' => $data['email'], 'password' => $data['password']])){
return Redirect::guest('/profile');
}
and after log in
if (Auth::check()) return Redirect::intended();

Resources