react native 0.50.3 authorization header not sent - django

I am using react-native 0.50.3 to send token authenticated requests to my backend and unfortunately the 'authorization' part of the header is not send by the fetch.
My code is the following :
async componentDidMount() {
var mytoken = await AsyncStorage.getItem('token');
fetch('http://myserver:8000/home', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Origin': '',
'Content-Type': 'application/json',
'authorization': 'Bearer ' + mytoken
}
})
.then((response) => response.json())
.then((content) => {
this.state.user = content.user;
})
.done();
}
And on my server side, the wireshark trace shows that the authorization is not in the request header :
Hypertext Transfer Protocol
GET /home/ HTTP/1.1\r\n
Host: 10.150.21.124:8000\r\n
Content-Type: application/json\r\n
Origin: \r\n
Accept: application/json\r\n
User-Agent: Expo/2.3.0.1012011 CFNetwork/893.14 Darwin/17.3.0\r\n
Accept-Language: en-us\r\n
Accept-Encoding: gzip, deflate\r\n
Connection: keep-alive\r\n
\r\n
[Full request URI: http://10.150.21.124:8000/home/]
[HTTP request 1/1]
[Response in frame: 2326]
And of course I get a 401 unhautorized by the server.
My backend is a django API with CORS installed and CORS_ORIGIN_ALLOW_ALL = True and ALLOWED_HOSTS = ['*'].
The versions of my developments framework elements are the following :
npm 4.6.1
node v9.3.0
react-native-cli 2.0.1
One important update, the request I try to do with react-native works like a charm with postman. So the issue is not located on the server side.
Thank you for your help.
Alex.

try with trailing slash, in url address:
fetch('http://myserver:8000/home/', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Origin': '',
'Content-Type': 'application/json',
'authorization': 'Bearer ' + mytoken
}
})
.then((response) => response.json())
.then((content) => {
this.state.user = content.user;
})
.done();

Pooya's answer worked for me by adding the trailing slash on the request object. Strange because it worked on postman without the trailing slash hence the challenge in debugging. P.S i am also using the same stack, django, django REST framework (DRF) react native
fetch('http://mywebsite.com/posts/', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token
}
})

Related

the request in postman works but in angular it doesn't

enter image description here
I send the bearer token returned by the login and it works
enter image description here
the token arrives but the api response is
Authentication credentials were not provided.
Had the same issue, solved it by passing a plain object, to the headers property like so!
return this.http.post('/test/hello',
formData,
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
}
);

Fetch CouchDB to authenticate using cookie

I'm trying to authenticate against couchdb using this documentation
When I do
# first request
const url = 'http://localhost:5984/_session'
fetch(url, {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body : JSON.stringify({
"name": "my_username",
"password": "my_password"
}),
}).then( data => {
console.log(data)
}).catch(e => {
console.log('Error', e)
})
If one of my_username or my_password IS NOT right i get:
body: (...)
bodyUsed: false
headers: Headers {}
ok: false
redirected: false
status: 401
statusText: "Unauthorized"
type: "cors"
url: "http://localhost:5984/_session"
which is fine.
But, if one of my_username or my_password IS right i get:
body: ReadableStream
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:5984/_session"
instead of
HTTP/1.1 200 OK
Cache-Control: must-revalidate
Content-Length: 43
Content-Type: application/json
Date: Mon, 03 Dec 2012 01:23:14 GMT
Server: CouchDB (Erlang/OTP)
Set-Cookie: AuthSession=cm9vdDo1MEJCRkYwMjq0LO0ylOIwShrgt8y-UkhI-c6BGw; Version=1; Path=/;
HttpOnly
{"ok":true,"name":"root","roles":["_admin"]} // <-- i expect that
And no cookie set.
I also tried curl, it works :
> curl http://localhost:5984/_session
{"ok":true,"userCtx":{"name":null,"roles":[]},"info":{"authentication_handlers":
["cookie","default"]}}
> curl -X POST http://localhost:5984/_session -H "Content-Type: application/json" -d '{"name":"my_username","password":"my_password"}'
{"ok":true,"name":"my_username","roles":["_admin"]}
But I need it to work in a react app, from http:localhost:3000
Maybe it's CORS related? I enabled CORS in CouchDB settings.
How can i modify the first request in order to get the user object for the name/password supplied?
I think Authentication Set-Cookie produce by backend server not by front end. So you need backend like Node.js to get cookie and then get it again from your front end.

