How to handle Facebook login using NestJS

Baptiste Arnaud
3 min readOct 4, 2019

NestJS is a great Node.js framework and its documentation explains server concepts quite well. They also have an Authentication section which you can follow if you want to implement a basic username/password login strategy.

But it has been a little bit difficult for me to understand how to adapt to other sign up providers such as Facebook. And I couldn’t find explicit tutorials so… Here I am!

NestJS is using Passport.js to handle authentication which is the most popular authentication library for Node.js

Who is this for?

This tutorial is made for people who have a front application that asks for the user to log into Facebook. The login workflow is handled front-end side and the user get an access_token specific to his account. We’ll use this access token in our back end in order to:

  1. Check if the token is correct
  2. Get Facebook profile information
  3. Create the user if he doesn’t exist

So we want a GET /auth/Facebook endpoint in our back end that sends us back “OK I created a new user”

Authentication Requirements

First, you’ll need to download the following packages:

$ npm install --save @nestjs/passport passport passport-facebook-token
$ npm install --save-dev @types/passport-facebook-token
  • nestjs/passport : NestJS module that wraps the passport library
  • passport : Passport.js library because the NestJS module will have to access it
  • passport-Facebook-token : The Passport.js Facebook strategy using access_token. There is also a passport-Facebook package that handles authentication workflow with callback URL and stuff. This isn’t what we want.

Now, let’s generate the components we’ll need:

$ nest g module auth
$ nest g controller auth
$ touch auth/facebook.strategy.ts

Configure the Facebook strategy

We need to give passport.js a specific FacebookTokenStrategy instance.

facebook.strategy.ts:

@Injectable()
export class FacebookStrategy {
constructor(
private readonly userService: UserService,
) {
this.init();
}
init() {
use(
new FacebookTokenStrategy(
{
clientID: <YOUR_APP_CLIENT_ID>,
clientSecret: <YOUR_APP_CLIENT_SECRET>,
fbGraphVersion: 'v3.0',
},
async (
accessToken: string,
refreshToken: string,
profile: any,
done: any,
) => {
const user = await this.userService.findOrCreate(
profile,
);
return done(null, user);
},
),
);
}
}

passport object expects that we call its use() method. This is what this class basically does. Also, here I assume you already have a User service with a function that either finds or creates a user.

I can give you a peek of what mine does:

async findOrCreate(profile): Promise<User> {
const user = await this.userModel
.findOne({ 'facebook.id': profile.id })
.exec();
if (user) {
return user;
}
const createdUser = new this.userModel({
email: profile.emails[0].value,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
Facebook: {
id: profile.id,
avatar: profile.photos[0].value,
},
});
return createdUser.save();
}

Either way, it will return a user object.

Implement the controller endpoint

auth.controller.ts:

@Controller('auth')
export class AuthController {
@UseGuards(AuthGuard('facebook-token'))
@Get('facebook')
async getTokenAfterFacebookSignIn(@Req() req) {
console.log(req.user);
}
}

This configures the /auth/Facebook endpoint of our server. It just says it exists. The request, after going through the facebook-token middleware, contains the user.

Putting in all together

auth.module.ts:

@Module({
imports: [UserModule],
providers: [FacebookStrategy],
controllers: [AuthController],
})
export class AuthModule {}

Now if we call the route with a session_token as a query param:

GET auth/Facebook?session_token=<SESSION_TOKEN>

It should persist the newly created user in your database. Then, you can implement JWT functionality to handle user sessions.

Let me know if you have any questions :)

Source code : https://github.com/baptisteArnaud/facebook-login-nestjs-example

Thanks for reading. If you enjoyed this tutorial, feel free to hit that clap button 👏 to help others find it.

Say Hi on Twitter!

--

--