so I am trying to get the active user off of a fetch request to my backend.
My front end code is:
let apiToken: string | null = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
fetch('http://192.168.0.6:8000/api/testURL', {
method: "POST",
//#ts-ignore
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text-plain, */*',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': apiToken
},
credentials: 'same-origin',
body: JSON.stringify(data)
})
.then(function(response): void {
console.log(response);
})
.catch(function(err): void {
console.log(err);
});
I have a CSRF token in a meta tag that is generated from csrf_token();
My backend code is:
Route::post('/testURL', function(Request $request)
{
$status = $request->input('status');
$comment = $request->input('comment');
$prospectType = $request->input('prospectType');
$leadId = $request->input('leadId');
$requestUser = $request->user();
return response()->json([
'status' => $status,
'comment' => $comment,
'prospectType' => $prospectType,
'leadId' => $leadId,
'user' => $requestUser
]);
});
The end result from the API call back shows 'user' as null.
I have tried Auth::user() & Auth::id() and they all return null.
I am at a lose and tried using Sanctum to create a validation token which when I added an auth:sanctum middleware it returned a 302 to redirect.
(The same redirect is happening when I apply a vanilla "auth" to a non-Sanctum token'd request).
The request out of all of this!
I want to ensure I have user by ID validation when I send up the request from the frontend to the backend.
I figured it out, the reason the request was not working correctly was the sanctum.php config file did not have my local IP (what I am running my php artisan serve off of) in its 'stateful' array.
I hope this helps anyone! That was five hours of my life.
Related
I am facing CSRF token mismatch problem in laravel. I have checked all notes from stackflow and other sites also but not able to clear this problem.
https://mybestlife.mg-wellness.com/admin/login
user : admin#gmail.com
pass : 1234
you can check the error in console.
Ajax
$("#loginform").on('submit', function(e){
e.preventDefault();
$('button.submit-btn').prop('disabled', true);
$('.alert-info').show();
$('.alert-info p').html('Authenticating...');
$.ajax({
type:"POST",
url:$(this).prop('action'),
data:new FormData(this),
headers: headers,
dataType:'JSON',
contentType: false,
cache: false,
processData: false,
success: function(data) {
console.log(data);
if ((data.errors)) {
$('.alert-success').hide();
$('.alert-info').hide();
$('.alert-danger').show();
$('.alert-danger ul').html('');
for(var error in data.errors) {
$('.alert-danger p').html(data.errors[error]);
}
} else {
// console.log(data)
$('.alert-info').hide();
$('.alert-danger').hide();
$('.alert-success').show();
$('.alert-success p').html('Success !');
window.location.href = data;
}
$('button.submit-btn').prop('disabled',false);
}
});
});
Login function
public function doLogin(Request $request)
{
// print_r($request->all());
$rules = [
'email' => 'required|email',
'password' => 'required'
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json(array('errors' => $validator->getMessageBag()->toArray()));
}
//--- Validation Section Ends
// Attempt to log the user in
if (Auth::guard('web')->attempt([
'email' => $request->email,
'password' => $request->password,
'status' => 1,
'role' => 1,
'level' => 0
], $request->remember)) {
// if successful, then redirect to their intended location
return response()->json(route('dashboard'));
}
// if unsuccessful, then redirect back to the login with the form data
return response()->json(array('errors' => [
0 => 'Credentials Doesn\'t Match !'
]));
}
Code is working perfectly on localhost and my testing server. But not on the server, i shared above.
Please help me to over come this problem.
Thanks
I think you're missing a header. That's how I've always passed the CSRF token when I use ajax.
The following should be in your resources/js/bootstrap.js file.
window.$ = window.jQuery = require('jquery');
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
});
When trying to login using your site, I couldn't see the X-CSRF-TOKEN header in the request.
I think you didn't set the APP_URL's value correctly. It should be
APP_URL=https://mybestlife.mg-wellness.com instead of what you currently have. (APP_URL=http://localhost/mybestlife_mg_wellness/)
(run php artisan config:clear after changing .env file)
Your site has debug mode on and an unrelated error about the route 'user_login' not existing, this exposes your whole configuration. Please take care to update your database credentials, they are compromised.
This is very important.
Also, rerun the command php artisan key:generate to update the APP_KEY as well.
you have to add #csrf in your form
<form method="post" action="javascript:void(0)" enctype="multipart/form-data">
#csrf
</form>
also add header in jquery
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
also add this meta tag in head of page
<meta name="csrf-token" content="{{ csrf_token() }}">
then you will never get token error .
Add a below line in data array
data:{
_token : {{csrf_field()}},
name:name
}
I have a SPA based on Laravel 5.8 and Vue 2.0.
Everything is working fine, a little bit too much to be honest, because if I delete the session and I try to save the content afterward or keep navigating the private pages, every ajax call that I'm doing with Axios is going through without returning any error. Only if I forcefully refresh the page I get the error page I setup but if I don't, I can keep doing everything even if the session no longer exist.
This is my setup.
web.php is where I have the only php route that points to a singlePageController:
Auth::routes();
Route::get('/{any}', 'SinglePageController#index')->where('any', '.*');
Then in the singlePageController I return the view:
class SinglePageController extends Controller
{
public function index() {
return view('app', ['loggedUser' => auth()->user()]);
}
}
Then I have the api.php where I have the API routes. As you can see at the end I have the middleware to make it private. Just to make an example this is the one I use for updating the content:
Route::put('event/update/{slug}', 'EventController#update')->middleware('auth:api');
Then the related controller of that API route:
public function update(Request $request, $slug)
{
$event = Event::where('slug', $slug)->first();
$event->title = $request->input('title');
return new EventResource($event);
}
And in the end this is the Resource I use to define what and how the API data is going to be displayed:
public function toArray($request)
{
// return parent::toArray($request);
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'curator' => $this->curator,
'featured_image' => $this->featured_image,
'body' => $this->body,
'date' => $this->date
];
}
So this above is the flow I have. Then when I do an axios call to update the content, I'm doing something like:
axios({
method: 'PUT',
url: '/api/event/update/' + this.$route.params.slug + '?api_token=' + this.isLogged.apiToken,
data: dataToSave,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
})
.then((response) => {
this.getNotification('Success: The Event has been saved');
})
.catch((error) => {
this.getNotification('Error: Impossible saving the event');
console.log(error);
})
Thanks in advance for the help
In Laravel routes in api.php ignore the session data.
If you want to authenticate with session data you could move your api routes to web.php and you should see the results you expect.
I have a SPA using VUE and LARAVEL 5.8
I have setup an API_TOKEN associated to the logged in user. Everything works fine right after the login. I get the API_TOKEN, I save it into a var and I send it together with the Axios request. In Laravel I have a middleware that is taking care of the token and comparing it with the one setup on the logged in user.
the problem though occur when session expires. Because I still can navigate the private pages and make API requests to save and delete content. This is possible I think because I still have the same API_TOKEN saved in the var and the middleware apparently doesn't get that the session is expired.
So I want to obtain the API_TOKEN every time I'm doing an Ajax, request so when the session expires, I won't get the token and therefore, I won't be able to complete the request.
This is my setup.
web.php is where I have the only php route that points to a singlePageController:
Auth::routes();
Route::get('/{any}', 'SinglePageController#index')->where('any', '.*');
Then in the singlePageController I return the view:
class SinglePageController extends Controller
{
public function index() {
return view('app', ['loggedUser' => auth()->user()]);
}
}
Then I have the api.php where I have the API routes. As you can see at the end I have the middleware to make it private. Just to make an example this is the one I use for updating the content:
Route::put('event/update/{slug}', 'EventController#update')->middleware('auth:api');
Then the related controller of that API route:
public function update(Request $request, $slug)
{
$event = Event::where('slug', $slug)->first();
$event->title = $request->input('title');
return new EventResource($event);
}
And in the end this is the Resource I use to define what and how the API data is going to be displayed:
public function toArray($request)
{
// return parent::toArray($request);
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'curator' => $this->curator,
'featured_image' => $this->featured_image,
'body' => $this->body,
'date' => $this->date
];
}
So this above is the flow I have. Then when I do an axios call to update the content, I'm doing something like:
axios({
method: 'PUT',
url: '/api/event/update/' + this.$route.params.slug + '?api_token=' + this.isLogged.apiToken,
data: dataToSave,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
})
.then((response) => {
this.getNotification('Success: The Event has been saved');
})
.catch((error) => {
this.getNotification('Error: Impossible saving the event');
console.log(error);
})
Do you know how to make it? or if there is a better way to accomplish that?
you and do like, your login method should like this.
public function login(Request $request)
{
if (Auth::attempt(['email' => $request['email'], 'password' => $request['password']])) {
$user = Auth::user();
$success = $user->createToken(config('app.name'))->accessToken;
return response()->json(["token" => $success, 'status' => 200]);
} else {
return response()->json(['message' => "Email or Password do not match"], 401);
}
}
I'm currently setting up a new project in Laravel.
Upon logging in I want to store the logged in user's token. so, I can make other API request in other controllers using this format,
Code:
$response = $client->request('POST', '/api/user', [
'headers' => [
'Authorization' => 'Bearer '.$token,
'Accept' => 'application/json',
],]);
I'm not quite sure, how I will store $token so it can be accessed in all controllers.
Normally, APIs that use token based authentication require the token to be sent with each request as the APIs are, hopefully, stateless. This means that whatever controller of yours is handling the user request will also have the token to perform other requests in the background. In your controller, you should be able to retrieve the token like so:
class MyController
{
public function index(Request $request)
{
$authorization = $request->header('Authorization');
$token = null;
if (substr($authorization, 0, 7) === "Bearer ") {
$token = substr($authorization, 7);
}
// in theory, this is obsolete as your controller should only
// be called if there is a valid token present on the request
if ($token === null) {
abort(403); // or whatever
}
$client = ...; // initialize the client
$response = $client->request('POST', '/api/user', [
'headers' => [
'Authorization' => 'Bearer '.$token,
'Accept' => 'application/json',
],
]);
// return some response to the user
}
}
Obviously it makes sense to extract the token parsing into its own function which lives in a base controller that all other controllers inherit from. In your concrete example you could also simply use ['headers' => ['Authorization' => $request->header('Authorization')]] as you only want to forward the header.
Old answer which doesn't make any sense:
Store the token in the session data of the user:
session(['token' => $token]);
The array indicates that you set data in the session. Retrieving the token is even easier:
$token = session('token');
I have this add method in my vue script
if (this.edit === false) {
this.link.link = submitEvent.target.elements.link.value;
fetch('products', {
method: 'POST',
body: JSON.stringify(this.link),
headers: {
'content-type': 'application/json'
}
})
.then(res => res.json())
.then(res => { // this does not get executed
this.qrcode.redirect_url = "";
alert('Added');
this.fetchAll()
})
.catch(err => console.log(err.res));
}
}
When I fill the form the request is send and entry is made to the database but I do not get response.
I am using laravel as backend and Add method in Controller returns 200 response after creation.
What could cause it and why console.log(err) does not not display anything?