CORS on AWS API Gateway and S3

I am calling an AWS API which uses lambda function. I am calling it from a HTML page which is hosted in S3 (static web hosting). While calling the API I get CORS error:
Access to XMLHttpRequest at '' from origin
'' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I have tried it after enabling CORS on API, Specifying CORS on S3 bucket but it is not working.
Seems, I am missing the right place where CORS headers are to be specifies.
Additional information:
I get following information in chrome developer tool
**Response Headers**
content-length: 42
content-type: application/json
date: Mon, 24 Feb 2020 04:28:51 GMT
status: 403
x-amz-apigw-id: IYmYgFQvoAMFy6Q=
x-amzn-errortype: MissingAuthenticationTokenException
x-amzn-requestid: 79b18379-383d-4ddb-a061-77f55b5727c3
**Request Headers**
authority: apiid-api.us-east-1.amazonaws.com
method: POST
path: /Prod
scheme: https
accept: application/json, text/javascript, */*; q=0.01
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,hi;q=0.8
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
access-control-allow-methods: GET, OPTIONS
access-control-allow-origin: https://apiid.execute-api.us-east-1.amazonaws.com/Prod
content-length: 117
content-type: application/json; charset=UTF-8
origin: http://example.com
referer: http://example.com/
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Lambda function code:
var AWS = require('aws-sdk');
var ses = new AWS.SES();
var RECEIVER = 'example#gmail.com';
var SENDER = 'example#gmail.com';
var response = {
"isBase64Encoded": false,
"headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'},
"statusCode": 200,
"body": "{\"result\": \"Success.\"}"
};
exports.handler = function (event, context) {
console.log('Received event:', event);
sendEmail(event, function (err, data) {
context.done(err, null);
});
};
function sendEmail (event, done) {
var params = {
Destination: {
ToAddresses: [
RECEIVER
]
},
Message: {
Body: {
Text: {
Data: 'name: ' + event.name + '\nphone: ' + event.phone + '\nemail: ' + event.email + '\ndesc: ' + event.desc,
Charset: 'UTF-8'
}
},
Subject: {
Data: 'Website Referral Form: ' + event.name,
Charset: 'UTF-8'
}
},
Source: SENDER
};
ses.sendEmail(params, done);
}
No 'Access-Control-Allow-Origin' header is present on the requested resource.
This is saying that the resource you requested, your Lambda via API Gateway, is not returning an Access-Control-Allow-Origin header in its response; the browser is expecting the CORS headers in the response from the API (possibly because of an OPTIONS request), but the response doesn’t have them.
You’ve not said so specifically but I’m assuming you’re using a Lambda proxy integration on your API gateway. To solve your issue, add a Access-Control-Allow-Origin: * header to the response your Lambda returns. You’ve not specified the language your Lambda is written in, or provided your Lambda code, but if it was in NodeJS, a snippet of what you‘d return might look something like:
const result = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
// other required headers
},
body: object_you_are_returning
};
return result;
Very surprisingly, the reason seems to be “the client-side shouldn't have 'Access-Control-Allow-Origin': '*'. That should only be in the Lambda code, apparently, and adding it to the jQuery code will cause the preflight to fail for some reason.”
https://github.com/serverless/serverless/issues/4037#issuecomment-320434887
Supplement information following the comment:
I also tried to use ajax hosted in S3 to call my Lambda function through API Gateway. I have tried many suggestions especially this solution (http://stackoverflow.com/a/52683640/13530447), but none of them works for me. In the developer-mode of Chrome, I kept seeing the error "Access to XMLHttpRequest at '[my API]' from origin '[my S3 website]' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response." I solved this by removing 'Access-Control-Allow-Origin': '*' in ajax. Still take the solution (http://stackoverflow.com/a/52683640/13530447) as an example, it will work by changing
$.ajax(
{
url: 'https://npvkf9jnqb.execute-api.us-east-1.amazonaws.com/v1',
headers: {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'
},
crossDomain: true,
type:'GET',
dataType: 'text',
success: function(data)
{
window.alert(data);
}
});
into
$.ajax(
{
url: 'https://npvkf9jnqb.execute-api.us-east-1.amazonaws.com/v1',
headers: {'Content-Type': 'application/json'},
crossDomain: true,
type:'GET',
dataType: 'text',
success: function(data)
{
window.alert(data);
}
});

missing token ‘access-control-allow-origin’ in CORS header ‘Access-Control-Allow-Headers’ from CORS preflight channel

I'm trying to connect my a React Application to a Django Server. The React application is running on http://127.0.0.1:3000/
The response headers has Access-Control-Allow-Origin: http://127.0.0.1:3000 set, yet I am still seeing the error.
I am currently using Django's corsheaders package as recommended everywhere. Decent example of the recommendation How can I enable CORS on Django REST Framework.
But I have also tried custom middleware at this point.
My Django Settings.py file contains the following
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
Django is on 8000, React on 3000
CORS_ORIGIN_WHITELIST = [
'http://127.0.0.1:3000',
'http://localhost:3000',
'http://127.0.0.1:8000',
'http://localhost:8000',
]
My request in react looks like this. (It works when I run it directly, not through the browser)
const fetch = require('node-fetch')
const response = await fetch(
url,
{
json: true,
method: 'GET',
headers: {
'Access-Control-Allow-Origin': '*',
Accept: '*/*',
'Content-Type': 'application/json'
}
}
)
Again, it is so strange that I am making the request from http://127.0.0.1:3000 and the response headers has Access-Control-Allow-Origin: http://127.0.0.1:3000 but for some reason it is still failing.
Oh the error message in the browsers console is
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/query/?date=2019-10-25. (Reason: missing token ‘access-control-allow-origin’ in CORS header ‘Access-Control-Allow-Headers’ from CORS preflight channel).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/query/?date=2019-10-25. (Reason: CORS request did not succeed).
Any help would be awesome! Thanks
#sideshowbarker figured it out. It was because I was sending headers in my request.
Changing
const fetch = require('node-fetch')
const response = await fetch(
url,
{
json: true,
method: 'GET',
headers: {
'Access-Control-Allow-Origin': '*',
Accept: '*/*',
'Content-Type': 'application/json'
}
}
)
to
const fetch = require('node-fetch')
const response = await fetch(
url,
{
json: true,
method: 'GET'
}
)
Immediately fixed the issue! Thank you!

