parent
5e76597ed7
commit
f871844dc0
@ -0,0 +1,21 @@
|
|||||||
|
import passport from 'passport';
|
||||||
|
import { facebookStrategy, facebookRouter } from './providers/facebook';
|
||||||
|
import { Router } from 'express'
|
||||||
|
import UserModel, { User } from '../models/user'
|
||||||
|
|
||||||
|
export function initPassport(): void {
|
||||||
|
passport.serializeUser((user: User, done) => {
|
||||||
|
done(null, user.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
passport.deserializeUser((id, done) => {
|
||||||
|
UserModel.findById(id, (err, user) => {
|
||||||
|
done(err, user);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
passport.use('facebook', facebookStrategy());
|
||||||
|
}
|
||||||
|
|
||||||
|
export const authRouter = Router();
|
||||||
|
authRouter.use(facebookRouter);
|
@ -0,0 +1,27 @@
|
|||||||
|
import { Strategy, StrategyOption, AuthenticateOptions, Profile } from 'passport-facebook';
|
||||||
|
|
||||||
|
import { Router } from 'express'
|
||||||
|
import passport from 'passport'
|
||||||
|
|
||||||
|
import genericStrategy from '../strategy'
|
||||||
|
|
||||||
|
const strategyOptions: StrategyOption = {
|
||||||
|
clientID: process.env.FACEBOOK_CLIENT_ID as string,
|
||||||
|
clientSecret: process.env.FACEBOOK_CLIENT_SECRET as string,
|
||||||
|
callbackURL: '/auth/facebook/redirect',
|
||||||
|
profileFields: ['id', 'displayName', 'picture.type(large)', 'email']
|
||||||
|
}
|
||||||
|
|
||||||
|
export function facebookStrategy() {
|
||||||
|
return new Strategy(strategyOptions, genericStrategy<Profile>('facebook'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const facebookRouter = Router()
|
||||||
|
|
||||||
|
const facebookAuthenticateOptions: AuthenticateOptions = {
|
||||||
|
authType: 'rerequest', scope: ['email']
|
||||||
|
}
|
||||||
|
|
||||||
|
facebookRouter.get('/facebook', passport.authenticate('facebook', facebookAuthenticateOptions));
|
||||||
|
facebookRouter.get('/facebook/redirect',
|
||||||
|
passport.authenticate('facebook', { successRedirect: '/museo', failureRedirect: '/' }));
|
@ -0,0 +1,48 @@
|
|||||||
|
import { Profile } from 'passport'
|
||||||
|
import UserModel, { User } from '../models/user'
|
||||||
|
import { authProviders } from '../types'
|
||||||
|
|
||||||
|
type doneCallback = (error: string | null, user?: Promise<User> | User | boolean) => void
|
||||||
|
|
||||||
|
function genericStrategy<ProfileT extends Profile>(provider: authProviders) {
|
||||||
|
return async (
|
||||||
|
_accessToken: string,
|
||||||
|
_refreshToken: string,
|
||||||
|
profile: ProfileT,
|
||||||
|
done: doneCallback
|
||||||
|
) => {
|
||||||
|
if (!profile.emails?.[0].value) {
|
||||||
|
console.error(`${provider} Email permission not provided`)
|
||||||
|
return done(null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await UserModel.findOne({ provider, providerId: profile.id }).exec();
|
||||||
|
|
||||||
|
console.info(`${provider} user found. Logging in.`);
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
return done(null, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.info(`${provider} user not found. Creating.`);
|
||||||
|
|
||||||
|
const newUser = new UserModel({
|
||||||
|
providerId: profile.id,
|
||||||
|
name: profile.displayName,
|
||||||
|
provider,
|
||||||
|
email: profile.emails?.[0].value,
|
||||||
|
photo: profile.photos?.[0].value,
|
||||||
|
}).save((err: string) => {
|
||||||
|
if (err) throw (err);
|
||||||
|
});
|
||||||
|
|
||||||
|
return done(null, newUser);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
return done(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default genericStrategy
|
@ -0,0 +1,36 @@
|
|||||||
|
import { model, Schema, Document } from "mongoose"
|
||||||
|
import { authProviders } from '../types'
|
||||||
|
|
||||||
|
export interface User extends Document {
|
||||||
|
providerId: string
|
||||||
|
name: string
|
||||||
|
email: string
|
||||||
|
provider: authProviders
|
||||||
|
photo?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const userSchema = new Schema(
|
||||||
|
{
|
||||||
|
providerId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
provider: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
photo: String
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
const UserModel = model<User>("User", userSchema)
|
||||||
|
export default UserModel
|
@ -0,0 +1 @@
|
|||||||
|
export type authProviders = "facebook" | "twitter" | "instagram" | "google"
|
Loading…
Reference in new issue