419 Error when attempting to post to my controller - laravel

I've been trying to submit a post request with axios to my projects controller and I keep getting an error 419(unknown status). Even though I'm passing the CSRF through headers to the controller. When I go into my network tab after posting it says:
X-CSRF-TOKEN: undefined
X-Requested-With: XMLHttpRequest
However, when I console.log(window.csrf_token) it returns a token.
This is included in my layout.blade.php
<script type="text/javascript">
window.csrf_token = "{{ csrf_token() }}"
</script>
I define the headers in my app.js for vue:
const axios = require('axios');
axios.defaults.headers.common = {
'X-CSRF-TOKEN': window.csrf_token,
'X-Requested-With': 'XMLHttpRequest',
};
and in my projects.vue here is my axios post request:
Swal.queue([{
title: 'Add a New Project?',
input: 'text',
inputAttributes: {
autocapitalize: 'on'
},
showCancelButton: true,
confirmButtonText: 'Create Project',
showLoaderOnConfirm: true,
preConfirm: (result) => {
return new Promise(function(resolve, reject) {
if (result) {
console.log(result)
axios.post('/api/projects', {title:result})
.then(function(response){
Swal.insertQueueStep({
type: 'success',
title: 'Your project has been created!'
})
resolve();
})
.catch(function(error){
Swal.insertQueueStep({
type: 'error',
title: 'Something went wrong.'
})
console.log(error);
reject();
})
}
});
}
}])
aswell as the store method in ProjectsController.php
public function store()
{
$validated = request()->validate([
'title' => 'required',
]);
Project::create($validated);
return response()->json($validated);
}

Most probably you are setting the CSRF token in your layout file after the usage hence the reason of getting undefined.
Try using the default way, which is by putting a meta tag in your head of the main template like this:
<meta name="csrf-token" content="{{ csrf_token() }}">
Then to use it you may open the given bootstrap.js file where this code is already set:
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
Or if this does not exist, put it in your app.js script or whichever you use on every page.

Related

CSRF TOKEN MISTATCH LARAVEL

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
}

Laravel Sanctum + Vue Auth

I have an API that is secured using Laravel Sanctum. In the front-end I managed to login with sanctum and a new bearer token is issued. So far so good but how can I store the token (without Vuex) to local storage and how I tell axios to use that token for any future requests ?
My code is as follows:
// AuthController.php
public function login(Request $request)
{
$fields = $request->validate([
'email' => 'required|string',
'password' => 'required|string'
]);
$user = User::where('email', $fields['email'])->first();
$token = $user->createToken('login_token')->plainTextToken;
if (!$user || !Hash::check($fields['password'], $user->password)) {
return response([
'message' => 'Invalid Login Credentials'
], 401);
}
$response = [
'user' => $user,
'token' => $token
];
return response($response, 201);
}
// Login.vue
export default {
methods: {
handleLogin() {
axios.get("/sanctum/csrf-cookie").then(response => {
axios.post("/api/login", this.formData).then(response => {
if (response.status === 201) {
this.$router.push({ path: "/" });
}
console.log(response);
});
});
}
},
data: function() {
return {
logo: logo,
formData: {
email: "",
password: ""
}
};
}
};
The login works fine, it is returning the expected results but I don't know how to store the generated token and how to send it to any future axios requests.
Thanks.
*** UPDATE ***
Ok so I figured it out how to send the headers and I'm doing it like so:
axios
.get("/api/expenses/", {
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + "6|cnuOY69grhJiZzxEHoU74PapFkkcJeqbf3UiKx8z"
}
})
.then(response => (this.expenses = response.data.data));
}
The only remaining bit to this is how can I store the token to the local storage because right now, for testing purposes I hard coded the token.
In your Login.vue script
methods:{
loginUser(){
axios.post('/login',this.form).then(response =>{
localStorage.setItem('token', response.data.token) //store them from response
this.alerts = true
this.$router.push({ name: 'Dashboard'})
}).catch((errors) => {
this.errors = errors.response.data.errors
})
},
}
In your logged in file lets call it Dashboard.vue in <script>,
data(){
return {
drawer: true,
user: {roles: [0]},
token: localStorage.getItem('token'), //get your local storage data
isLoading: true,
}
},
methods: {
getUser(){
axios.get('/user').then(response => {
this.currentUser = response.data
this.user = this.currentUser.user
}).catch(errors => {
if (errors.response.status === 401) {
localStorage.removeItem('token')
this.$router.push({ name: 'Login'})
}
}).finally(() => {
setTimeout(function () {
this.isLoading = false
}.bind(this), 1000);
})
},
},
created(){
axios.defaults.headers.common['Authorization'] = `Bearer ${this.token}` //include this in your created function
this.getUser()
this.isCreated = true
}
I hope it works well for you
Ok so this is how I sorted this out.
Storing the token in the local storage:
localStorage.setItem("token", response.data.token);
Using the token when sending an axios call to the api:
const token = localStorage.getItem("token");
axios
.get("/api/endpoint/", {
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + token
}
})
.then(response => (this.expenses = response.data));
}

