user10325073
user10325073

Reputation:

cors issue with passport.js google oauth strategy

I have a setup as such:

-backend
    -model
        --User.js
    -routes
        --auth.js
    -database
        --connection.js
    -passport
        --passport.js
    --server.js
-client
     -react folders / files
     ...

In my server.js:

const express = require("express");
const cookieSession = require("cookie-session");
const passport = require("passport");

const { authRoutes } = require("./routes/auth");

require("./model/User");
require("./services/passport");
require("./services/mongoConnect");

const app = express();

app.use(
    cookieSession({
        maxAge: "30 * 24 * 60 * 60 * 1000",
        keys: "MY-KEY",
    })
);
app.use(
    cors({
        origin: true,
        methods: "GET, POST, PATCH, DELETE, PUT",
        allowedHeaders: "Content-Type, Authorization",
    })
);

app.use(passport.initialize());
app.use(passport.session());

const PORT = process.env.PORT || 5000;

app.use("/", authRoutes);

app.listen(PORT);

Inside my auth.js file inside my router

const passport = require("passport");
const router = require("express").Router();

router.get(
    "/auth/google",
    passport.authenticate("google", {
        scope: ["profile", "email"],
    })
);

router.get("/auth/google/callback", passport.authenticate("google"));

router.get("/api/logout", (req, res) => {
    req.logout();
    res.send(req.user);
});

router.get("/api/current_user", (req, res) => {
    res.send(req.user);
});

module.exports = {
    authRoutes: router,
};

Inside passport.js file I have

const passport = require("passport");
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const mongoose = require("mongoose");

const User = mongoose.model("users");

passport.use(
    new GoogleStrategy(
        {
            clientID: "MY-ID",
            clientSecret: "MY-SECRET",
            callbackURL: "/auth/google/callback",
            proxy: true,
        },
        (accessToken, refreshToken, profile, done) => {
            User.findOne({ googleId: profile.id }).then((existingUser) => {
                if (existingUser) {
                    done(null, existingUser);
                } else {
                    new User({
                        googleId: profile.id,
                    })
                        .save()
                        .then((newUser) => {
                            done(null, newUser);
                        });
                }
            });
        }
    )
);

passport.serializeUser((user, done) => {
    done(null, user._id);
});

passport.deserializeUser((id, done) => {
    User.findById(id).then((user) => {
        done(null, user);
    });
});

My frontend consists of a button that hits my auth/google route. However it logs a cors issue error in the console.

(redirected from 'http://localhost:3000/auth/google') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Doea anyone know how i can solve this? In mu google console I have the redirect url setup as 'http://localhost:3000/auth/google/callback'

Upvotes: 5

Views: 5149

Answers (4)

Athira V Ajit
Athira V Ajit

Reputation: 336

The problem is even though you have used cors package you have not added the following Access-Control-Allow-Origin option in cors. Try this :

app.use(
cors({
    origin: '*',
    methods: "GET, POST, PATCH, DELETE, PUT",
    allowedHeaders: "Content-Type, Authorization",
   })
);

Or as yash has mentioned simply use:

app.use(cors())

For more reference check the official npm cors documentation

Upvotes: 0

Nazrul Chowdhury
Nazrul Chowdhury

Reputation: 244

First you need to update the cors origin with '*' or your client specific whitelisted url. But that alone is not going to solve the problem. your button should load the auth url on the browser instead of making an api call to the auth/google route. So you can make the button a href link instead.

Upvotes: 2

andsilver
andsilver

Reputation: 5972

Maybe you didn't configure cors policy in your backend.

The most simple way is to install cors package if you use Express.

npm install cors

And use it as a middleware of your express app.

var app = express()
var cors = require('cors');
...
app.use(cors());

Upvotes: 0

Matus Dubrava
Matus Dubrava

Reputation: 14462

You have misconfigured CORS on your backend.

First, you are using wrong syntax when it comes to methods - there should be no spaces when you are listing them (I don't know how they are parsing the string but you should probably stick with the documentation - according to documentation, you can specify methods either as a string: 'GET,PUT,POST' or a list: ['GET', 'PUT', 'POST'].

Second, you are missing OPTIONS HTTP method in the methods which is used by browsers in preflight request to test server's CORS configuration.

Third, are you sure about the specified headers?

The easiest option is to drop the CORS options configuration completely if you are not sure what you are doing and apply the cors globally before every request.

app.use(cors());

Or to only specific path where you want to allow CORS.

app.get("/somepath", cors(), (req, res) => {...

Upvotes: 0

Related Questions