I am integrating a Vue JS (Quasar framework) based SPA with API. The API is built in Laravel and is using sanctum for CSRF.
When I send a request to the sanctum endpoint https://someweburl.com/sanctum/csrf-cookie it sends the XSRF-TOKEN as cookie correctly. But when I am sending the the POST request, the X-XSRF-TOKEN is not attaching itself with the header. And I am getting a 'token mismatch' error.
The front-end is on my localhost:8080 while the API is live on a url. I do not have direct access to the Laravel project but only the API.
Following is my axios configuration
import Vue from 'vue';
import axios from 'axios';
Vue.prototype.$axios = axios;
const apiBaseUrl = "https://someweburl.com";
const api = axios.create({ baseURL: apiBaseUrl });
api.defaults.withCredentials = true;
Vue.prototype.$api = api;
Vue.prototype.$apiBaseURL = apiBaseUrl;
export { axios, api, apiBaseUrl }
Following is the request format that I am trying to achieve i.e A POST request after getting the CSRF
export const fetchAllEvents = async function (context, payload) {
this._vm.$api.get('/sanctum/csrf-cookie').then(response => {
this._vm.$api.post('/api/website/event/all').then(response => {
context.commit('setAllEvents', response.data.data);
}).catch(error => {
console.log(error);
})
}).catch(error => {
console.log(error);
})
}
When I check use Postman to make the POST request with X-XSRF-TOKEN added as header, i am getting the correct response. Which means the API is working correctly. But there's some issue with axios.
Any help will be appreciated.
Maybe that is because the Axios only sets the X-XSRF-TOKEN header when the front and backend have the exact origin. You mentioned you are trying with your frontend app at your localhost and the API is on the web at another URL.
See the axios GitHub repository for more information: https://github.com/axios/axios/blob/cd8989a987f994c79148bb0cacfca3379ca27414/lib/adapters/xhr.js#L179
Related
I have built an API in AWS API Gateway. I have written the endpoints to perform basic CRUD operations as well. I am making a call to those endpoints using axios from my React frontend. The APIs in turn call AWS Lambda functions to interact with DynamoDB.
Since DynamoDB contains sensitive user data, I wish to secure it with an API key.
As per the steps mentioned here and here.
Now in order to make an API call I had the following code. Please note that I have swapped in the real values with dummy values for explanation purposes.
src/config/api.js
const customHeaders = {
"X-Api-Key": "thisIsADummyStringForExplanation",
"Content-Type": "application/json",
};
const axiosInstance = axios.create({
baseURL: "https://this.is.a.dummy.base.url/v0",
headers: customHeaders,
});
const Aws_Api_Gateway_GET = (uri) => {
return axiosInstance({
method: "get",
url: `${uri}`,
timeout: 2000,
});
};
export { Aws_Api_Gateway_GET };
Following is the Code that I wrote in order to make a GET request at the API endpoint
Aws_Api_Gateway_GET("/my-resource")
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
THE ISSUE
This code throws CORS Error. I can assure that I have enabled CORS on the API Gateway by selecting the Enable CORS option for each and every resource.
Following is the error
Access to XMLHttpRequest at 'https://this.is.a.dummy.base.url/v0/my-resource' from origin 'http://localhost:3000' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
But when I try the same using Postman, it works.
Can someone please help me get rid of the CORS Error ?
Thanks in advance.
Currently, my SPA is simple and has only a contact form. The form data is sent to the backend. I have installed Laravel Sanctum for that.
axios.get('/sanctum/csrf-cookie').then((response) => {
axios.post('api/contact')
.then((response) => {
//doing stuff
});
});
This works perfectly fine. However, I was wondering. Where and which time in your SPA do you fire the initial request to get the CSRF cookie? (axios.get('/sanctum/csrf-cookie'))
My first thoughts were:
Every time the page is mounted/loaded
Only when you receive a 419 and you attempt to refresh the token and retry the previous request
You don't fire any API requests, only when the user tries to log in and only then you are requesting a cookie (in my case I don't have any user authentification)
For each API request, you wrap it with axios.get('/sanctum/csrf-cookie') around
So for future readers, I chose:
Only when you receive a 419 and you attempt to refresh the token and retry the previous request
For that, I'm using the package axios-auth-refresh.
My settings look like that
//bootstrap.js
import axios from 'axios';
import createAuthRefreshInterceptor from 'axios-auth-refresh';
axios.defaults.withCredentials = true;
axios.defaults.baseURL = process.env.GRIDSOME_BACKEND_URL;
const refreshAuthLogic = (failedRequest) => axios.get('/sanctum/csrf-cookie').then((response) => Promise.resolve());
createAuthRefreshInterceptor(axios, refreshAuthLogic, { statusCodes: [419] });
window.axios = axios;
This question already has answers here:
Access-Control-Allow-Origin with instagram api
(1 answer)
CORS error, when i use instagram API with angularjs
(1 answer)
Closed 3 years ago.
I'm trying to fetch some images from my Instagram account in a Laravel application with Vue as front end. When I try to do it in a standalone Vue app, it works well, but when I do so with Laravel, I got a message saying "has been blocked by CORS policy: Request header field x-csrf-token is not allowed by Access-Control-Allow-Headers in preflight response."
I'm using Laravel 5.8 and the Vue and Axios that comes within in and I'm using Homestead as my localhost server.
I've tried a lot of tips that I found here and on Google but I had no success. Basically, I'm trying the very basic of Axios call
beforeMount() {
axios.get('https://api.instagram.com/v1/users/self/media/recent/?access_token=[MY_ACCESS_TOKEN]').then(response => console.log(response))
}
I already created a Cors middleware on Laravel and tried a lot of headers settings on Axios.
I'm basically trying to retrieve a list of my Instagram posts and bypass that cors / x-csrf error.
Laravel automatically applies the X-CSRF-TOKEN header to all axios requests. This is so you can communicate with your application without having to pass the CSRF token every time for POST, PUT, DELETE, etc.
resources/js/bootstrap.js (default settings)
/**
* Next we will register the CSRF Token as a common header with Axios so that
* all outgoing HTTP requests automatically have it attached. This is just
* a simple convenience so we don't have to attach every token manually.
*/
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');
}
You should be able to remove the offending header by doing something like this:
beforeMount() {
// create a new instance so we don't delete the csrf token for other requests
let instance = axios.create();
// delete the x-csrf-token header
delete instance.defaults.headers.common['X-CSRF-TOKEN'];
// use the new instance to make your get request
instance.get('https://api.instagram.com/v1/users/self/media/recent/?access_token=[MY_ACCESS_TOKEN]')
.then(response => console.log(response))
}
Your AJAX request to the Instagram API endpoint has to be sent as a jsonp request which means the dataType of the request has to be jsonp.
This blob in axios repository contains an example of sending a request using jsonp which is mentioned below.
Install jsonp package, if you haven't already.
npm install jsonp --save
and then;
const jsonp = require('jsonp');
jsonp('http://www.example.com/foo', null, (err, data) => {
if (err) {
console.error(err.message);
} else {
console.log(data);
}
});
Below is an example of sending a request using jQuery method with jsonp dataType to the Instagram API endpoint.
$.ajax({
url: "https://api.instagram.com/v1/users/self/media/recent/?access_token=[MY_ACCESS_TOKEN]",
type: "GET",
crossDomain: true,
dataType: "jsonp",
success: function(response){
console.log(response);
}
});
Im using laravel passport for token authentication, and axios for send requests from vuejs frontend. I can successfully login usin oauth/token url and it does return access token, refresh token and other data. But when every time i trying to access api/user route it returns me unauthorized error message. It seems bearer token is not in header but i cannot insert that token to axios header in bootstrap.js it also return error. Can anyone help.
You can do like ,first create an axios instance with token
const HTTP = axios.create({
baseURL: `http://baseURL.com/api`,
headers: {
Authorization: 'Bearer {token}'
}
})
Then you can use that 'HTTP' constant can be in your script to call the request
created() {
HTTP.get(`user`)
.then(response => {
})
.catch(e => {
this.errors.push(e)
})
}
Refer more here to how to work with axios
I'm trying to send a post request from a vuejs app to a spring backend with which I'm attaching a jwt authorization header.
I have tried with vue-resource
Vue.http.headers.common['Authorization'] = 'Bearer YXBpOnBhc3N3b3Jk';
and the backend headers are like this
{accept-language=en-US,en;q=0.5, origin=http://localhost:8080, host=127.0.0.1:8084, access-control-request-headers=authorization, connection=keep-alive,...
But if i use postman to send the same request, the backend headers are like this
{authorization=Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI1OTBhYWFmMjRhNjQ3ZjRiYmZlMDBhMDQiLCJzdWIiOiJiYmIiLCJpYXQiOjE0OTM5NzUxMDQsInJvbGVzIjoidXNlciIsImV4cCI6MTQ5Mzk3NTQ2NH0.kldUh3H1i3xEiNcxQ2ecq1HsjIIF5BI8Q-tb3sALc3E, content-length=0, accept-language=en-US,en;q=0.8,.......
My question is, how can i achieve the postman header using vuejs. I have tried with axios as well but without success.
Try this way with axios. I'm using spring backend too and it works..
axios.post(
url,
query ,
{headers: {
"header name" : "header value"
}}
)
.then((response) => {
var response = response.data;
}, (error) => {
var error = error.response;
}
}
)