How to handle Facebook login using NestJS

Baptiste Arnaud
Oct 4 · 3 min read

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!

Baptiste Arnaud

Written by

Maker | Full Stack Developer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade