I am making my first app with React, interacting with a Django Rest Framework back-end application. They both are running in their local servers.
I found that requests from the React front-end (that are sent with Axios) requiere a csrftoken cookie. I read and followed Django Documentation about it, but I always get an undefined csrftoken cookie.
This is the code of the request:
handleClick() {
var csrftokenCookie = Cookies.get('csrftoken');
console.log(csrftokenCookie);
const axios = require('axios');
axios.post('http://127.0.0.1:8000/es/api-auth/login/', {
next: '/',
username: 'some_name',
password: 'secret'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
}
I print to console the result of the Cookies.get('csrftoken'), and I can see that it is always undefined.
I don't know what I am missing in order to be able to get the csrftoken cookie.
Related
Has anyone successfully implemented CSRF protection for a form submitted with React (as a controlled component) to a Flask back-end (ideally with WTForms)? I've seen a lot of partial answers, and one with Django, but couldn't find anything definitive for Flask. My big issue seems to be that I don't know how to send the csrf token to my react front end, store it as a header before submitting my form, then submit my form with the correct token. Any direction would be really helpful.
So, essentially what I did is I set up a route in Flask that can receive both GET and POST requests. React sends a GET request when the component mounts, and Flask responds with the csrf token as a header (done manually). Then React stores this value in state. When the form is submitted, the csrf token from state is sent as a field, similar to the way it is sent in a pure Flask app, where it would be a hidden field. While this technically works, I am curious if this is still vulnerable to CSRF. I think the next best option is to set up CSRF protection on all endpoints, so can try that if this isn't secure.
Flask route:
#app.route('/api/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
print(request.method)
if request.method == 'GET':
return ('', {'csrf_token': form.csrf_token._value()})
elif form.validate_on_submit():
return { 'message': 'Login successful' }, 200
else:
return { 'errors': form.errors }
GET request in componentDidMount:
componentDidMount() {
axios.get('/api/login',{data: null, headers: {'Content-Type': 'application/json'}})
.then(res => {
console.log(res)
this.setState({
csrf: res.headers.csrf_token
});
})
}
POST request when form is submitted:
onSubmitLogin = e => {
e.preventDefault();
const userData = {
username: this.state.username,
password: this.state.password,
csrf_token: this.state.csrf
};
axios({
method: 'post',
url: '/api/login',
data: userData,
headers: {
'content-type': 'application/json'
}
})
.then(res => {
console.log(res);
});
}
Maybe you need flask-security-too lib
https://flask-security-too.readthedocs.io/en/stable/patterns.html#csrf
I created a joke generator app that takes jokes from a local json file with data that I created and displays it in the browser. This app has no backend at all. I am trying to make a GET request through Postman, but no luck. Is it even possible to use postman in this scenario?
NO Postman is not used for programmatic api calls. Use axios for this. Suppose your server is running on localhost:3000.
npm install axios
In your component,
const axios = require('axios');
// Make a request for a user with a given ID
axios.get('/jokes?id=1')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
I am using mern stack to make an application. For authentication i am using toke auth with passport authentication and for security reasons i am sending token in cookie. I have a login call which returns a cookie with response. The snippet is below:
res.cookie("cookie_token", token, { maxAge: 84600 });
res.send({
status: "success"
});
I can see the cookie in postman and even in browser in network(xhr request).
I am using axios for making call to the login api in react js.
axios.get(myapiurl, {
headers: {
email: fields.email,
password: fields.password,
"access-control-allow-origin": "*"
}
})
.then(res => {
console.log(res);
}).catch((err) => {
console.log(err);
});
Though i can't find a snippet to access the cookie in react js. How can i parse it? I can't see cookie in response of axios though? How can i access it.
Please try this. Snippet from mdn.
function getCookie(sKey) {
if (!sKey) { return null; }
return document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + sKey.replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1") || null;
}
export function getLoginInfo() {
const cookieToken = getCookie('cookie_token')
console.log(cookieToken)
}
I'm creating a node web app that needs to integrate with some azure services using Azure REST API. I'm using the node MSAL library for user login and retrieving an access token for making requests to the Azure REST api. I'm able to login a user successfully and retrieve an access token. However, when I try to make a request to Azure's REST api I am receiving a 401 error that says error="invalid_token", error_description="The access token is from wrong audience or resource."
The web app itself is built with Node LTS and React v16.8.6. It has been deployed in Azure and registered with active directory.
I'm using MSAL v1.0.1 to login a user and retrieve a token when the user lands on the login page.
login.js
import React, { Component } from 'react';
import * as Msal from 'msal';
let msalConfig = {
auth: {
clientId: process.env.REACT_APP_CLIENT_ID,
authority: `https://login.microsoftonline.com/process.env.REACT_APP_TENANT_ID'`,
navigateToLoginRequestUrl: false,
redirect_uri: 'http://localhost:3000/newEntry',
resource: 'https://management.azure.com/'
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
var msalInstance = new Msal.UserAgentApplication(msalConfig);
var tokenRequest = {
scopes: ['https://management.azure.com/']
}
class Login extends Component {
constructor(props) {
super(props);
this.state = {
response: null,
};
}
componentWillMount() {
// prevent login loop by checking for logged in user and then acquire a token if logged in
if (!msalInstance.getAccount() && !msalInstance.isCallback(window.location.hash)) {
this.login();
} else {
msalInstance.acquireTokenSilent(tokenRequest)
.then(res => localStorage.setItem('access_token', res.accessToken))
.catch(err => console.error(err))
}
}
login = () => {
msalInstance.handleRedirectCallback((error, response) => {
if (error) console.error(error);
console.log(response);
})
msalInstance.loginRedirect(tokenRequest);
}
render() {
return (
<div>
<h2>Login</h2>
</div>
)
}
}
export default Login;
I am successfully returning an access token and putting it in local storage.
On a separate page I am retrieving the MSAL access token from local storage and using it to make a request to retrieve all resources associated with my Azure subscription.
componentWillMount() {
let token = localStorage.getItem('access_token');
let url = 'https://management.azure.com/subscriptions/process.env.REACT_APP_SUBSCRIPTION_ID/resource?api-version=2018-02-14'
fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
})
.then(response => console.log(response))
.catch(err => console.error(err));
}
I suspect I'm getting the error because there is some discrepancy between the resource value sent with the login request and the scope value sent with the token request.
I've attempted changing the resource value to 'resource': 'https://management.core.windows.net/' per Azure: The access token has been obtained from wrong audience or resource but that didn't change anything.
I've also attempted various scopes including https://management.azure.com/user_impersonation and https://management.azure.com//user_impersonation following this example Access Token do not include access for API with MSAL
The get method is default, and the problem might be in 'Authorization': `Bearer ${token}`.
Sometimes people use different rules, like 'Authorization': token, or 'Token': `Bearer ${token}`.
I see some API using 'S-token': token. try that. I thinkit is because the token did get there.
You are using msal, so resource parameter is not needed in your msalConfig. You can remove it.
Change the scopes to scopes: ['https://management.azure.com/.default'].
So I ended up switching to the ADAL library to see if I would get the same error and I did. I did however realize the resource request URL wasn't correct. The api-version wasn't an accepted version. Once I switched it to 2018-02-01 the request returned 200.
makePlaylist = event => {
event.preventDefault()
let token = localStorage.getItem('token')
let playlist = {name: this.state.text, public:false}
axios.post(
`https://api.spotify.com/v1/users/${this.state.user_id}/playlists`, playlist,
{headers: {
"Authorization": 'Bearer ' + token
}
}
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
and I get the following error
https://api.spotify.com/v1/users/my_user_id_here/playlists 403 error
I looked up the documentation online at
https://developer.spotify.com/documentation/web-api/reference/playlists/create-playlist/
and it looks like I'm setting things up as far as I can tell. Anyone know what I'm doing wrong with the request? I know the access token is valid.
"Trying to create a playlist when you do not have the user’s authorization returns error 403 Forbidden." Make sure that the Spotify app that you made in Dashboard has the proper scope permissions on the user you are trying to create the playlist for. Here is the scope for creating a private playlist: https://developer.spotify.com/documentation/general/guides/scopes/#playlist-modify-private
Here is the tutorial for setting up authorization with passing in a scope:
https://developer.spotify.com/documentation/general/guides/authorization-guide/