Tutorial - Como crear un login / registro usando Facebook con Typescript + Express Js + Handlebars Js + Mysql
Como crear un login - registro con Facebook y Typescript + Express Js + Handlebars Js + Mysql
El primer paso será ir a Facebook Developers. y seguir estos simples pasos:
- Hacer click en la parte superior derecha al link que dice Mis Apps
- Agregar una nueva App
- crear un nuevo identificador
- Introducir el nombre y darle al botón identificador de la app
- Agregar un nuevo producto +
- Inicio de sesión con Facebook
- Copiar el App ID y App Secret en el block de notas. (mas tarde lo usaremos)
Base de datos:
- Creamos una base de datos
- Creamos una tabla users
- Campos { id; facebook_ID ; email ; foto }
Desktop (creación carpeta) (windows):
- tecla window + R = consola
- cd desktop
- mkdir facebook_access
- cd facebook_access
- npm init --yes
- tsc --init
- type nul > .env
- mkdir src
- cd src
- type nul > index.ts
- type nul > app.ts
- mkdir views
- cd views
- mkdir layouts
- mkdir partials
- type nul > home.hbs
- cd layouts
- type nul > main.hbs
- cd ../../../
Instalar paquetes/módulos (producción)
- npm i express express-handlebars morgan express-session mysql2 passport passport-facebook method-override
Instalar paquetes/módulos (desarrollo)
- npm i -D typescript nodemon ts-node dotenv @types/express @types/express-handlebars @types/morgan @types/express-session types/mysql2 @types/passport @types/passport-facebook @types/method-override
Modificar el tsconfig.json
descomentar 2 opciones:
1) outDir :./dist
2) rootDir: ./src
modificar el target y colocar : es6
Modificar el package.json :
crear un script llamado dev
y colocar : nodemon src/index.ts --exec ts-node
Abrir el .env y colocar lo siguiente (lo tienes anotado en el block de notas):
sustituye las xxx con tus datos creados en facebook
FACEBOOK_CLIENT_ID = xxxxxxxxx
FACEBOOK_SECRET_APP = xxxxxxxxxxxxxxxxxx
COMIENZA EL CÓDIGO DE NUESTRO EJEMPLO
crearemos el archivo de conexión a la bd mysql
cancelamos la consola
escribimos en la consola :
cd src
type nul > database.ts
cd ..
abrimos el database.ts y escribimos lo siguiente:
import mysql from ´mysql2/promise´
export const connection = async(): Promise <mysqli.pool> => {
<mysqli.pool>const conex = await mysql.createPool({
<mysqli.pool> host:´localhost´,
<mysqli.pool> user:´root´,
<mysqli.pool> database:´facebook_acceso´,
<mysqli.pool> connectionLimit:10 }
<mysqli.pool>) return conex;
<mysqli.pool>}
index.ts
import dotenv from ´dotenv´;
dotenv.config();
import app from ´./app´
async function main()
{
await app.listen(app.get(´port´));
console.log(´Server on port ´, app.get(´port´));
}
main();
app.ts
import express, {Application,Request,Response,NextFunction} from ´express´
import morgan from ´morgan´
import path from ´path´
import exphbs from ´express-handlebars´
import passport from ´passport´
import session from ´express-session´
import methodOverride from ´method-override´
import ´./passport´
// SETTINGS
const app:Application = express()
app.set(´port´, process.env.PORT || 3000 )
app.set(´views´, path.join(__dirname,´views´) )
app.engine(´.hbs´ , exphbs({</p>
defaultLayout: ´main.hbs´,</p>
layoutsDir:path.join(app.get(´views´),´layouts´),
partialsDir:path.join(app.get(´views´),´partials´),
extname:´.hbs´ }))
app.set(´view engine´, ´.hbs´)
// MIDDLEWARES
app.use(morgan(´dev´))
app.use(express.urlencoded({extended:false}))
app.use(express.json())
app.use(session({ secret : ´secret_anything´, resave:false, saveUninitialized:false })) app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride(´_method´))
app.use( (req:Request,res:Response,next:NextFunction) => {
app.locals.user = req.user || null;
next(); })
const authenticate = (req:Request,res:Response,next:NextFunction): void | Response => {
if(req.isAuthenticated()){
return next(); }
return res.redirect(´/´);
}
//ROUTES
app.get(´/´, (req,res) => { res.render(´home´) })
app.get(´/login-with-facebook´, passport.authenticate(´facebook´,{scope:[´email´]}) )
app.get(´/facebook/callback´, passport.authenticate(´facebook´, {</p>
failureRedirect:´/´,
successRedirect:´/profile´ }))
app.get(´/profile´, authenticate, (req,res) => { res.render(´profile´) })
app.delete(´/´, (req,res) => { req.logout(); })
export default app;</p>
passport.ts
import passport from ´passport´
import {Strategy as FacebookStrategy} from ´passport-facebook´
import {connection} from ´./database´
interface IUser {
id:number;
facebook_id:string;
email:string | null;
foto:string | null
}
passport.use( new FacebookStrategy({</p>
clientID: `${process.env[´FACEBOOK_CLIENT_ID´]}`,
clientSecret: `${process.env[´FACEBOOK_SECRET_APP´]}`,
callbackURL: ´/facebook/callback´,
profileFields: [´id´, ´photos´, ´email´] },
async(accessToken,refreshToken,profile,cb) => {
try{
const conn = await connection();
const [results] = await conn.query("select * from users where facebook_id=?",[profile.id])
const rows = JSON.parse(JSON.stringify(results))
if(rows.length > 0) </p>
{
cb(null,rows[0])
}else{
const email = profile.emails ? profile.emails[0].value : null
const photo = profile.photos ? profile.photos[0].value : null
const [rows] = await conn.query(´insert into users(facebook_id,email,foto) values(?,?,?)´,[profile.id,email,photo])
const row = JSON.parse(JSON.stringify(rows));
const user:IUser = { id:row.insertId, facebook_id:profile.id, email, foto:photo } return cb(null, user);</p>
}
}catch(e){
return cb(e.message)
}
}) )
passport.serializeUser( (user:IUser,cb) => {
cb(null,user.id)
})
passport.deserializeUser( async(id,cb) => {</p>
try{
const conn = await connection();
const [results] = await conn.query("select * from users where id=?",[id]);
const result = JSON.parse(JSON.stringify(results));
return cb(null,result[0])
}catch{
return cb(false)
}
})
Con esto terminamos el 80% del código ahora vamos con las vistas
navegamos a la carpeta views / layouts / main.hbs
Main.hbs
{{{body}}}
views/
Home.hbs
views/
Profile.hbs
Con eso ya hemos terminado, si todo ha salido bien facebook nos solicitará que aceptemos el permiso de acceso y listo
RESULTADO FINAL
Espero que les sirva de ayuda en sus proximos proyectos!!
Tutorial disponible en mi pagina web oficial aquí