Otentikasi Users Menggunakan Node ExpressJS Dan Passport.js - CRUDPRO

Otentikasi Users Menggunakan Node ExpressJS Dan Passport.js

Banyak aplikasi Node.js mengharuskan users untuk mengautentikasi untuk mengakses konten pribadi. Proses otentikasi harus berfungsi dan aman, dan membuat proses otentikasi dari awal dapat memakan waktu dan membosankan. Untuk alasan ini, sebagian besar developer modern memilih untuk menggunakan perpustakaan tepercaya atau layanan eksternal. Passport.js adalah middleware Express populer yang dibuat khusus untuk memfasilitasi proses login. Fleksibel, dipercaya oleh banyak organisasi di seluruh dunia, dan mudah diintegrasikan ke dalam kode ExpressJS.

Dalam tutorial ini, Anda akan melakukan hal berikut:

  • Buat form login untuk aplikasi Node Anda menggunakan passport
  • Gunakan strategi otentikasi sessions dengan passport
  • Hubungkan passport ke database MongoDB untuk menyimpan data users
  • Izinkan hanya users yang masuk untuk mengakses halaman

Pada akhir tutorial ini, Anda akan belajar cara membuat halaman login fungsional dengan otentikasi dan otorisasi. Tutorial ini menjelaskan cara menggunakan Express.js untuk otentikasi users.

Tujuan

Buat aplikasi yang melakukan tugas otentikasi dan otorisasi dasar.

Prasyarat

  • Apa perbedaan antara otorisasi dan otentikasi?
  • Proses form login dengan ExpressJS
  • Menyiapkan Express Session Authentication

Strategi passport.js

passport adalah perpustakaan fitur otentikasi yang dapat disesuaikan dengan kebutuhan sebagian besar aplikasi. Apa alasan fleksibilitas passport? Alasan utamanya adalah developer dapat memilih dari harta karun strategi implementasi. Strategi passport adalah modul terpisah yang disesuaikan dengan metode otentikasi individu. Strategi passport yang tersedia adalah:

  • passport-local: Nama users lokal dan otentikasi kata sandi
  • passport-facebook: Otentikasi dengan Facebook melalui OAuth
  • Passport-Twitter: Otentikasi dengan Twitter melalui OAuth
  • passport-jwt: gunakan Token Web JSON instance dari sessions

Ada ratusan strategi. Anda juga dapat menemukan modul yang disesuaikan dengan teknologi atau basis data khusus Anda. Misalnya, proyek ini menggunakan otentikasi lokal dengan MongoDB. Gunakan pembungkus MongoDB Mongoose dan modul passport-local-mongoose untuk fokus pada kode otorisasi.

MongoDB

MongoDB adalah database NoSQL yang menyimpan data menggunakan dokumen berformat JSON. Beberapa developer NodeJS lebih memilih MongoDB karena mereka akrab dengan JSON, yang mudah digunakan dengan objek JavaScript. Berikut ini adalah contoh data MongoDB.

{ name: 'Lori Fields',
  address: {
    street: 123 Palm Trace
    city: Miami, FL
    zip code: 33101
  }
},  
{ name: 'Harry Humbug',
  address: {
    street: 6 SW 1st Street
    city: Deerfield Beach, FL
    zip code: 33442
  }
}

Aplikasi otentikasi menggunakan Passport dan ExpressJS

Sekarang setelah Anda memiliki gambaran umum tentang passport dan MongoDB, Anda siap untuk memulai proyek Anda. Struktur file dari aplikasi ini adalah sebagai berikut:

.
└── login
    ├── package.json
    ├── server.js
    ├── static
    │   ├── index.html
    │   ├── login.html
    │   └── secret-page.html
    └── user.js

