I'm using googleapis package from node to get refresh token and access token from auth code passed from front-end but every time I get the following error.
{
error: 'redirect_uri_mismatch',
error_description: 'Bad Request'
}
I know this error comes up when we mismatch URL passed as a callback URL in the console.
https://console.cloud.google.com/apis/credentials
but I've already set up the correct URL in the console. still not sure what's the problem with the code.
Using /auth to pass the token from front-end to node-server.
const {
google
} = require("googleapis");
const OAuth2 = google.auth.OAuth2;
var bodyParser = require('body-parser')
const express = require('express');
const app = express();
app.use(bodyParser.json());
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use('/tokenCallback', (req, res) => {
console.log(req);
res.send('An alligator approaches!');
});
app.post('/auth', (req, res) => {
runProcess(req.body.auth);
res.send('An alligator approaches!');
});
app.listen(4300);
function runProcess(code) {
const oauth2client = new OAuth2(
"210347756664-xxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
"57ZU6JuQ7oQ7SvSFtki5atxx", // Client Secret
"http://localhost:4300/tokenCallback",
);
oauth2client.getToken(code, (e) => {
console.log(e);
});
oauth2client.on('tokens', (tokens) => {
if (tokens.refresh_token) {
console.log("refresh token", tokens);
}
});
}
Any help from anyone will be greatly appreciated.
The redirect_uri_mismatch means that your application isn't sending a valid redirect URI, or it is not registered on Google Cloud Console.
Make sure that in Console -> APIs & Services -> Credentials -> OAuth client IDs -> (your key) you have added the http://localhost:4300/tokenCallback URI.
Related
Tried everything I could find on here in regards to setting up cors for my node server. Tried aliasing my localhost and that doesn't seem to work either. Also tried using the CORS unblock extension.
error: localhost/:1 Access to fetch at
'http://localhost:8080/api/login' from origin 'http://localhost:3000'
has been blocked by CORS policy: Response to preflight request doesn't
pass access control check: It does not have HTTP ok status.
:8080/api/login:1 Failed to load resource: net::ERR_FAILED
im trying to use magic link authentication in my react app. I got this POST request being made to my node server
const res = await fetch(`http://localhost:8080/api/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + didToken,
},
});
my server code is
const express = require("express");
const cors = require("cors");
const { Magic } = require('#magic-sdk/admin');
require('dotenv').config();
const app = express()
const magic = new Magic(process.env.MAGIC_SECRET_KEY);
app.use("*", (req, res) => res.status(404).json({ error: "not found" }));
// Allow requests from client-side
app.use(cors({origin: process.env.CLIENT_URL}));
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.sendStatus(200);
next();
});
app.post('api/login', async (req, res) => {
console.log("login fired")
try {
const didToken = req.headers.authorization.substr(7);
await magic.token.validate(didToken);
res.status(200).json({ authenticated: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
module.exports = app
app.use(cors({origin: process.env.CLIENT_URL}));
I'd be curious what this URL is. If you want an open CORS policy you don't need to set anything any there.
Put a "/" in front of this route
app.post('/api/login', async (req, res) => {
I was able to reproduce your problem locally and this server setup worked for me to fix it.
const express = require("express");
const cors = require("cors");
const port = 8080;
const app = express();
app.use(cors());
app.post("/api/login", async (req, res) => {
console.log("login fired");
try {
res.status(200).json({ authenticated: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
module.exports = app;
I am trying to connect my front end to my back end, and I am using express server with node and react.
this is my fetch request fom front end: server runs on port 5000
const response = await axios.post("http://localhost:5000/send-email", {
to_email: data.data.email,
url: data.data.url,
});
console.log(response);
this resutls in:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/send-email. (Reason: CORS request did not succeed). Status code: (null).
I have in my back end:
app.post("/send-email", async (req, res) => {
try {
const { to_email, url } = req.body;
console.log(to_email, url);
await sendMail()
.then((result) => console.log("Email sent...", result))
.catch((error) => console.log(error.message));
res.send({ express: "YOUR EXPRESS BACKEND IS CONNECTED TO REACT" });
} catch (error) {
console.log(error);
res.status(500).json({ message: error });
}
});
I am also using core and also something like this:
// app.use(function (req, res, next) {
// // res.header("Access-Control-Allow-Origin", "*");
// res.header("Access-Control-Allow-Origin", "http://localhost:3000");
// res.header(
// "Access-Control-Allow-Headers",
// "Origin, X-Requested-With, Content-Type, Accept"
// );
// res.header("Access-Control-Allow-Methods", "POST, OPTIONS");
// res.header("Access-Control-Allow-Credentials", true);
// next();
// });
but regards less I keep getting this error and I am not sure how to get rid of it. I have seen several solutions they are either old, and I have tried some of them, they dont work at all.
Install cors using (npm install cors).
In your backend code file, add
var cors = require('cors') <br />
app.use(cors())
Alternatively, follow instructions given at https://www.npmjs.com/package/cors.
I fixed it like the following:
in my front end, I have
const response = await axios.post("http://localhost:8000/signup", {
newUserNameEmail,
url,
});
console.log("response--> ", response.data);
and in my backend server:
const PORT = 8000;
const express = require("express");
const cors = require("cors");
const nodemailer = require("nodemailer");
const { google } = require("googleapis");
const app = express();
app.use(cors());
app.use(express.json());
//sign up
app.post("/signup", async (req, res) => {
try {
const { newUserNameEmail, url } = req.body;
console.log(newUserNameEmail, url);
await sendMail(newUserNameEmail, url)
.then((result) => console.log("Email sent...", result))
.catch((error) => console.log(error.message));
res.status(200).json({ newUserNameEmail, url });
} catch (error) {
console.log(error);
res.status(500).json({ message: error });
}
});
So for some reason, this works and doesn't generate the error I was getting before. I can now communicate with front end and backend and send data, and email.
But I have no idea why this worked and the other one didnt. I also didnt change my package.json
Add proxy in your package.json file to the port of your backend api
"proxy": "http://localhost:8000"
then change your url in the request to port 3000 or wherever your frontend is
const response = await axios.post("http://localhost:3000/send-email", {
to_email: data.data.email,
url: data.data.url,
});
console.log(response);
proxy only works in local, however your app and api usually share the same main domain so this cors error will not appear in production..
I've deploy my node.js server into Azure by new AppService linux.
It correctly start, because if I call one http get it return the correct data.
But when I try to call the post url that make a:
server.post('/api/messages', (req, res) => {
adapter.processActivity(req, res, async (context) => {
// Process bot activity
await botActivityHandler.run(context).catch((e) => { console.dir(e) });
});)}
it return
UnhandledPromiseRejectionWarning: Error: BotFrameworkAdapter.processActivity(): 400 ERROR Error: BotFrameworkAdapter.parseRequest(): missing activity type.
I've already check if the bot have the correct appId and pwd, and it's are ok.
This is my index.js file:
// index.js is used to setup and configure your bot
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
const { BotFrameworkAdapter } = require('botbuilder');
// Import bot definitions
const { BotActivityHandler } = require('./botActivityHandler');
// Read botFilePath and botFileSecret from .env file.
const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });
// Create adapter.
const adapter = new BotFrameworkAdapter({
appId: "XXXXXXXXXXXXXXXXXXXXXX",
appPassword: "XXXXXXXXXXXXXXXXXXXXXXX"
});
adapter.onTurnError = async (context, error) => {
console.error(`unhandled error: ${error}`);
console.dir(`unhandled error: ${error}`);
await context.sendTraceActivity(
'OnTurnError Trace',
`${error}`,
'https://www.botframework.com/schemas/error',
'TurnError'
);
await context.sendActivity('The bot encountered an error or bug.');
await context.sendActivity('To continue to run this bot, please fix the bot source code.');
};
// Create bot handlers
const botActivityHandler = new BotActivityHandler();
// Create HTTP server.
const server = express();
server.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
next();
});
server.use(bodyParser.json()); // to support JSON-encoded bodies
server.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
const port = process.env.port || process.env.PORT || 3978;
server.listen(port, () =>
console.log(`service listening at https://localhost:${port}`)
);
// Listen for incoming requests.
server.post('/api/messages', (req, res) => {
console.dir(adapter);
adapter.processActivity(req, res, async (context) => {
// Process bot activity
console.dir(context);
await botActivityHandler.run(context).catch((e) => { console.dir(e) });
});
});
server.post('/api/create/uat', (req, res) => {
console.dir(req.params);
});
server.get('/api/read/uat', (req, res) => {
console.dir(req.params);
});
server.post('/api/prova/post', (req, res) => {
console.dir(req.params);
});
Locally with ngrok it run ok, Can anyone help me?
Thanks.
As suggested by #Leonardo, Local and distributed app can be deleted and setup a new app by changing the URL.
I have a REST Api, and all endpoints must send a response when the user has an authentication token (I use the jwt token).
everything works fine when I test my code using postman, but from front not working(session closes after OPTION request, and on the request header bearer token not set).
Authentication Middleware
module.exports = function(req, res, next) {
const authorization = req.headers['authorization'];
console.log(authorization);
const token = authorization
? authorization.replace('Bearer ', '')
: null;
if (!token)
return res.status(403).send({ auth: false, message: 'No token provided.' });
jwt.verify(token, config.secret, function(err, decoded) {
if (err)
return res.status(500).send({ auth: false, message: 'Failed to authenticate token.' });
req.userId = decoded.id;
next();
});
}
route
const Router = require('express').Router;
//Authentication Middleware
const requireAuthentication = require('../middlewares/').Auth()
module.exports = () => {
let router = new Router();
router.use(requireAuthentication);
router.use('/accounts', require('./account')());
router.use('/projects', require('./projects')());
return router;
};
with authentication
https://i.stack.imgur.com/cAFw5.png
without authentication
https://i.stack.imgur.com/VUuuv.png
The reason was in access headers
I add middleware in bootstrap file.
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if ('OPTIONS' === req.method) {
res.send(200);
}
else {
next();
}
});
Try to use Express Cors: https://github.com/expressjs/cors
Simple Usage (Enable All CORS Requests)
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin. A web application makes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.
Read more about CORS here https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I am working on a university/student project with full MEAN stack. We have NodeJS, ExpressJS backend and Angular2 frontend. Backend runs on localhost:8080 and frontend runs on localhost:4200
This is how my backend looks like
var express = require('express'),
...
var app = express();
...
// needed because of cross origin resource sharing during development
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
var port = process.env.PORT || 8080;
var loginController = require('./controllers/loginController')(Person);
var personController = require('./controllers/personController')(Person, Transaction);
var transactionController = require('./controllers/transactionController')(Person, Transaction);
var apiRouter = express.Router();
apiRouter.post('/login', loginController.authenticate);
/**
* Middleware that handles authorization of particular routes.
* Every request which starts with `/api/persons` or `/api/transactions`, will be intercepted and validated against JWT.
*/
apiRouter.use(function (req, res, next) {
// JWT gets validated
});
apiRouter.get('/persons', personController.fetchAllPersons);
apiRouter.get('/persons/:personId', personController.fetchPersonById);
apiRouter.get('/persons/:personId/transactions', personController.fetchTransactionsByPersonId);
apiRouter.post('/transactions', transactionController.addNewTransaction);
app.use('/api', apiRouter);
app.listen(port, function () {
console.log('Listening on port: ' + port);
});
I read that the routes of the express router get executed sequentially, so the order of middleware inclusion is important. Therefore I set it after /login route since it should not be available without JWT authorization.
When I start the application and execute requests with postman everything works as it is supposed, but when I try to login from the frontend middleware function gets executed also for login route but it shouldn't, right?
Is is maybe because of they are running on different ports or could it be an issue caused by cross origin, I really have no idea?
Did anyone already face similar issue and could you please explain this behavior?
Thx
EDIT 1:
As robertklep has mentioned below, it might depend on the loginController implementation and the way how we handle login in frontend, here are the code snippets
jwt = require('jsonwebtoken');
var loginController = function (Person) {
var authenticate = function (req, res) {
req.person = req.body;
var searchPerson = { username: req.person.username }
Person.findOne(searchPerson, function (err, person) {
if (err) throw err;
if (!person) {
return res.status(401).send({ message: 'Wrong username/password' });
}
person.comparePasswords(req.person.password, function (err, isMatch) {
if (err) throw err;
if (!isMatch) {
return res.status(401).send({ message: 'Wrong username/password' });
}
var token = jwt.sign(person._id, /* XXX SECRET XXX */);
res.status(200).json({
token: token,
person: person
});
});
});
};
return {
authenticate: authenticate
};
};
module.exports = loginController;
Frontend:
...
export class LoginComponent implements OnInit {
/**
* validates input data and on successful validation,
* tries to login the user with her/his credentials
*/
public login(): void {
// validation logic should consider all fields, no matter if the user has entered any data
this.validate(false);
// no validation error, continue with login process
if(!this.errorMessage){
const form = this.loginForm;
var credentials = {
name: form.get('name').value,
password: form.get('password').value
};
this.loginService.login(credentials.name,credentials.password)
.subscribe(
name => this.router.navigate(['welcome']),
error => this.errorMessage = error);
}
}
}
...
export class LoginService {
...
public login(userName: string, password: string): Observable<string> {
var person = {
'username': userName,
'password': password
};
return this.http.post('http://localhost:8080/api/login',person)
.map(this.extractToken)
.catch(this.handleError);
}
}
EDIT 2:
As asked, I am posting my middleware, so this is how it looks like
apiRouter.use(function(req, res, next) {
// first, check if a token is provided
var token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
// token gets validated by jwt lib
jwt.verify(token, /* SECRET */, function (err, decoded) {
if (err) {
// token invalid, respond with unauthorized
res.status(401).json({
message: 'Failed to authenticate token.'
});
} else {
// token is valid, continue to the particular request handler
req.decoded = decoded;
next();
}
});
} else {
// token was not provided, respond with forbidden
res.status(403).json({
message: 'No token provided.'
});
}
});
Like I said, when I use postman client and execute login request, everything works as expected (Middleware doesn't execute for the login request) but when I start our frontend app and do the same, middleware function gets executed.