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