Saturday 26 September 2020

How to manage OAuth in Node-Express / Vue web app?

I'm a bit confused as to how to manage the OAuth flow in my application. I can make it work, but I'm unsure of the best practices, and would like to find some good articles/tutorials/documentation on that topic.

My app is structured as follows:

  • A Vue front-end that makes HTTP requests via axios to a back-end
  • A Node.js / Express back-end that uses Passport.js allowing local, Google and Facebook strategies

Passport is configured like this:

passport.use(
    new GoogleStrategy(
        {
            clientID: process.env.GOOGLE_CLIENT_ID,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET,
            callbackURL: '/api/login/google/callback'
        },
        async (accesToken, refreshToken, profile, done) => {
            try {
                let user = await User.findOne({ googleId: profile.id });
                if (user) {
                    if (
                        user.email != profile.emails[0].value ||
                        user.pic != profile.photos[0].value
                    ) {
                        user.email = profile.emails[0].value;
                        user.pic = profile.photos[0].value;
                        user.save();
                    }
                    return done(null, user);
                } else {
                    user = await User.findOne({
                        email: profile.emails[0].value
                    });
                    if (user) done(new UserError('existing-user'));
                    const newUser = await new User({
                        googleId: profile.id,
                        email: profile.emails[0].value,
                        name: profile.displayName,
                        pic: profile.photos[0].value
                    }).save();
                    return done(null, newUser);
                }
            } catch (e) {
                return done(e);
            }
        }
    )
);

And these are the auth methods in my login component:

methods: {
        async login() {
            await authClient.login(this.credentials);
        },
        async googleLogin() {
            window.open('/api/login/google', 'loginPopup', 'menubar=on');
            // window.location.href = '/api/login/google';
        },
        async facebookLogin() {
            window.location.href = '/api/login/facebook';
        },
        async requestResetToken() {
            await userClient.requestResetToken({
                email: this.emailReset
            });
        }
    }

My confusion comes from the fact that in order to start the OAuth flow, I need to actually leave my Vue app by linking to /api/login/google, which redirects to the Google OAuth page. Once the OAuth is completed, I'm not redirected to my Vue app but to the Node back-end (via the callback setup in Passport config).

One way to make it work is to open that OAuth flow in a popup window, track through my Vue app the content of that window, and as soon as I get the user object I close the window and login the user in the front-end. But somehow that doesn't seem quite right.

Should I find a way to actually have that callback function redirect to my Vue app and get the Vue app to deal with it? Any good resource online with examples to understand that clearly?

Thanks for your help!



from How to manage OAuth in Node-Express / Vue web app?

No comments:

Post a Comment