Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS with Angular and Express - Working in Postman but not in the browser

Tags:

I'm having a CORS related issue (I think), When I send a login post request from postman it succeeds. When I try logging in with my angular 2 front end app the request status seems to be 200, but nothing happens, and in the console I get this strange message that my localhost:4200 is not allowed, How can I fix this?

Angular http method

 authenticateUser(user){
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    return this.http.post('http://localhost:3000/api/authenticate', user, {headers: headers})
    .map(res => res.json());
  }

Error msg from console. enter image description here

Postman request (success) enter image description here

In case it would be a express related problem here is my express code:

const express = require("express")
const bodyParser = require("body-parser")
const logger = require('morgan')
const api = require("./api/api")
const path = require('path')
const secret = require('./models/secrets')
const expressJWT = require('express-jwt')
const cors = require('cors');

const app = express()

app.set("json spaces", 2)
app.use(logger("dev"))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

app.use(expressJWT({secret: secret}).unless({path : ['/api/authenticate', '/api/register']}))

app.use("/api/", api)

app.use(function (req, res, next) {
  var err = new Error('Not Found')
  err.status = 404
  next(err)
})

app.use(function (err, req, res, next) {
  console.error(err.status)
  res.status(err.status || 500)
  res.json({ msg: err.message, status: err.status })
})

// Body Parser middleware
app.use(bodyParser.json());

// CORS middleware
app.use(cors());

// set static folder
app.use(express.static(path.join(__dirname, 'public')));
//Call this to initialize mongoose
function initMongoose(dbConnection) {
  require("./db/mongooseConnect")(dbConnection)
}

app.initMongoose = initMongoose

module.exports = app

And the route for /authenticate looks like this

// Authenticate
router.post('/authenticate', (req, res, next) => {
    const username = req.body.username;
    const password = req.body.password;

    User.getUserByUsername(username, (err, user) => {
        if (err) throw err;
        if (!user) {
            return res.json({ success: false, msg: 'User not found' });
        }

        User.comparePassword(password, user.password, (err, isMatch) => {
            if (err) throw err;
            if (isMatch) {
                const token = jwt.sign({data: user}, secret, {
                    expiresIn: 604800 // 1 week
                });

                res.json({
                    success: true,
                    token: 'Bearer ' + token,
                    user: {
                        id: user._id,
                        name: user.name,
                        username: user.username,
                        email: user.email
                    }
                });
            } else {
                return res.json({ success: false, msg: 'Wrong password' });
            }
        });
    });
});
like image 428
Rasmus Puls Avatar asked Dec 16 '17 15:12

Rasmus Puls


People also ask

Why does CORS work on Postman but not browser?

The CORS standard is a client-side standard, implemented in the browser. So it is the browser which prevent the call from completing and generates the error message - not the server. Postman does not implement the CORS restrictions, which is why you don't see the same error when making the same call from Postman.

Does CORS apply to Postman?

Postman simply doesn't care about CORS headers. So CORS is just a browser concept and not a strong security mechanism. It allows you to restrict which other web apps may use your backend resources but that's all.

Does Postman throw CORS error?

Note: The CORS error generally happens due to browser limitations regarding resources shared between different internet domains. Please refer to this blog post for more information about CORS and how the Postman Desktop Agent works.


1 Answers

The request that's being made is called a preflight request - You can see this in the error message, where it states that the response to the preflight request doesn't pass the access control check. Preflight requests are made by the browser, as CORS is a browser security restriction only - This is why it works in Postman, which is, of course, not a browser.

The docs for the CORS middleware you are using state the following:

To enable pre-flighting, you must add a new OPTIONS handler for the route you want to support:

In your case, as you've set up CORS handling to work for all origins, etc, you can use the following (again, from the docs):

app.options('*', cors()) // include before other routes

As the comment states, you'll need to move this up towards the top of your .js file so that it is processed first.

It is also advisable to specifically set the allowed origins, routes, etc, in order to lock down which origins are able to access which endpoints. You can read more about that using your favourite search engine.

like image 192
Kirk Larkin Avatar answered Sep 22 '22 12:09

Kirk Larkin