Error message: No Firebase ID token was passed as a Bearer token in the Authorization header. Make sure you authorize your request by providing the following HTTP header: Authorizaiton: Bearer or by passing a "__session" cookie
There actually is a valid token. This same setup works in other functions but not here. The main difference is that this is a delete instead of a post.
firebase
.auth()
.currentUser.getIdToken(true)
.then((token) => {
console.log(token)
return axios.delete(
`${FunctionsDir}/deleteMessage`,
{
messageID: messageID,
},
{
headers: {
Authorization: `Bearer ${token}`,
'content-type': 'application/octet-stream',
},
}
)
})
and the cors setup...
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1 || !origin) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
allowedHeaders: 'Content-Type,Authorization',
methods: 'GET,POST,DELETE',
preflightContinue: false,
optionsSuccessStatus: 200,
}
app.options('*', cors())
app.use(cors(corsOptions))
Update: Fixed, turned out to be the cors thing plus the axios.delete() sig was wrong.
This is likely a CORS issue that needs to be solved on the server.
This is because DELETE requests need to make a pre-flight request to the server asking what is acceptable to send. Because you got a response from your server, it is likely that you have already added DELETE to your Access-Control-Allow-Methods header. However, Authorization isn't considered a "safe header" by default. So you must also explicitly allow it, otherwise browsers will remove it from the request as they send it off. You can do this by adding Authorization to your Access-Control-Allow-Headers header.
If you are using Express on your server, you can allow the cors package to do this for you:
import express from "express";
import cors from "cors";
const app = express();
app.options("/deleteMessage", cors()); // enable preflight request for DELETE
app.use(cors({ origin: ["https://yourapp.com"] })); // enable CORS for all routes
// ...
If you don't like making use of third-party dependencies, you can manually add the headers as shown in this answer.
For non-express requests, like a HTTP Request Cloud Function, you can use the following code:
import express from "express";
import cors from "cors";
const corsMiddleware = cors({ origin: ["https://yourapp.com"] }); // or your manual (req, res, next) function
export const someFunction = functions.https.onRequest((req, res) => {
corsMiddleware(req, res, (err) => {
if (err) {
res.status(500).send('CORS check failed');
return;
}
// your code here
}
})
Related
I am trying to make request to a third party api from express, i want express to serve as a proxy, and send the result to the front end. the problem is that the route on the frontend has qyeries and parameters, this is my code
app.get("/api/posts/:id", function (req, res) {
request(
"https://api.xxxx.com/yyyy/1897970/user",
{
headers: {
Authorization: API_KEY,
"Content-Type": "application/json",
},
},
function (error, response, body) {
const per_page = req.query.per_page;
const page = req.query.page;
const query = req.query.query;
const id=req.params.id;
if (!response.body) {
console.log(error);
} else {
res.send({
body,
id,
"per-page": per_page,
page: page,
query: query
});
}
}
);
});
On the front end, i have to make request to a route like
axios
.get(
`/api/posts/{id}/query?per_page=10&page=${title}`)
.then((res) => {
}).catch((err)=>{console.log (err) })
The problem is that it returns an error 404, it cannot get the data, please what am i doing wrong?
The URL in the get is not a full URL. change it to the full URL of your backend, if you are in localhost so localhost.
Add proxy to the package.json in react client to fetch the data from the backend
"proxy": "http://localhost:3000",
the proxy should be the port on which the backend is running.
I saw many tutorials on jwt authentication but every video maker uses Postman to show what's happening and they pass on the header in the headers section while requesting a URL in Postman. I tried to do it with JavaScript but I was not able to do it.
I want to do jwt authentication but after token generation, I send it to client side to use it for further requests but I failed to do so after trying it a few times. I also tried to set req.headers in server side but it didn't do what I wanted to..
I want to set request headers for authentication of the form "Bearer {token}" for every request after token generation. How to do it with JS??
What I am most concerned about is that every tutorial does it with postman but they didn't show how they implemented it in their own app. I hope my question is clear.
You can easily add header on your http request like that
it has been solved here Node.JS: How to send headers with form data using request module
In vanilla nodejs:
const uri = "http://example.com";
const options = {
headers: {
"Authorization": "Bearer ...."
}
}
// require http/https lib
let req = require("http").request(uri, options, (res) => {
const chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.once("end", () => {
// concat body chunks
let body = Buffer.concat(chunks);
console.log(body.toString());
});
});
req.on("error", (err) => {
console.log(err);
});
req.end();
https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_options_callback
Something like that:
$.ajax({
url: url,
beforeSend: function(xhr) {
xhr.setRequestHeader("custom_header", "value");
},
success: function(data) {
}
});
First install jwt and express framework using npm then make a middleware file which will check if the tokek is set or not.
Middleware.js :
let jwt = require('jsonwebtoken');
const config = require('./config.js');
let checkToken = (req, res, next) => {
let token = req.headers['authorization']; // Express headers are auto converted to lowercase
if (token) {
if (token.startsWith('Bearer ')) { // Checks if it contains Bearer
// Remove Bearer from string
token = token.slice(7, token.length); //Separate Bearer and get token
}
jwt.verify(token, config.secret, (err, decoded) => { //Inser the token and verify it.
if (err) {
return res.json({
status: false,
message: 'Token is not valid'
});
} else {
req.decoded = decoded;
next();
}
});
} else {
return res.json({
status: false,
message: 'Access denied! No token provided.'
});
}
};
Next, create a config file which will contain the secrets.
Config js:
module.exports = {
secret: 'worldisfullofdevelopers'
};
Finally, create a token route which will create your token and after that the rest of the calls will be authenticated for that token.
Index.js :
const middleware = require('./middleware');
const jwt = require("jsonwebtoken");
const config = require('./config.js');
//Call token Route
app.use('/token', (req, res, next) => {
//Generate Token
let token = jwt.sign({ username: "test" },
config.secret,
{
expiresIn: '1h' // expires in 1 hours
}
);
//Send Token
res.json({
success: true,
message: 'Authentication successful!',
token: token
});
});
//Add Authentication to all routes
app.use(middleware.checkToken);
//===> All the routes after middleware will be checked for token
app.use('/getUser', (req, res, next) => {;
console.log('do something')
});
If I understand correctly, you want to set the HTTP header on the client, in order to pass an authentication token to the server. I would recommend that you use a library like **axios*.
Using axios, once you receive the toke, set the header for every outgoing communication with the following line of code:
axios.defaults.headers.common['Authorization'] = "Bearer " + token;
This will set the authentication http header to the form you need.
My web server is working fine when I call it through chrome. However when I am using fetch or axiom in my react-app to call the same url, it returns 404 Not Found. The react-app also sends a options request to same url which returns status 200. I have even set this header to allow the origin.
app.use(async (ctx, next) => {
var origin = ctx.headers.origin;
ctx.set({
'Access-Control-Allow-Headers': 'authorization,Content-Type,refresh',
'Access-Control-Allow-Methods': "GET,HEAD,POST,PUT,DELETE",
'Access-Control-Allow-Origin': '*',
'Connection': 'keep-alive',
'Access-Control-Allow-Credentials': true
});
await next();
console.log('______________')
});
require('./routes')(app); //2
my ./routes.js file contain
//router.post('/signin' , signinController.signin);
router.get('/signin' , signinController.signin);
can you please tell me what I am missing here. My axios call
axios.get('http://localhost:3002/signin')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Alright I tried your code out and it works for me if I use app.use(router.allowedMethods()) middleware to pass preflights, OR declare separate option-routes for each route; Or instead of using router.get() there is router.all('/signin', ...) which will also catch options-requests.
This is my complete server code:
const app = new Koa();
const router = new Router();
router.get('/signin' , (ctx, next) => {
ctx.body = '{"status":"hello"}';
});
// Adding a options-route works (instead of router.allowedMethods())
router.options('/signin' , (ctx, next) => {
ctx.body = '';
});
app.use(async (ctx, next) => {
var origin = ctx.headers.origin;
ctx.set({
'Access-Control-Allow-Headers': 'authorization,Content-Type,refresh',
'Access-Control-Allow-Methods': "GET,HEAD,POST,PUT,DELETE",
'Access-Control-Allow-Origin': '*',
'Connection': 'keep-alive',
'Access-Control-Allow-Credentials': true
});
await next();
console.log('______________')
});
app.use(router.routes());
// app.use(router.allowedMethods()); // This works instead of separate option-routes.
app.use((ctx, next) => {
console.log('here');
next();
});
app.listen(9787);
And this is my call:
axios.defaults.headers.common['Authorization'] = "sometoken";
axios.get('http://localhost:9787/signin').then(response =>{
console.log(response); // {data: {…}, status: 200, ... }
});
(I had to add the header or the CORS won't trigger.)
I've tried setting various origin and headers and it does obey your middleware.
But I did notice that if you choose to use allowedMethods(), that will override your Access-Control-Allow-Methods (and make it useless).
It has to do with cross origin support
You can use this package #koa/cors#2 to add cors support
const Koa = require('koa');
const cors = require('#koa/cors');
const app = new Koa();
app.use(cors());
Heres the link to the package
https://github.com/koajs/cors
I have a React application using axios as HTTP library, express server that uses http-proxy-middleware package and API express server that contains APIs.
React application should communicate with API server through proxy authentication server like this:
Within my React application I created this test method:
testReq(){
axios.get('http://localhost:5000/applicationData/checkMe', {
withCredentials: true,
headers: {
'x-access-token': '...'
}
})
.then(response => console.log(response.status))
.catch(e => console.log(e))
}
This is how my proxy method looks like:
server.use('/applicationData', authenticate, proxy({
target: 'http://localhost:4000',
changeOrigin: false,
onProxyReq(proxyReq, req) {
// proxyReq.setHeader('x-access-identity-email', req.decodedToken.email)
},
}))
and this is authenticate middleware function used above:
module.exports = (req, res, next) => {
const token = req.headers['x-access-token']
console.log('token', token)
if (token) {
verifyToken(token, global.config.secret).then((verificationResponse) => {
const { decoded, message } = verificationResponse
if (!decoded) return res.status(401).json({ message })
req.decoded = decoded
return next()
})
.catch((err) => {
console.error(err)
res.status(500).json({ message: 'Internal error' })
})
} else return res.status(401).json({ message: 'Missing authentication token' })
}
I enabled CORS on both API and Proxy servers like this:
server.all('/*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
res.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, x-access-token')
res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')
res.header('Access-Control-Allow-Credentials', 'true')
next()
})
The problem is that I get this response when request is sent:
I assume it's due to authentication middleware trying to access x-access-token header from OPTIONS request which doesn't exist and therefore returns 401. If I remove authentication middleware from proxy method then requests go through.
How do I make x-access-token present in OPTIONS requests? Or else, what is the proper way to handle this situation?
in facebook not allowing to paste code not sure, why, so pasting here:
in your middleware missing is (for options part as you have commented):
if (req.method == 'OPTIONS') {
res.send(200);
}
else {
next();
}
for error part, as you have said authentication triggering before cors part, so you may have to set that code before authentication (security part I am not much sure)
I think the line:
res.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, x-access-token')
should be:
res.header('Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, x-access-token')
I recently created a server and deployed it to Heroku. It works fine in Postman and when testing out basic GET requests. But whenever I try to make POST request to it via Axios in my client, I am met with this error.
In my back-end server, I enabled cors so that it could make cross-domain requests. Here, on lines 67 and 69, I set up cors before declaring my routes (click here to see the full 'app.js' file on my github.)
My register router works fine in Postman, and its response time is below 30 seconds, at 1877 milliseconds.
Interestingly, when I make a conditional GET requests to my API in my client, it works. (The lines of code where I make aforementioned GET request are on line 222-258 here)
In my client, the problem arises whenever I want to make a POST request in my client. Here is network response I get in the image below.
If I go to the response tab, it shows my POST request timing out at 30.1 seconds, despite the fact that the same API request was finished in 1.8 seconds in Postman.
Here is the code in particular where I am making the POST request in my index_actions.js file.
import axios from 'axios'
export function register(fields) {
console.log('below are the fields');
console.log(fields);
return function action(dispatch) {
let objArrSkills = Object.keys(fields.form_skills);
let skillsArr = objArrSkills.map(function (value) {
if (fields.form_skills[value] === true && fields.form_skills[value] !== undefined) {
return value;
}
});
let objArrArts = Object.keys(fields.form_arts);
let artsArr = objArrArts.map(function (value) {
if (fields.form_arts[value] === true && fields.form_arts[value] !== undefined) {
return value;
}
});
console.log('artsArr is...' + artsArr);
console.log('skillsArs is...' + skillsArr);
const request = axios({
method: 'post',
url: "https://jammr-backend.herokuapp.com/register",
data: {
firstName: fields.form_first_name,
lastName: fields.form_last_name,
email: fields.form_email,
password: fields.form_password,
skills: skillsArr,
iWantToMake: artsArr,
street: fields.form_address,
city: fields.form_city,
provinceState: fields.form_province,
gender: fields.form_gender,
imLookingFor: ['Acting', 'Drawing', 'Music', 'Writing', 'Programming', 'Videography']
},
headers: {
'Access-Control-Allow-Origin': '*'
}
});
return request.then(response => {
console.log('axios call ran! Below is response....');
console.log(response);
dispatch({
type: 'REGISTER',
payload: {
myId: response.data,
fields: fields,
skills: skillsArr,
iWantToMake: artsArr
}
})
},
err => {
if (err) throw err;
})
}
};
Everything works fine right up until I make the Axios to the /register route. The files pertaining to this issue are here and here.
UPDATE: I went into my app.js file to change the Cors configuration.I commented out app.use(cors()); and app.options('*', cors()); and replaced it with this.
/// x-auth is a custom-header in my server-side code
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,x-auth,Accept,content-type,application/json');
next();
});
/// After this line, I declare my routes.
However, now I am getting this error Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.