nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript 🚀
https://nestjs.com
MIT License
67.75k stars 7.63k forks source link

A working example of Facebook login? #1247

Closed oipewr closed 6 years ago

oipewr commented 6 years ago

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

I saw one or two samples, but those are way too complicated.

Expected behavior

A documentation and a sample of social logins with Passport and JWT.

Environment


Nest version: 5.1


For Tooling issues:
- Node version: 10.13  
- Platform:  Linux 

Others:

Root-Control commented 6 years ago

First of all, you need this: "passport-facebook-token": "^3.3.0", 1.- Create the auth module 2.- Create config file in /auth/interfaces/facebook-config.interface.ts

Copy the following code

export interface IFacebookConfig {
  readonly login_dialog_uri: string;
  readonly access_token_uri: string;
  readonly client_id: string;
  readonly client_secret: string;
  readonly oauth_redirect_uri: string;
  readonly state: string;
}

3.- Implement interface with data creating config file in /auth/config/facebook-config.ts

import { IFacebookConfig } from '../interfaces/facebook-config.interface';

export const facebookConfig: IFacebookConfig = {
  login_dialog_uri: 'https://www.facebook.com/v2.12/dialog/oauth',
  access_token_uri: 'https://graph.facebook.com/v2.12/oauth/access_token',
  client_id: 'YOUR CLIENT ID HERE',
  client_secret: 'YOUR CLIENT SECRET HERE',
  oauth_redirect_uri: 'YOUR REDIRECT URI',
  state: '{fbstate}'
};

4.- Create the facebook passport configuration /auth/passport/facebook.strategy.ts

import { Injectable, Inject } from '@nestjs/common';
import { Model } from 'mongoose';
import { use } from 'passport';

import { FACEBOOK_CONFIG_TOKEN, USER_MODEL_TOKEN } from '../../../server.constants';
import { IFacebookConfig } from '../interfaces/facebook-config.interface';
import { IUser } from '../../users/interfaces/user.interface';

const FacebookTokenStrategy = require('passport-facebook-token');

@Injectable()
export class FacebookStrategy {
  constructor(
    @Inject('FACEBOOK') private readonly fbConfig: IFacebookConfig,
    @Inject('USER') private readonly userModel: Model<IUser>
  ) {
    this.init();
  }

  private init(): void {
    use('facebook', new FacebookTokenStrategy({
      clientID: this.fbConfig.client_id,
      clientSecret: this.fbConfig.client_secret,
      profileFields: ['id', 'name', 'displayName', 'emails', 'photos']
    }, async (accessToken: string, refreshToken: string, profile: any, done: Function) => {
      try {
        var providerData = profile._json;
        providerData.accessToken = accessToken;
        providerData.refreshToken = refreshToken;

        let email: string = profile.emails.shift().value;

        //  Conditional if facebook doesn't return email
        if (!email || email === '') email = `${profile.id}@${profile.provider}.com`;

        const existingUser: IUser = await this.userModel.findOne({ email: email });

        if (existingUser) {
          return done(null, existingUser);
        }

        var providerUserProfile = {
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          displayName: profile.displayName,
          email: email,
          username: profile.username || `${profile.id}`,
          profileImageURL: (profile.id) ? '//graph.facebook.com/' + profile.id + '/picture?type=large' : undefined,
          provider: 'facebook',
          providerIdentifierField: 'id',
          providerData: providerData
        };

        const user = new this.userModel(providerUserProfile);

        done(null, await user.save());
      } catch (err) {
        done(err, null);
      }

      function generateUsername(profile) {
        var username = '';

        if (profile.emails) {
          username = profile.emails[0].value.split('@')[0];
        } else if (profile.name) {
          username = profile.name.givenName[0] + profile.name.familyName;
        }

        return username.toLowerCase() || undefined;
      }
    }));
  }
}

5.- Configure your auth module

import {
  Module,
  NestModule,
  MiddlewareConsumer,
  RequestMethod,
} from '@nestjs/common';
import { authenticate } from 'passport';

