CORS not working with React app - ajax

I tried to make a request from wikipedia api. Though I use a normal node.js server (localhost) i get this in the console:
XMLHttpRequest cannot load https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&generator=search&piprop=name|original&pilimit=max&gsrsearch=Horse&gsrlimit=20. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
This is my react component:
import React, {Component} from 'react';
import axios from 'axios';
class WikipediaViewer extends Component {
constructor(props) {
super(props);
this.state = {
data: null
}
}
componentDidMount() {
axios.get('https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&generator=search&piprop=name|original&pilimit=max&gsrsearch=Horse&gsrlimit=20')
.then(data => {
this.setState({
data: data
});
console.log(data);
})
}
render() {
return (
<h1>HEllo world!</h1>
);
}
}
export default WikipediaViewer
After having issus with the request I add following config options according to the axios documentation:
componentDidMount() {
axios.get({
method: 'get',
url: 'https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&generator=search&piprop=name|original&pilimit=max&gsrsearch=Horse&gsrlimit=20',
headers: {'X-Requested-With': 'XMLHttpRequest'},
withCredentials: true,
}).then(data => {
this.setState({
data: data
});
console.log(data);
})
}
Result:
GET http://localhost:3000/[object%20Object] 404 (Not Found)
Why am I have to get this error, though I'm working locally. Btw I used the "Allow-Control-Allow-Origin: *" Chrome extension from vitcad as well and it doesn't work.

Related

CSRF token mismatch in Laravel and Vuejs

I am using Axios to Post my data from Vue to Laravel Controller.
I have used this below code to resolve the problem. But it's not working!
import Axios from 'axios'
window.axios = require('axios');
Vue.prototype.$http = Axios;
window.axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content')
};
This is my Method which I want to Post:
onSubmit(event) {
event.preventDefault();
this.$http.post('store', {
email: this.email
}).then( (res) => {
console.log(res.data.newsletter_success)
}).catch( (err) => {
console.log(err);
})
}
What is the problem?? There is a CSRF setup in Laravel bootstrap.js file.
Well it may be caused by the first 2 lines in your code:
import Axios from 'axios'
window.axios = require('axios');
You should choose one way of importing axios and go with that
Have a look at this solution:
window.axios = require('axios');
Vue.prototype.$http = window.axios
window.axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content')
};
Now we know for sure that Vue.prototype.$http (which is window.axios) will also send the CSRF headers you set.
You can give headers like ajaxSetup
this.$http.post('store', { email: this.email},
{
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}

redirect after axios method submit on successful result

i have a form which i am using axios to submit a form in my laravel app like below :
<script>
export default {
props: [ 'route' ],
data: function () {
return {
mobile: ''
}
},
methods: {
submitMobile(){
axios.post('/customer/send-sms', {
mobile: this.mobile
})
.then(response => {
console.log(response.data)
})
.catch(function (error) {
console.log(error)
});
}
},
}
</script>
now i know it may not possible but after submiting the form if the user mobile is valid and all other conditions that i check i want to redirect user to the page that enters the the verify code
If you are using Vue router, then in your axios then block, you could do something like:
.then(() => this.$router.push('/verify-path'))
If not, there are lots of different ways to achieve the same with vanilla javascript.

NextJS api cookies are not set in response header

I'm using NextJs getInitialProps trying to refresh the access token.
if(!access_token && ctx.req) {
try {
await axios({
method: 'GET',
url: 'http://localhost:3000/api/refresh_token',
withCredentials: true,
headers: refresh_token ? { cookie: ctx.req.headers.cookie } : {}
})
console.log(ctx.res.headers)
} catch (error) {
console.log(error.response)
}
}
and this is the api endpoint:
import axios from 'axios'
import { serialize } from 'cookie'
export default async (req, res) => {
try {
const response = await axios.post('http://localhost/oauth/token', {
grant_type: 'refresh_token',
refresh_token: req.cookies.refresh_token,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
scope: '*',
})
const { access_token, refresh_token, expires_in } = response.data
res.setHeader('Set-Cookie', [
serialize('access_token', access_token, { path: '/', maxAge: expires_in, httpOnly: true, sameSite: true }),
serialize('refresh_token', refresh_token, { path: '/', httpOnly: true, sameSite: true })
])
return res.status(200).json({ message: 'yess' })
} catch (error) {
res.status(error.status || 500).end(error.response.data.message)
}
}
but when I log the response headers the cookies are not set. Chrome also doesnt show the cookies. Am I missing a step? Maybe because its server side rendering I have to do it another way? I've honestly been stuck with this for 3 days now and I've tried everything (I think so at least) and with no success. Its bugging me as I have no idea to setup proper auth in NextJs.

Request fails after retrieving JWT token

I am using Django JWT with DRF and Vue Js with axios. When a user logs in I retrieve and store the token in local storage which I have verified to work. I then redirect to a new page where I make another request to get data. Every time I redirect to this page I get a 401 not authorized and when I refresh the page it works fine. I checked to make sure the token is stored before making the second request which it is. I attempt to get the data on the redirected page in the created hook. I also create an axios instance to deal with the headers and use a base route and then import that into the files where needed, I am not sure if that has something to do with it. This also only happens when the token has expired and you try to retrieve a new one. Should I be refreshing the token instead of trying to get a new one?
Axios instance
import axios from 'axios'
export default axios.create({
baseURL: `http://127.0.0.1:8000/`,
headers: {
'Content-Type': 'application/json',
Authorization: 'JWT ' + localStorage.getItem('token')
},
xsrfCookieName: 'csrftoken',
xsrfHeaderName: 'X-CSRFToken',
withCredentials: true
})
Edit
api.js
import axios from 'axios'
export default axios.create({
baseURL: `http://127.0.0.1:8000/`,
headers: {
'Content-Type': 'application/json',
Authorization: 'JWT ' + localStorage.getItem('token')
},
xsrfCookieName: 'csrftoken',
xsrfHeaderName: 'X-CSRFToken',
withCredentials: true
})
AppLogin.vue
Confirm is triggered by clicking a login button
confirm: function() {
API.post("accounts/login/", {
email: this.email,
password: this.password,
})
.then(result => {
console.log(result.data.token);
this.token = result.data.token;
localStorage.setItem("token", this.token);
this.getUserInfo()
})
.catch(error => {
console.log(error);
});
},
getUserInfo: function(){
axios.get("http://127.0.0.1:8000/userinfo/get/", {
headers: {
'Content-Type': 'application/json',
Authorization: 'JWT ' + this.token
}
})
.then(response => {
console.log(response.data.pos);
var pos = response.data.pos;
this.reroute(pos);
})
.catch(error => {
console.log(error);
});
},
reroute(pos) {
if (pos == "owner") {
this.$router.push({ path: "/bizhome" });
} else {
this.$router.push({ path: "/" });
}
}
BizHome.vue
This is the page that login redirects to on success
created: function() {
this.getLocations();
},
methods: {
getLocations() {
API.get("business/")
.then(response => {
this.biz = response.data;
})
.catch(error => {
console.log(error);
});
API.get("locations/")
.then(response => {
this.bizLocations = response.data;
})
.catch(error => {
console.log(error);
});
},
}
solution
Using some advice that I had gotten from YuuwakU below, I added the headers directly to the get calls in the getLocations method to overwrite the axios instance headers. It appeared that the new page loaded before the token was updated in the instance. One drawback to this solution though is that I now have to directly add the headers to all the calls I make. The headers in the instance never to update. I did add API.defaults.headers.common['Authorization'] = 'JWT ' + result.data.token; to the confirm method on successful retrieval of the token which should have updated the token for the instance. This did not work for me, if anyone has any ideas I would be interested in hearing them
edit 2
I did figure out why the axios instance did not update it is because I was trying to get the token from local stroage in api.js and it was overriding it. Now it works but the token is not persistent so this is not ideal as well. I will update if I find a better solution.
Final Update
I finally figured out a good solution. I removed the authorization header from the axios instance in api.js then I removed all the headers from all the axios calls. In the confirm method upon successful login I added this line mentioned previously mentioned API.defaults.headers.common['Authorization'] = 'JWT ' + result.data.token; and also added the token to local storage. I have a verify token method that runs before pages load. In that method before I make the post request to verify the token I added API.defaults.headers.common['Authorization'] = 'JWT ' + localstorage.getItem('token'); . This allows a user to navigate aways the site and come back and still use the token if valid and does not require the headers to be set on every call.
The reason why that is happening is because an axios instance has already been created with an expired token that exists in the localStorage. So you have to make sure that the axios instance is updated with a fresh get of the token after login, otherwise you will end up using the old token until a fresh page reload. Try the following:
import axios from 'axios'
export default axios.create({
baseURL: `http://127.0.0.1:8000/`,
headers: {
'Content-Type': 'application/json',
Authorization() { // Converted to a method, similar concept to a vue data property
return `JWT ${localStorage.getItem('token')}`,
}
},
xsrfCookieName: 'csrftoken',
xsrfHeaderName: 'X-CSRFToken',
withCredentials: true
})
OR, you can even use axios interceptors as well to fetch from localStorage with each request:
// Add a request interceptor
axios.interceptors.request.use(config => {
// Do something before request is sent
config.headers = {
'Content-Type': 'application/json',
Authorization: 'JWT ' + localStorage.getItem('token')
}
return config
}, function (error) {
// Do something with request error
return Promise.reject(error);
});

Handling ajax JSONP with React

I found this post
and tried to make cross domain request with jsonp but failed both on webpack dev server and live server.
Full code
official_ajax.jsx
const UserGist = React.createClass({
getInitialState: function() {
return {
username: '',
login: ''
};
},
componentDidMount: function() {
$.ajax({
url: this.props.serverPath,
dataType: 'jsonp',
cache: false,
success: function(data) {
const title = data[0];
this.setState ({
username:title.title,
login:title.link
});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.serverPath, status, err.toString());
}.bind(this)
});
},
render:function() {
return (
<div>
{this.state.username} and <a href = {this.state.login}>here</a>
</div>
);
}
});
export default UserGist;
index.jsx
import UserGist from './official_ajax.jsx';
class App extends React.Component {
render () {
return (
<div>
<UserGist serverPath = "http://api.flickr.com/services/feeds/groups_pool.gne?id=807213#N20&lang=en-us&format=json&jsoncallback=?" />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
Every time i receive response from server that "connection is not secure".
Every ideas will be greatly appreciated.
I think about that maybe,
it's https And CORS ( Cross-Origin Resource Sharing) Policy violation.
http -> https
live Web server add-header (Cors header added)
reference URL ; http://enable-cors.org/index.html

Resources