NestJS is a relatively new framework that has been growing in popularity for many good reasons. It has full support for TypeScript and it combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming) to enable developers build scalable and coherent server-side applications.
Requirements
Below is a list of software required to follow along as we setup facebook login with NestJS:
- Facebook account
- NodeJS
- Yarn
Project Setup
NestJS comes with a convenient CLI that can be used to scaffold a new NestJS project.
Install the CLI globally using the following command:
npm i -g @nestjs/cli
Scaffold a new project using the command:
nest new <project-name>
For this project,you use a descriptive name as shown below:
nest new nest-facebook-auth
The CLI will prompt you to choose a package manager between yarn
or npm
.you be using yarn for this project.
After the setup is complete, you can open the project in your favorite editor and you should have a folder structure like this:
Dependencies
To implement facebook login, we need to add a few dependencies to the project:
- dotenv
- passport
- passport-facebook
- @nestjs/passport
The dotenv package will be used to load environment variables and passport will be used to manage authentication. Add the packages using the following command:
yarn add dotenv @nestjs/passport passport passport-facebook
To add static typing for passport-facebook
, we need to install one more dependency:
yarn add @types/passport-facebook
Create Facebook App
Visit https://developers.facebook.com to create a Facebook app. If you don't have a developer account, click on Get Started at the top right of the screen. After setting up your account, you should see the dialog below:
Click on Create First App and fill in the details for your desired app name and contact info. You can give yours a different name than the one below:
Once your app is created, you should see a dashboard that looks similar to the one below. Click on Set Up Facebook Login.
Select Web and fill in your website's URL (without any paths). Since this is just for testing, our request will be coming from localhost, so enter http://localhost:3000 and click Save.
Just like this:
Get and Save Credentials
To get your app credentials, click on Settings on the left side menu and click on Basic. Copy your App ID and App Secret.
Create a new .env
file in the NestJs project's root directory. Store your app credentials as environment variables for security reasons:
APP_ID=<your_app_id>
APP_SECRET=<your_app_secret>
NOTE: make sure you add .env
to your .gitignore
to prevent it from being added to git. At the bottom of your .gitignore
, add the following:
# Environment
.env
Implement Facebook Login
To import the saved environment variables, add the following code to the top (and below other imports) of your main.ts
file in the src
folder
import * as dotenv from "dotenv";
dotenv.config();
Since we're using passport to implement Facebook Login, we need to create a passport strategy. To do that, create a facebook.strategy.ts
file in the src
folder and add the code below:
import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { Profile, Strategy } from "passport-facebook";
@Injectable()
export class FacebookStrategy extends PassportStrategy(Strategy, "facebook") {
constructor() {
super({
clientID: process.env.APP_ID,
clientSecret: process.env.APP_SECRET,
callbackURL: "http://localhost:3000/facebook/redirect",
scope: "email",
profileFields: ["emails", "name"],
});
}
async validate(
accessToken: string,
refreshToken: string,
profile: Profile,
done: (err: any, user: any, info?: any) => void
): Promise<any> {
const { name, emails } = profile;
const user = {
email: emails[0].value,
firstName: name.givenName,
lastName: name.familyName,
};
const payload = {
user,
accessToken,
};
done(null, payload);
}
}
The first argument to PassportStrategy
is Strategy
which comes from passport-facebook
. The second argument tells passport the name of the strategy which in our case is facebook
.
To be able to use the newly created strategy, we need to include it as a provider in our app module. Open app.module.ts
in the src
folder and replace it with:
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { FacebookStrategy } from "./facebook.strategy";
@Module({
imports: [],
controllers: [AppController],
providers: [AppService, FacebookStrategy],
})
export class AppModule {}
Add login route
Finally, we need to add the API endpoint/route for facebook login. In NestJS, routes are handled by controllers.you implement facebook login in app.controller.ts
as follows:
import { Controller, Get, UseGuards, HttpStatus, Req } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { Request } from "express";
import { AppService } from "./app.service";
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
@Get("/facebook")
@UseGuards(AuthGuard("facebook"))
async facebookLogin(): Promise<any> {
return HttpStatus.OK;
}
@Get("/facebook/redirect")
@UseGuards(AuthGuard("facebook"))
async facebookLoginRedirect(@Req() req: Request): Promise<any> {
return {
statusCode: HttpStatus.OK,
data: req.user,
};
}
}
The last two routes are responsible for the entire login flow. The first one initiates facebook login. The second route is where facebook will redirect the user to after a successful login.
Test App
Run in development mode using the following command:
yarn start:dev
Navigate to the facebook endpoint in your browser: http://localhost:3000/facebook. You'll be prompted to log in with facebook as shown below:
After a successful login, you'll be redirected to http://localhost:3000/facebook/redirect and you'll get the response as defined in the facebookLoginRedirect
controller. See an example response below:
🎉🎉🎉, you have successfully implemented facebook login. The code for this project can be found on GitHub: https://github.com/elishaking/nestjs-facebook-login
If you encountered any issues, feel free to leave a comment below or reach me @ElishaChibueze.
I love making these articles, so please I'd love to know your suggestion on topics you'll like me to explore.
❤️ the article ?****?**?** I loved making it.
Top comments (17)
when i git the localhost:3000/auth/facebook in the browser i do get a login screen by facebook. After login i do get an error from facebook:
I have a similar issue, but I solve it by adding an email scope on facebook app
I hope this one can help you guys
hey did you find the solution for this? I've been getting the exact same error, even though I have tried everything, I'm still stuck with this
you are my hero! Thank you for this article, it was very very useful...
Thank you.
How protect other routes ?
@Get("/products")
@UseGuards(AuthGuard("facebook")) ?
if i have also Google guard it will be like:
@Get("/products")
@UseGuards(AuthGuard("facebook"))
@UseGuards(AuthGuard("google"))
I got an error, apparently it does not return the name and email, some help
dev-to-uploads.s3.amazonaws.com/i/...
I think this shows up if the email of user is not verified.
Amazing article! One thing to note is if your local front-end runs on a separate port you will have CORS errors with Facebook. To resolve, the front-end MUST use the same port as your server (localhost:3000 in this case) so you'll need to proxy your request made on front-end to get rid of the errors.
Wonderful article Sir....
Thank King Elisha, hope you can create a lot of post like this <3
then how to implement logout ??
Thank for your sharing, may i ask how can i implement facebook login with graphql project? is it possible without @Req annotation?
Hello @linhtran28 , did you found a way to implemenent this?
Any news on this?
To anyone getting the "Sorry, something went wrong". Go to facebook app and allow "email" as a scope.