Cookies removed when reloaded - React and Flask - python

How to I prevent chrome from removing the cookies when browser reload?
A cookies created when a user created an account shown below and the Expires/Max-age is 1 months later. However, when I reloaded/refreshed the page the cookies was gone. However, the cookies in the post-man was not deleted.
Domain (Frontend): http://localhost:3000/
Domain (Backend): http://127.0.0.1:5000/
Updated (22 Sept 2021):
React:
This is how I do my fetch request. I set the credentials to include.
fetch(domain + "/account/create", {
method: 'POST', // or 'PUT'
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(inputData),
})
.then(res => res.json())
.then(data => {
console.log('Success:', data);
return(data);
})
.catch((error) => {
setErrorMsg(error.message);
});
Flask (backend):
resp = Response(
response=json.dumps(
{ 'message': 'Account Created',
'token': f'{encoded_jwt}'}),
status=200,
mimetype="application/json"
)
resp.headers.add('Access-Control-Allow-Origin', 'http://localhost:3000')
resp.headers.add('Access-Control-Allow-Credentials', 'true')
resp.set_cookie('token', value=encoded_jwt, httponly= True, expires = TOKEN_EXPIRY_DATE, samesite='None', secure=True)

You are all doing it right.
I am just getting some suspect on your TOKEN_EXPIRY_DATE it's must be datetime object.
See the documentation
Check your expires value.
If it's still making problem.
Use flask-login instead. It will going to store your user auth. And manage all your logins it's so easy to use.

Related

Getting 401 error : "invalid_client" in django-oauth-toolit

I am trying to have an Ouath2 access token based authentication. I am using django-oauth-toolkit for that. I have registered my app on http://localhost:8000/o/applications.
However, When I tried to hit the URL http://localhost:8000/o/token/ from the react-app . I got 401.
Here is my the useEffect hook that I used for calling that URL :
useEffect(() => {
// axios.get("api/tests")
// .then((res)=>{
// setUsers(JSON.stringify(res.data))
// })
fetch("http://localhost:8000/o/token/", {
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: client_id,
client_secret: client_secret
}),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${btoa(client_id+":"+client_secret)}`}
,
method: "POST"
}).then((res)=>{
console.log(res)
})
}, [])
Will look forward to some comments and solutions.
I got the solution. Actually I was Using the encrypted version of the client secret. I forgot to copy it before saving. Once it is saved the value is encrypted. So it's better to copy it somewhere prior saving it.

flask_jwt_extended.exceptions.NoAuthorizationError: Missing Authorization Header

Server-side flask
#project_ns.route('/projects')
class ProjectsResource(Resource):
#project_ns.marshal_list_with(project_model)
#jwt_required()
def get(self):
"""Get all projects """
user_id = User.query.filter_by(username=get_jwt_identity()).first() # Filter DB by token (username)
projects=Project.query.filter_by(user_id=user_id)
#projects = Project.query.all()
return projects
client-side reactjs
const getAllProjects=()=>{
const token = localStorage.getItem('REACT_TOKEN_AUTH_KEY');
console.log(token)
const requestOptions = {
method: 'GET',
headers: {
'content-type': 'application/json',
'Authorization': `Bearer ${JSON.parse(token)}`
},
body: "Get projects listed"
}
fetch('/project/projects', requestOptions)
.then(res => res.json())
.then(data => {
setProjects(data)
})
.catch(err => console.log(err))
}
I specified header on the client side and the error still occurs:
flask_jwt_extended.exceptions.NoAuthorizationError: Missing Authorization Header
my flask versions are as follows:
Flask==2.0.1
Flask-Cors==3.0.10
Flask-JWT-Extended==4.2.3
Flask-Migrate==3.1.0
Flask-RESTful==0.3.9
flask-restx==0.5.0
Flask-SQLAlchemy==2.5.1
I have tried many options and the issue is still persisting. Would love to come to a resolution. Thanks in advance!
I haven't used these libraries before, but it sounds like it might possibly be an issue with the Flask-RESTful library?
https://stackoverflow.com/a/52102884/2077884
https://github.com/vimalloc/flask-jwt-extended/issues/86#issuecomment-335509456
https://github.com/vimalloc/flask-jwt-extended/issues/86#issuecomment-444983119
If you're not getting a value for console.log(token), I would start there. And maybe check to see if you can decode the token details via https://jwt.io/ to ensure that the value you have for token is valid.

Fetch content from API

My frontend (ReactJS) is located at localhost:3000 which sends a request to my backend (localhost:5090/api/fetch/<name>)
frontend-snippet:
handleSubmit(event) {
//alert('A name was submitted: ' + this.state.value);
fetch('http://127.0.0.1:5090/api/fetch/' + this.state.value,
{
mode: 'no-cors'
}).then((response) => console.log(response));
event.preventDefault();
}
the backend receives the request:
127.0.0.1 - - [22/Oct/2020 10:54:44] "GET /api/fetch/212 HTTP/1.1" 200 -
and responses with {"stock": name}
Python
def get(self, name):
print(name)
return {"stock": name}
however, i'm unable to get the response.
What am I missing, that I can actualy see the response data of {"stock": <name>}?
Sending a request with no-cors returns an opaque type object.
Updating my backend to allow all sources
What happens with cross-origin requests from frontend JavaScript is that browsers by default block frontend code from accessing resources cross-origin. If Access-Control-Allow-Origin is in a response, then browsers will relax that blocking and allow your code to access the response.
from flask_cors import CORS
...
CORS(app, resources={r"/api/*": {"origins": "*"}})
and then removing the mode to cors in frontend
fetch('http://127.0.0.1:5090/api/fetch/' + this.state.value,
{
}).then(response => response.json())
.then(response => {
console.log(response)
})
.catch(error => {
console.log('Error ' + error);
})
successfully displays the data
(response)
{stock: "111"}
Can you try like this
.then(response => response.json())
.then(result => {
console.log(result);
})
})
.catch(error => {
console.log('Error ' + error);
})
code in Ejaz's answer should work just fine, But I'd recommned you to read the official documentation for fetch api
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
You cant just console.log the response from fetch api it just returns a promise,
you cant print response.body either as it returns a readable stream, Use interface methods on body to read the stream into completion.
You can call response.text() or response.json() depending on type of data your api returns.
Using fetch api, you have to deal with promises, I'll try to refactor your handleSubmit function using async/await, much cleaner way to deal with promises.
async handleSubmit(event) {
event.preventDefault();
try{
let response = await fetch('http://127.0.0.1:5090/api/fetch/'+this.state.value, {
mode: 'no-cors'});
console.log(await response.json());
}
catch(error => console.log('Error ' + error));
}

send metatags through Google Cloud Signed URL with Django

I'm using signed url to get or post/put video fileq on my google storage. My modules refers on signed_url V4 and it's working quite well.
I wanted to add some metadata tags to my requests in order to manage more efficiently the charges related to GCS. But since I added those headers, the requests failed returning a cors policy error : (I have shortened the signature in the block above to make it more readable)
Access to XMLHttpRequest at 'https://test-dev-slotll.storage.googleapis.com/uploads/dave/FR/eaa678c9/2020/9/785f/f45d3d82-785f_full.mp4?X-
Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=dev-storage%40brilliant-tower-264412.iam.gserviceaccount.com%2F20200926%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20200926T093102Z&X-Goog-Expires=3600&X-Goog-SignedHeaders=host%3Bx-goog-meta-account&x-goog-signature=6fbb27e[...]bd0891d21' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
and the detailed message:
<Error>
<Code>MalformedSecurityHeader</Code>
<Message>Your request has a malformed header.</Message>
<ParameterName>x-goog-meta-account</ParameterName>
<Details>Header was included in signedheaders, but not in the request.</Details>
</Error>
The cors are conigured to allow almost everything on my bucket :
[{"maxAgeSeconds": 3600, "method": ["*"], "origin": ["*"], "responseHeader": ["*"]}]
and here is the Python/Django function
def _get_signed_url(self, http_method="GET"):
"""' create a signed url with google storage
create a 'GET' request by default,
add method='w' or 'put' to create a 'PUT' request
get_signed_url('w')->PUT / get_signed_url()->GET
"""
if http_method.lower() in ["w", "put", "post"]:
http_method = "PUT"
else:
http_method = "GET"
signed_url = generate_signed_url(
settings.GS_BUCKET_NAME,
self.file.name,
subresource=None,
expiration=3600,
http_method=http_method,
query_parameters=None,
headers={'x-goog-meta-language':'french','x-goog-meta-account':'david',},
)
return signed_url
As I wrote it above, method get_signed_url() is copied from signed_url V4
if i replace headers = {'x-goog-meta-language':'french','x-goog-meta-account':'david',},
by hearders = {} or headers = None (as it was previously, it works fine
last, when I click on the link given by the signed-url, I got an error message:
The signed url as well as blob uploading or downloading are working fine without the headers for months but I do not see why the server is responding that the header meta tags are malformed...
I will appreciate any help
thanks !
I was getting the same error message when I was performing a GET request on the pre-signed urls from GCP. Adding the content-type: "application/octet-stream" solved it for me.
ajaxCall_getFile = $.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
return xhr;
},
type: 'GET',
url: <PRE-SIGNED URL>,
contentType: "application/octet-stream",
processData: false,
success: function(file_data){
alert("file downloaded");
},
error: function(err) {
alert('Download failed, please try again.');
}
});
As #Sideshowbarker suggests it in his comments, the problem came from the client.
The signed url was used to send files to storage through ajax but no custom header were added to the ajax.
By specifying the headers in the ajax, the PUT request of a signed url with custom metadata works well.
function ajaxSendToStorage(uuid, url) {
// Sending ONE file to storage
var file = getFileById(uuid);
$.ajax({
method: "PUT",
contentType: file.type,
processData: false,
dataType: "xml",
crossDomain: true,
data: file,
url: url,
headers: {"x-goog-meta-account":"david","x-goog-meta-language": "fr"},
success: function() {},
complete: function() {},
});
}

Node JS and Python - POST image from Node JS to Python REST API

I have a Node JS application. I want to send an image from the Node JS application to a REST API which is written in Python. The key and the inputs needed by the Python REST API are as follows
My problem is that I am able to POST a simple 'Hello World' string with the code I have written and get a response. However, when I try to send an image something goes wrong and I get no response.
var http = require('http');
var querystring = require('querystring');
// This is some dummy string data
var postData = querystring.stringify({
msg: 'hello world'
});
var fs = require('fs')
, path = require('path')
, certFile = path.resolve(__dirname, 'ssl/client.crt')
, keyFile = path.resolve(__dirname, 'ssl/client.key')
, caFile = path.resolve(__dirname, 'ssl/ca.cert.pem')
, request = require('request');
// I want to send an image from one server to another. What changes should I make to the options below for POSTing image data
var options = {
hostname: '127.0.0.1',
port: 8888,
path : '/predict',
//image: fs.createReadStream('car.jpg'), //Should I give something like this??
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
'Content-Length': postData.length
}
};
var req = http.request(options, function (res) {
console.log('STATUS:', res.statusCode);
console.log('HEADERS:', JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY:', chunk);
});
res.on('end', function () {
console.log('No more data in response.');
});
});
req.on('error', function (e) {
console.log('Problem with request:', e.message);
});
req.write(postData);
req.end();
Please let me know what changes I have to make to this code to post an image.I read about the use of multer package. However, the examples that I came across were using JS on both ends. Since for me, I have a Python REST API , I cannot use that. PLease help since I have been struggling with it for some time now.
Edit 1: Based on #Jana's suggestion, I added the multipart within the options and tried, where image is the key and the value is fs.createReadStream('car.jpg') . However, at the python end, it does not get the 'image' key because of which I get a False response. What am I missing?
var options = {
hostname: '127.0.0.1',
port: 8888,
path : '/predict',
//image: fs.createReadStream('car.jpg'), //Should I give something like this??
multipart: [
{
'content-type': 'application/json',
body: JSON.stringify({'image': fs.createReadStream('car.jpg') })
}
],
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
//'Content-Length': postImageData.length
}
};
Check this,
`request({
method: 'POST',
uri: 'http://127.0.0.1:8888/predict',
multipart: [{
'content-type': 'application/json',
body: JSON.stringify({
"key": "value"
})
},
{
body: fs.createReadStream('car.jpg')
}
],
},
function(error, response, body) {
if (error) {
return console.error('upload failed:', error);
}
console.log('Upload successful! Server responded with:', body);
})`
And also you can get the best examples from its own documentation Request - Simplified HTTP client

Categories

Resources