// Strategies
import { FacebookStrategy } from './passport/facebook.strategy';
import { UsersModule } from '../users/users.module';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';

@Module({
  imports: [UsersModule],
  providers: [
    AuthService,
    FacebookStrategy,
  ],
  controllers: [AuthController]
})
export class AuthModule implements NestModule {
  public configure(consumer: MiddlewareConsumer) {

    consumer
      .apply(authenticate('facebook', { session: false }))
      .forRoutes('auth/facebook/token');
  }
}
Root-Control commented 6 years ago

You can copy the following example here -> https://github.com/bojidaryovchev/nest-angular don't use this scaffolding, right now is deprecated

kamilmysliwiec commented 6 years ago

We are tracking this issue here: https://github.com/nestjs/docs.nestjs.com/issues/99. I'll share recipe in the docs once I find some time (hopefully very soon) :)

kgrvamsi commented 5 years ago

@kamilmysliwiec is there any chance to have example for facebook strategy and also can we use on single route to have two strategies like

@UseGuards(AuthGuard('jwt','facebook'))
ruslanguns commented 5 years ago

@kamilmysliwiec is there any chance to have example for facebook strategy and also can we use on single route to have two strategies like

@UseGuards(AuthGuard('jwt','facebook'))

Did you solve it?

kgrvamsi commented 5 years ago

@ruslanguns no ....for now i did the jwt integration but want to update the code for facebook ,google .

ruslanguns commented 5 years ago

@ruslanguns no ....for now i did the jwt integration but want to update the code for facebook ,google .

I will get that and will share it to you soon. It is pretty easy just have to follow step-by-step anyways any working sample made with Nodejs would be compatible as well just need to adapt it.

lucasmonstrox commented 5 years ago

news?

ruslanguns commented 5 years ago

There's a way to do it simply with Passport... i will work on that next week.

lucasmonstrox commented 5 years ago

@ruslanguns

@Injectable()
export class GithubStrategy extends PassportStrategy(
  Strategy,
  AuthProviderEnum.Github,
) {
  constructor(
    @Inject('GITHUB_CONFIG')
    private readonly githubConfig: IGithubConfig,
    private readonly userService: UserService,
  ) {
    super(githubConfig);
  }
}

I just put configs there and everything is working :)

kgrvamsi commented 5 years ago

sorry but my question was more on can a route have two strategies enabled instead one.

ruslanguns commented 5 years ago

@ruslanguns

@Injectable()
export class GithubStrategy extends PassportStrategy(
  Strategy,
  AuthProviderEnum.Github,
) {
  constructor(
    @Inject('GITHUB_CONFIG')
    private readonly githubConfig: IGithubConfig,
    private readonly userService: UserService,
  ) {
    super(githubConfig);
  }
}

I just put configs there and everything is working :)

@luqezman I like your sample, can you share all working module, I am just having issues coding this Social Integration.

TrejGun commented 5 years ago

Guys here is what you are looking for - boilerplate with local/google auth, sessions, and ACL https://trejgun.github.io/

ruslanguns commented 5 years ago

Ohhh nice... thank you really much!!

Ruslán González Tel: +34 644 27 47 56 email: ruslanguns@gmail.com

El dom., 1 de sep. de 2019 a la(s) 12:16, Trej Gun (notifications@github.com) escribió:

Guys here is what you are looking for - boilerplate with local/google auth, sessions, and ACL https://github.com/TrejGun/nest-authorization

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/nestjs/nest/issues/1247?email_source=notifications&email_token=AEXDV6E7XMYBBC4ZDPQMC33QHOQBBA5CNFSM4GAPRDE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD5UACSY#issuecomment-526909771, or mute the thread https://github.com/notifications/unsubscribe-auth/AEXDV6AYKFQDWATNJ53INEDQHOQBBANCNFSM4GAPRDEQ .

lock[bot] commented 4 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.