post request using axios on Laravel 7

i am trying to post request on server by axois but unfortunately page is refreshing on button click how can i resolve this issue please help me thanks.
html view
axois script
<script>
$(document).ready(function(){
$("#prospects_form").submit(function(e) {
let url = "{{route('home.store')}}";
var name =$("#name").val();
var email =$("#email").val();
axios.post(url, {
params:{
name: 'name',
email:'email'
}
}).then((res)=>{
console.log(res);
}).catch(function(err){
console.log(err);
});
});
});
</script>
Route
Route::post('/home/store', 'HomeController#store')->name('home.store');
controller
public function store(Request $request)
{
$this->validate(
$request,
[
'name' => 'required',
'email' => 'required|email|unique:subscribes,email',
],
[
'name.required' => 'Name is required',
'email.required' => 'Email is required'
]
);
$subscribes = new Subscribe();
$subscribes = $request->name;
$subscribes = $request->email;
return response()->json($subscribes, 200);
}
axios send data in body not in params ref link https://github.com/axios/axios#note-commonjs-usage
axios.post(url, {
name: 'name',
email:'email'
}).then((res)=>{
console.log(res);
}).catch(function(err){
console.log(err);
});
params is used for get request
and to not refresh on form submit you can try
$("#prospects_form").submit(function(e) {
e.preventDefault()
and you need to preventDefault form action so u can submit form via ajax
so your final code will be
<script>
$(document).ready(function () {
$("#prospects_form").submit(function (e) {
e.preventDefault();
let url = "{{route('home.store')}}";
var name = $("#name").val();
var email = $("#email").val();
axios
.post(url, {
name: name,
email: email,
})
.then((res) => {
console.log(res);
})
.catch(function (err) {
console.log(err);
});
});
});
</script>
Use e.preventDefault(); Like given below
<script>
$(document).ready(function(){
$("#prospects_form").submit(function(e) {
e.preventDefault();
let url = "{{route('home.store')}}";
var name =$("#name").val();
var email =$("#email").val();
axios.post(url, {
params:{
name: 'name',
email:'email'
}
}).then((res)=>{
console.log(res);
}).catch(function(err){
console.log(err);
});
});
});
</script>

Laravel Spark 6.0 Ajax request unauthenticated

I am building an app from a vanilla Spark 6.0 installation. I can login, access the Kiosk and click around.
I have created a new Card section with a form and am using the SparkForm object as directed by the documentation; however every single request returns unauthenticated and thus I have to re-login.
I cannot get the ajax request to authenticate. I have created a seperate adminApi to handle admin ajax request which is protected by auth/dev/web middleware.
Any ideas/pointer much appreitated.
Relevent Code:
RouteServiceProvider:
public function map(Router $router)
{
$this->mapWebRoutes($router);
$this->mapApiRoutes($router);
$this->mapAdminApiRoutes($router);
//
}
...
protected function mapAdminApiRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace,
'middleware' => ['dev', 'auth', 'web'],
'prefix' => 'admin/api',
], function ($router) {
require base_path('routes/adminApi.php');
});
}
routes/adminApi.php
Route::resource('/insurers', 'Admin\InsurersController');
vue component - insurers.js
var base = require('kiosk/users');
Vue.component('spark-kiosk-insurers', {
mixins: [base],
data: function() {
return {
showingInsurerProfile: false,
form: new SparkForm({
name: '',
email:'',
logo:''
})
}
},
props: {
insurer: {}
},
methods: {
search: function() {
},
create: function() {
Spark.post('/admin/api/insurers', this.form)
.then(response => {
console.log(response);
});
},
}
});
Add the CSRF Token to the form like
<meta name="csrf-token" content="{{ csrf_token() }}">
Then add the following to your request:
headers: {
'X-CSRF-TOKEN': 'Token Here' // from meta
}

Laravel ajax 422 Unprocessable Entity even when token is matching

I'm getting 422 Unprocessable Entity error even when I'm submitting my form via Ajax.
My javascript file
$.ajaxSetup({
headers: {
'X-XSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('.keywords-plan-form').submit(function(event) {
event.preventDefault();
$.ajax({
url: '/laravel/public/keywordsplans',
type: 'POST',
data: $(this).serialize(),
success: function(data){
alert(data);
// success logic
},
error: function(data){
// Error...
var errors = $.parseJSON(data.responseText);
console.log(errors);
$.each(errors, function(index, value) {
});
}
});
});
as you can see I added X-XSRF-TOKEN****strong text to ajax header.
This is my '' tag
<meta name="csrf-token" content="{{ csrf_token() }}">
my Form Data in chrome debuger
_token:5j6DGhhTytbIRB1GrW9Wml9XrOxmKjgE9RiGa4Gf
date:
keyword[0]:Lorem ipsum
keyword[1]:Is dolor amet
keyword[2]:plumber tampa
Request Headers
X-XSRF-TOKEN:5j6DGhhTytbIRB1GrW9Wml9XrOxmKjgE9RiGa4Gf
.....
am I doing something wrong or forgetting something?
I don't think that csrf token is the issue here. If it were you would get TokenMissmatchException and not Unprocessable Entity.
Do you happen to have a request validator in your Controller like this?
$validator = Validator::make($request->all(), [
'username' => 'required|max:30|min:6|unique:users',
'email' => 'required|email|max:50|unique:users',
'password' => 'required|confirmed|min:6',
]);
If so maybe you can do something like this:
if ($validator->fails()) {
if($request->ajax())
{
return response()->json(array(
'success' => false,
'message' => 'There are incorect values in the form!',
'errors' => $validator->getMessageBag()->toArray()
), 422);
}
$this->throwValidationException(
$request, $validator
);
}
After that you can catch validation errors in your ajax error handler like this:
$('.keywords-plan-form').submit(function(event) {
event.preventDefault();
$.ajax({
url: '/laravel/public/keywordsplans',
type: 'POST',
data: $(this).serialize(),
success: function(data){
alert(data);
// success logic
},
error: function(jqXhr, json, errorThrown){// this are default for ajax errors
var errors = jqXhr.responseJSON;
var errorsHtml = '';
$.each(errors['errors'], function (index, value) {
errorsHtml += '<ul class="list-group"><li class="list-group-item alert alert-danger">' + value + '</li></ul>';
});
//I use SweetAlert2 for this
swal({
title: "Error " + jqXhr.status + ': ' + errorThrown,// this will output "Error 422: Unprocessable Entity"
html: errorsHtml,
width: 'auto',
confirmButtonText: 'Try again',
cancelButtonText: 'Cancel',
confirmButtonClass: 'btn',
cancelButtonClass: 'cancel-class',
showCancelButton: true,
closeOnConfirm: true,
closeOnCancel: true,
type: 'error'
}, function(isConfirm) {
if (isConfirm) {
$('#openModal').click();//this is when the form is in a modal
}
});
}
});
});
And see the messages in the
modal message
Maybe someone will come in handy.
422 Unprocessable Entity
is default error by validator laravel
vendor/laravel/framework/src/Illuminate/Validation/Validator.php
If fails validate params, then throught Exception ValidationException
vendor/laravel/framework/src/Illuminate/Validation/ValidationException.php
where default status = 422
And therethore all your ajax responses with non validate forms will be with status = 422
I have solved this issue :
public function register(\Illuminate\Http\Request $request) {
if ($this->validator($request->all())->fails()) {
$errors = $this->validator($request->all())->errors()->getMessages();
$clientErrors = array();
foreach ($errors as $key => $value) {
$clientErrors[$key] = $value[0];
}
$response = array(
'status' => 'error',
'response_code' => 201,
'errors' => $clientErrors
);
} else {
$this->validator($request->all())->validate();
$user = $this->create($request->all());
$response = array(
'status' => 'success',
'response_code' => 200
);
}
echo json_encode($response);
}
Whoever is still looking for the answer, if you are using Lumen make sure the Request object is a type of Illuminate\Http\Request and not the default one from Lumen.
```function create(Request $request){

Resources