Seperti yang Anda lihat, nama folder proyek utama adalah login. Saat masuk:

  • Folder bernama static yang berisi file HTML
  • Akar aplikasi Anda, server.js yang berisi semua kode server ExpressJS yang berisi root
  • Gunakan Mongoose untuk terhubung ke database dan membuat model users user.js
  • package.json, file konfigurasi

  1. Unduh MongoDB dan buat database
  2. Buka Instal MongoDB Community Edition dan klik tautan untuk sistem operasi Anda (Linux, macOS, atau Windows). Ikuti petunjuk untuk menginstal dan meluncurkan MongoDB. Setelah menginstal dan meluncurkan MongoDB, buka shell perintah MongoDB.

    mongo
    

    Kemudian masuk ke database "users" (buat jika belum ada).

    > use users
    

    Anda dapat keluar dari shell perintah MongoDB kapan saja dengan memasukkan perintah quit.

    > quit ()
    

  3. Buat file package.json
  4. Dengan asumsi Anda sudah menginstal NodeJS, buat file package.json di folder proyek utama Anda.

    npm init -y
    

  5. Instal ExpressJS dan dependensi
  6. Sebelum Anda mulai menulis kode, Anda perlu menginstal dependensi yang diperlukan. Pertama, instal ExpressJS (kerangka server), body-parser (parsing badan permintaan masuk), dan sessions ekspres (middleware sessions berbasis cookie).

    npm install express body-parser express-session
    

    emudian instal Passport dan passport-local. passport adalah perpustakaan otentikasi dan passport-lokal adalah strategi otentikasi inti kami.

    npm install passport passport-local
    

    Selanjutnya, instal connect-ensure-login, middleware otentikasi yang memungkinkan Anda membatasi akses ke halaman Anda dengan mudah. Dibuat untuk bekerja dengan passport, satu panggilan fungsi hanya dapat menyetujui rute ke users yang masuk.

    npm install connect-ensure-login
    

    Selanjutnya, instal Mongoose, objek data mapper (ODM) yang digunakan untuk mengintegrasikan MongoDB dengan NodeJS. Pustaka ini menyederhanakan pemodelan data MongoDB dan memfasilitasi pembuatan objek JavaScript dan persistensi dokumen database. Asinkronnya fungsi kueri NodeJS dapat memperumit pemodelan data. Menggunakan Mongoose dalam proyek ini memungkinkan Anda untuk fokus pada kode otorisasi daripada pembuatan dokumen atau integrasi database.

    npm install mongoose
    

    Terakhir, instal passport-local-mongoose. Strategi ini mengintegrasikan luwak dengan strategi passport lokal.

    npm install passport-local-mongoose
    

  7. Buat file HTML
  8. Pastikan semua file HTML ditulis dengan benar dan disimpan dalam direktori statis. Contoh index.html:

    contoh index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
      <title>Welcome Home</title>
      </head>
      <body>
      <a href="/login">Please Login Here!</a>
      </body>
    </html>
    

    contoh login.html:

    <!DOCTYPE html>
    <html lang="en">
      <head>
      <title>Example Login Form</title>
      </head>
      <body>
      <form action="//members.osiolabs.com/login" method="post">
          <!-- user input-->
          Username:<br>
          <input type="text" name="username" placeholder="Username" required><br><br>
          Password:<br>
          <input type="password" name="password" placeholder="Password" required><br><br>
          <!-- submit button -->
          <input type="submit" value="login">
      </form>
      </body>
    </html>
    
    contoh secret-page.html:
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>Secret Page</title>
      </head>
      <body>
        <p align="justify">This is a secret page that is only available to logged-in users.
         Congratulations!!!  You are in on our secret!</p>
         <a href="/logout">Log Out</a>
      </body>
    </html>
    

  9. Buat user.js
  10. Mari kita buat user.js keluar dari kode database. kami akan:

    • Hubungkan ke database
    • Buat model users passport
    • Buat dokumen MongoDB bernama 'userData'

    Pertama, sertakan Mongoose dan passport-local-mongoose.

    const mongoose = require('mongoose');
    const passportLocalMongoose = require('passport-local-mongoose');
    

    Kemudian sambungkan ke database "users" di server lokal. Jika server database tidak ada di mesin lokal Anda, tulis nama host atau alamat IP alih-alih "localhost".

    mongoose.connect('mongodb://localhost/users',{
      useNewUrlParser: true,
      useUnifiedTopology: true
    });
    
    • URL koneksi: URL koneksi adalah "mongodb://localhost/users". "Localhost" adalahh host dan "users" adalah database. Jika database Anda berada di server eksternal, Anda mungkin perlu menyertakan lebih banyak parameter. Contoh:'mongodb://username:password@host:port/database? pilihan ...'

    • useNewUrlParser: Ini diatur untuk menghindari peringatan usang dari driver MongoDB asli. Keikutsertaan untuk memfasilitasi konversi aplikasi lama. Untuk developeran baru, setel ini ke true. Lihat dokumentasi Mongoose untuk informasi lebih lanjut.

    • useUnifiedTopology: Juga disetel untuk menghindari peringatan yang tidak digunakan lagi. Sederhananya, mesin manajemen koneksi telah ditingkatkan. Setel ke true untuk developeran baru, lihat dokumentasi Mongoose untuk detail selengkapnya.

    Selanjutnya, buat model users yang berisi dua properti: username dan password. Keduanya adalah tipe data string.

    const Schema = mongoose.Schema;
    
    const User = new Schema({
      username: String,
      password: String
    });
    

    Akhirnya, model siap untuk diekspor.

    1. Gunakan library passport-local-mongoose untuk mengekspor "users" dalam format yang dapat digunakan ke kode passport yang akan Anda buat.

    2. Karena Anda mengekspor model sebagai modul, Anda dapat menggunakannya di server.js untuk membuat dokumen yang disebut "userData". userData menyimpan informasi users (id, username, hash). passport-local-mongoose secara otomatis akan memberi garam dan hash kata sandi Anda.

    File user.js yang telah selesai akan terlihat seperti kode berikut.

    // dependencies
    const mongoose = require('mongoose');
    const passportLocalMongoose = require('passport-local-mongoose');
    // connect to database
    mongoose.connect('mongodb://localhost/users',{
      useNewUrlParser: true,
      useUnifiedTopology: true
    });
    // Create Model
    const Schema = mongoose.Schema;
    
    const User = new Schema({
      username: String,
      password: String
    });
    // Export Model
    User.plugin(passportLocalMongoose);
    
    module.exports = mongoose.model('userData', User, 'userData');
    

  11. Buat data users dummy
  12. Untuk menguji aplikasi Anda, Anda memerlukan data pengujian. Data uji adalah data sementara yang Anda masukkan ke dalam database untuk menguji kode Anda. Dalam aplikasi langsung, users mendaftar melalui form pendaftaran. Daftarkan dua untuk menguji kode otorisasi Anda.

    const UserDetails = require('./user');
    
    UserDetails.register({ username: 'candy', active: false }, 'cane');
    UserDetails.register({ username: 'starbuck', active: false }, 'redeye');
    

    Ini akan membuat dua users, cany dan starbuck, dengan kata sandi cane dan redeye.

    Pada tahap awal developeran, ini adalah cara mudah untuk menambahkan data pengujian sementara ke database pengujian sementara. Anda tidak akan pernah menggunakan metode ini di server produksi. Cara lain untuk menyisipkan data termasuk melakukan migrasi dari baris perintah, menggunakan form (seperti form pendaftaran), dan menempatkan kode di atas dalam file migrasi data.

    Jalankan kodenya.

    node dummy-data.js
    

  13. Buat server.js
  14. Sekarang Anda siap untuk membuat file root server.js untuk aplikasi Anda.

    Pertama, sertakan dependensi.

    const express = require('express'); // server software
    const bodyParser = require('body-parser'); // parser middleware
    const session = require('express-session');  // session middleware
    const passport = require('passport');  // authentication
    const connectEnsureLogin = require('connect-ensure-login'); //authorization
    

    Juga, jangan lupa untuk menyertakan model users.

    const User = require('./user.js'); // User Model
    

    Selanjutnya, mari kita buat aplikasi Express.

    const app = express();
    

    Itu tidak diatur dalam modul passport-local-mongoose, jadi Anda perlu mengatur sessions ekspres. Untuk informasi tentang pengaturan sessions ekspres, periksa pengaturan untuk otentikasi sessions ekspres.

    app.use(session({
      secret: 'r8q,+&1LM3)CD*zAGpx1xm{NeQhc;#',
      resave: false,
      saveUninitialized: true,
      cookie: { maxAge: 60 * 60 * 1000 } // 1 hour
    }));
    

    Anda perlu mengkonfigurasi middleware sedikit lagi:

    1. bodyParser: Mengurai data yang disandikan URL dari badan
    2. passport.initialize: Middleware yang menggunakan Passport dengan Express
    3. passport.session: Anda harus menggunakan sessions ekspres di passport Anda
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(passport.initialize());
    app.use(passport.session());
    

    Sebelum Anda dapat mengautentikasi, Anda perlu mendeklarasikan dan mengonfigurasi strategi Anda. Modul strategi kami, passport-local-mongoose, melakukan tugas yang membosankan untuk membuat strategi bagi kami, jadi yang Anda butuhkan hanyalah kode di bawah ini.

    passport.use(User.createStrategy());
    

    Jika Anda menggunakan passport-lokal instance passport-local-mongoose, Anda perlu mengonfigurasi strategi login Anda. Lihat contoh konfigurasi strategi lokal di bawah ini (tidak digunakan dalam proyek hari ini).

    passport.use(new LocalStrategy(
      // function of username, password, done(callback)
      function(username, password, done) {
        // look for the user data
        User.findOne({ username: username }, function (err, user) {
          // if there is an error
          if (err) { return done(err); }
          // if user doesn't exist
          if (!user) { return done(null, false, { message: 'User not found.' }); }
          // if the password isn't correct
          if (!user.verifyPassword(password)) { return done(null, false, {   
          message: 'Invalid password.' }); }
          // if the user is properly authenticated
          return done(null, user);
        });
      }
    ));
    

    Untuk mengautentikasi, passport pertama-tama melihat detail login users dan kemudian memanggil panggilan balik yang divalidasi (selesai). Jika users diautentikasi dengan benar, teruskan users ke panggilan balik. Jika users tidak diautentikasi dengan benar, berikan false ke panggilan balik. Anda juga memiliki opsi untuk meneruskan pesan tertentu ke panggilan balik.

    Saat menggunakan sessions di passport, sessions baru dimulai segera setelah users diautentikasi dengan benar. Ketika ini terjadi, data users diserialkan ke dalam sessions dan ID users disimpan di req.session.passport.user. Untuk mengakses data users, deserialized menggunakan ID users sebagai kunci. Data users ditanyakan dan dilampirkan ke req.user.

    passport.serializeUser(User.serializeUser());
    passport.deserializeUser(User.deserializeUser());
    

    Sejauh ini, server.js akan terlihat seperti kode berikut.

    const express = require('express'); // server software
    const bodyParser = require('body-parser'); // parser middleware
    const session = require('express-session');  // session middleware
    const passport = require('passport');  // authentication
    const connectEnsureLogin = require('connect-ensure-login');// authorization
    
    const User = require('./user.js'); // User Model
    
    const app = express();
    
    // Configure Sessions Middleware
    app.use(session({
      secret: 'r8q,+&1LM3)CD*zAGpx1xm{NeQhc;#',
      resave: false,
      saveUninitialized: true,
      cookie: { maxAge: 60 * 60 * 1000 } // 1 hour
    }));
    
    // Configure More Middleware
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(passport.initialize());
    app.use(passport.session());
    
    // Passport Local Strategy
    passport.use(User.createStrategy());
    
    // To use with sessions
    passport.serializeUser(User.serializeUser());
    passport.deserializeUser(User.deserializeUser());
    

  15. Tentukan rute GET
  16. Anda siap menambahkan rute GET ke kode server.js Anda. Mulailah dengan rute ke halaman rumah Anda. Siapapun bisa mengaksesnya.

    app.get('/', (req, res) => {
      res.sendFile(__dirname + '/static/index.html');
    })
    

    Selanjutnya, buat rute ke halaman login aplikasi Anda. Selain itu, siapa pun dapat mengaksesnya.

    app.get('/login', (req, res) => {
      res.sendFile(__dirname + '/static/login.html');
    });
    

    Selanjutnya, buat rute dasbor. Hanya users yang masuk yang dapat mengaksesnya.

    app.get('/dashboard', connectEnsureLogin.ensureLoggedIn(), (req, res) => {
      res.send(`Hello ${req.user.username}. Your session ID is ${req.sessionID} 
       and your session expires in ${req.session.cookie.maxAge} 
       milliseconds.<br><br>
       <a href="/logout">Log Out</a><br><br>
       <a href="/secret">Members Only</a>`);
    });
    

    Seperti disebutkan di atas, panggil fungsi connectEnsureLogin.ensureLoggedIn() di root handler sehingga hanya users yang masuk yang dapat mengakses halaman. Saat Anda menavigasi ke rute itu, itu mengirim pesan ke users yang masuk. Pesan tersebut meliputi:

    1. Nama users mereka: req.user.username (lebih dijelaskan di atas saat membuat file skema user.js)
    2. ID sessions mereka: req.sessionID
    3. Masa pakai cookie sessions maksimum: req.session.cookie.maxAge
    4. Tautan untuk keluar dari aplikasi:/logout
    5. Tautan ke halaman khusus anggota:/secret

    Akar halaman rahasia juga hanya dapat diakses oleh users yang masuk.

    app.get('/secret', connectEnsureLogin.ensureLoggedIn(), (req, res) => {
      res.sendFile(__dirname + '/static/secret-page.html');
    });
    

    Terakhir, buat rute untuk logout users.

    app.get('/logout', function(req, res) {
      req.logout();
      res.redirect('/login');
    });
    
    • req.logout: Keluar dari users
    • req.redirect: Mengarahkan users ke halaman lain. Dalam hal ini, users akan diarahkan ke /login.

  17. Tambahkan rute POST masuk
  18. Aplikasi ini berisi satu POST route/login. Dengan membuat rute ini, Anda siap untuk membuat proses otentikasi bekerja.

    app.post('/login', passport.authenticate('local', { failureRedirect: '/' }),  function(req, res) {
      console.log(req.user)
      res.redirect('/dashboard');
    });
    

    Panggil passport.authenticate pada route handler dan berikan dua parameter.

    • "Lokal": Strategi utama yang kami gunakan

    • failureRedirect: Jika users tidak mengautentikasi, users akan diarahkan ke halaman beranda.

    Jika users gagal mengautentikasi, users akan dikirim kembali ke halaman beranda. Jika mereka diautentikasi, kode dalam panggilan balik akan dieksekusi:

    • console.log (req.user): Properti users dilampirkan ke req.user saat users mengautentikasi. Saat Anda menguji aplikasi ini, Anda akan melihat ID, nama users, garam, dan properti hash di perangkat Anda. Properti ini dapat bervariasi tergantung pada bagaimana Anda mendesain.

    • res.redirect (‘/ dashboard’): Ketika otentikasi users selesai, users akan diarahkan ke /dashboard. Tetapkan port ke aplikasi

    Anda siap untuk keluar dari server.js dengan menetapkan port.

    // assign port
    const port = 3000;
    app.listen(port, () => console.log(`This app is listening on port ${port}`));
    
    File server.js yang telah selesai akan terlihat seperti kode berikut.
    
    const express = require('express'); // server software
    const bodyParser = require('body-parser'); // parser middleware
    const session = require('express-session');  // session middleware
    const passport = require('passport');  // authentication
    const connectEnsureLogin = require('connect-ensure-login');// authorization
    
    const User = require('./user.js'); // User Model
    
    const app = express();
    
    // Configure Sessions Middleware
    app.use(session({
      secret: 'r8q,+&1LM3)CD*zAGpx1xm{NeQhc;#',
      resave: false,
      saveUninitialized: true,
      cookie: { maxAge: 60 * 60 * 1000 } // 1 hour
    }));
    
    // Configure Middleware
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(passport.initialize());
    app.use(passport.session());
    
    // Passport Local Strategy
    passport.use(User.createStrategy());
    
    // To use with sessions
    passport.serializeUser(User.serializeUser());
    passport.deserializeUser(User.deserializeUser());
    
    // Route to Homepage
    app.get('/', (req, res) => {
      res.sendFile(__dirname + '/static/index.html');
    });
    
    // Route to Login Page
    app.get('/login', (req, res) => {
      res.sendFile(__dirname + '/static/login.html');
    });
    
    // Route to Dashboard
    app.get('/dashboard', connectEnsureLogin.ensureLoggedIn(), (req, res) => {
      res.send(`Hello ${req.user.username}. Your session ID is ${req.sessionID} 
      and your session expires in ${req.session.cookie.maxAge} 
      milliseconds.<br><br>
      <a href="/logout">Log Out</a><br><br><a href="/secret">Members Only</a>`);
    });
    
    // Route to Secret Page
    app.get('/secret', connectEnsureLogin.ensureLoggedIn(), (req, res) => {
      res.sendFile(__dirname + '/static/secret-page.html');
    });
    
    // Route to Log out
    app.get('/logout', function(req, res) {
      req.logout();
      res.redirect('/login');
    });
    
    // Post Route: /login
    app.post('/login', passport.authenticate('local', { failureRedirect: '/' }),  function(req, res) {
      console.log(req.user)
      res.redirect('/dashboard');
    });
    
    // assign port
    const port = 3000;
    app.listen(port, () => console.log(`This app is listening on port ${port}`));
    

  19. Uji kodenya
  20. Proyek selesai dan Anda siap untuk menguji kode Anda. Pergi ke terminal, buka folder proyek utama (login) dan mulai server.

    node server.js
    

    Di browser web Anda, buka http://localhost:3000/. Halaman rumah ditampilkan. Silakan masuk dari sini Klik! Link untuk menuju halaman login. Kemudian masukkan kredensial login yang valid. Kemudian klik tombol login untuk masuk ke /dasbor.

    Kemudian klik tautan Hanya Anggota untuk membuka / rahasia.

    Terakhir, klik link Logout untuk mencegah akses ke /dasbor atau /rahasia ketika Anda tidak login. Anda juga dapat memastikan bahwa Anda diarahkan ke halaman rumah Anda jika Anda memasukkan informasi login yang salah.

kesimpulan

Passport.js adalah middleware otentikasi yang banyak digunakan yang memudahkan pembuatan aplikasi. developer dapat memilih dari berbagai strategi otentikasi yang sesuai dengan kebutuhan sebagian besar aplikasi. Dalam proyek ini, kami menggunakan passport-lokal untuk memverifikasi nama users dan kata sandi secara lokal.

Untuk database, kami menggunakan MongoDB, database NoSQL populer yang menyimpan data dalam dokumen JSON. Untuk menyederhanakan pemodelan data, kami menggunakan Mongoose untuk menangani interaksi antara NodeJS dan MongoDB. Ada ratusan modul strategi passport khusus yang tersedia dan saya memilih untuk menggunakan passport-local-mongoose.

Untuk menggunakan passport dengan ExpressJS, Anda perlu melakukan hal berikut:

  • Hubungkan ke database
  • Buat model users
  • Konfigurasikan middleware yang tepat
  • Konfigurasikan strategi passport
  • Panggil fungsi passport.authenticate pada root POST login
  • Setelah diautentikasi, req.user akan dibuat dan Anda akan dapat mengakses properti users.

Lebih memperdalam pemahaman