Restrict login to specific domain using Node Passport with Google Auth

javascript, node.js, oauth, oauth-2.0, passport.js

Solution

Here's an example:

// first make sure you have access to the proper scope on your login route
app.get("/login", passport.authenticate("google", {
    scope: ["profile", "email"]
}));

// set up your Google OAuth strategy elsewhere...
passport.use(new GoogleStrategy({
    clientID: "something",
    clientSecret: "something",
    callbackURL: "/something"
}, function(token, refreshToken, profile, done){
    if(profile._json.hd === "yourdomain.com"){
        // find or create user in database, etc
        User.find({ id: profile.id }).done(done);
    }else{
        // fail        
        done(new Error("Invalid host domain"));
    }
});

And for good measure here's a full variable dump of what the "profile" variable looks like.

{ 
    provider: 'google',
    id: '12345678987654321',
    displayName: 'Don Draper',
    name: { familyName: 'Whitman', givenName: 'Richard' },
    emails: [ { value: 'don@scdp.com' } ],
    _raw: 'a bunch of stringified json',
    _json: { 
        id: '123456789',
        email: 'something@something.com',
        verified_email: true,
        name: 'Don Draper',
        given_name: 'Don',
        family_name: 'Draper',
        link: 'https://plus.google.com/123456789',
        picture: 'https://lh3.googleusercontent.com/XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/123456789/photo.jpg',
        gender: 'male',
        locale: 'en',
        hd: 'yourdomain.com' 
    } 
}

Here are some detailed tutorials that should answer your question about the theory behind all of this. You'll want some combination of the two.

- Local authentication and basic setup

- Google authentication

Problem

I am implementing Google Auth on an internal service at work. It is a JS client heavy application with a Node backend. I am choosing to use the Node module Passport.js with the passport-google-oauth strategy. I have successfully got it working but one thing is still confusing me. I want to ensure my application allows only company employees to login. I understand that you can restrict the login by domain using a parameter called "hd", according to the official documentation. Firstly, where do you send that parameter in the context of Passport.js? I just don't understand where in the code that is put. If it helps, I have been mostly following the example passport-google-oauth provides. Secondly, in theory how does this all work? Is it on the Google side, where they reject anyone trying to access the app with a domain outside of our company. Or is it on my side, that I need to check what domain the user is logging in from?

Original source