AWS API Gateway working through CURL but not working through javascript

Hi I am trying to hit a AWS API gateway it's working fine on CURL but not working from JS
Brocking for CROS policy.
But from AWS I already enabled CROS
$.ajax({
url: ApiURL,
type: 'POST',
dataType: 'json',
contentType: "application/json",
data: JSON.stringify(hash),
async: true,
crossDomain: true,
crossOrigin: false,
headers: {
'accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Methods': 'POST'
},
CURL method hit through AJAX
$.ajax({
url: stripTrailingSlash(BASE_URL) + '/contact/send',
type: 'POST',
dataType: 'json',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(body),
async: true,
headers: {
'X-CSRF-Token': csrfToken
},
My api gateway POST structure like this
My lambda response I did like this
const response = {
statusCode: statusCode,
headers:{ 'Access-Control-Allow-Origin' : '*' },
body: JSON.stringify({
message: responceMessage,
input: event,
}),
};
callback(null, response);
Error I am getting in my browser
It works in CURL because, CURL doesn't send OPTIONS request, but browser sends it whenever you are making a CORS request.
Response to the OPTIONS request is what browser uses to check whether you are allowed to call the API.
When you enable CORS in API Gateway, it will add the following headers
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Methods': 'POST'
but if you enable Proxy Request Integration, API Gateway no longer modifies the response to add the headers. Hence, it won't work unless your lambda function adds these header by itself.