{"id":19606752,"url":"https://github.com/learnwithfair/web-authentication-documentation","last_synced_at":"2025-06-26T23:34:25.602Z","repository":{"id":237639016,"uuid":"794941119","full_name":"learnwithfair/web-authentication-documentation","owner":"learnwithfair","description":"web-authentication-documentation with  [learnwithfair, Learn with fair, Rahatul Rabbi, Md Rahatul Rabbi ,rahatulrabbi]. In this repo I describes about Database Matching, Database Encryption Hashing, Hashing + Salting Password, Cookies and Session with Passport, Google OAuth with passport session based, Passport-jwt (token based)","archived":false,"fork":false,"pushed_at":"2024-05-02T09:13:25.000Z","size":241,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-09T09:24:24.285Z","etag":null,"topics":["auth","authentication","database-encryption","database-matching","hashing","jwt-authentication","learn-with-fair","learnwithfair","passport-google-oauth20","passport-local","passportjs","rahatul-rabbi","rahatulrabbi","salting","web-authentication"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/learnwithfair.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-02T09:11:54.000Z","updated_at":"2024-05-02T09:20:35.000Z","dependencies_parsed_at":"2024-05-02T22:24:29.754Z","dependency_job_id":null,"html_url":"https://github.com/learnwithfair/web-authentication-documentation","commit_stats":null,"previous_names":["learnwithfair/web-authentication-documentation"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/learnwithfair%2Fweb-authentication-documentation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/learnwithfair%2Fweb-authentication-documentation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/learnwithfair%2Fweb-authentication-documentation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/learnwithfair%2Fweb-authentication-documentation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/learnwithfair","download_url":"https://codeload.github.com/learnwithfair/web-authentication-documentation/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240894537,"owners_count":19874832,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","authentication","database-encryption","database-matching","hashing","jwt-authentication","learn-with-fair","learnwithfair","passport-google-oauth20","passport-local","passportjs","rahatul-rabbi","rahatulrabbi","salting","web-authentication"],"created_at":"2024-11-11T10:07:06.494Z","updated_at":"2025-02-26T16:43:50.657Z","avatar_url":"https://github.com/learnwithfair.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WEB-AUTHENTICATION-DOCUMENTATION\n\nThanks for visiting my GitHub account!\n\n\u003cimg src =\"https://www.w3.org/2019/03/webauthn-color.png\" height = \"200px\" width = \"200px\"/\u003e **Web Authentication** is a web standard published by the World Wide Web Consortium. WebAuthn is a core component of the FIDO2 Project under the guidance of the FIDO Alliance [see-more](https://webauthn.guide/#intro)\n\n## Source Code (Download)\n\n[Click Here](https://mega.nz/folder/RGFiUApD#PoKIVCwF8IkQhE2PHw1XxQ)\n\n## Authentication Schema\n\n|                                              |\n| :------------------------------------------: |\n|                    Schema                    |\n| ![schema](images/Web_Authentication.svg.png) |\n\n## Table of Contents\n\n1. [Database Matching](#level-1-database-matching)\n2. [Database Encryption](#level-2-database-encryption)\n3. [Hashing Password](#level-3-hashing-password)\n4. [Hashing + Salting Password](#level-4-hashing--salting-password)\n5. [Cookies \u0026 Session with Passport](#level-5-cookies--session-with-passport)\n6. [Google OAuth with passport session based](#level-6-google-oauth-with-passport-session-based)\n7. [Passport-jwt (token based)](#level-7-passport-jwt-token-based)\n8. [Follow Me](#follow-me)\n\n## Level 1: Database matching\n\n- save(), find({property: value})\n- if hacker can access our database then our data is too much human readable\n- [password checker online](http://password-checker.online-domain-tools.com/)\n\n## Level 2: Database Encryption\n\n- read mongoose encryption documentation: https://www.npmjs.com/package/mongoose-encryption\n- install mongoose encryption `npm install mongoose-encryption`\n- create new mongoose Schema\n\n  ```js\n  const mongoose = require(\"mongoose\");\n  const encrypt = require(\"mongoose-encryption\");\n\n  const userSchema = new mongoose.Schema({\n    name: String,\n    age: Number,\n    // whatever else\n  });\n  ```\n\n- create an encryption key inside .env file\n\n  ```js\n  ENCRYPTION_KEY = thisismyencryptionkey;\n  ```\n\n- set encryption key with our schema\n\n  ```js\n  const encrypt = require(\"mongoose-encryption\");\n\n  const encKey = process.env.ENCRYPTION_KEY;\n  // encrypt age regardless of any other options. name and _id will be left unencrypted\n  userSchema.plugin(encrypt, {\n    secret: encKey,\n    encryptedFields: [\"age\"],\n  });\n\n  User = mongoose.model(\"User\", userSchema);\n  ```\n\n## Level 3: Hashing password\n\n- no cncryption key; we will use hashing algorithm\n- hackers can not convert to plain text as no encryption key is available\n- md5 package: https://www.npmjs.com/package/md5\n- install md5 npm package: `npm install md5`\n- usage\n\n  ```js\n  var md5 = require(\"md5\");\n  console.log(md5(\"message\"));\n  // 78e731027d8fd50ed642340b7c9a63b3\n\n  // hash password when create it\n  const newUser = new User({\n    email: req.body.username,\n    password: md5(req.body.password),\n  });\n\n  app.post(\"/login\", async (req, res) =\u003e {\n    try {\n      const email = req.body.email;\n      const password = md5(req.body.password);\n      const user = await User.findOne({ email: email });\n      if (user \u0026\u0026 user.password === password) {\n        res.status(200).json({ status: \"valid user\" });\n      } else {\n        res.status(404).json({ status: \"Not valid user\" });\n      }\n    } catch (error) {\n      res.status(500).json(error.message);\n    }\n  });\n  ```\n\n## Level 4: Hashing + salting password\n\n- we can hash the password with some random number(salting)\n- install bcrypt npm package `npm install bcrypt`\n- usage\n\n  ```js\n  const bcrypt = require(\"bcrypt\");\n  const saltRounds = 10;\n\n  app.post(\"/register\", async (req, res) =\u003e {\n    try {\n      bcrypt.hash(req.body.password, saltRounds, async function (err, hash) {\n        const newUser = new User({\n          email: req.body.email,\n          password: hash,\n        });\n        await newUser.save();\n        res.status(201).json(newUser);\n      });\n    } catch (error) {\n      res.status(500).json(error.message);\n    }\n  });\n\n  app.post(\"/login\", async (req, res) =\u003e {\n    try {\n      const email = req.body.email;\n      const password = req.body.password;\n      const user = await User.findOne({ email: email });\n      if (user) {\n        bcrypt.compare(password, user.password, function (err, result) {\n          if (result === true) {\n            res.status(200).json({ status: \"valid user\" });\n          }\n        });\n      } else {\n        res.status(404).json({ status: \"Not valid user\" });\n      }\n    } catch (error) {\n      res.status(500).json(error.message);\n    }\n  });\n  ```\n\n## Level 5: Cookies \u0026 Session with passport\n\n- passport local strategy\n\n- `npm install passport passport-local passport-local-mongoose express-session`\n\n- my computer browser -\u003e browse aliexpress (GET Request) -\u003e to aliexpress server -\u003e response the website -\u003e add some items to the cart (post request to the server) -\u003e aliexpress server will response and tell the browser to create a file in my computer for storing my selection -\u003e so when next time we make a get request to the server we send the cookie with the get request -\u003e server will return the cart again\n\n- cookie is a text file created by server on a user's device when we visit a website\n- that stores limited information such as login credentials - username, password; user preferences, cart contents from a web browser session\n- saving users behaviour\n- read more about cookies - https://www.trendmicro.com/vinfo/us/security/definition/cookies\n- types of cookies -\u003e session cookie, presistent cookie, supercookie\n- login -\u003e save user credentials as cookie for next time authentication -\u003e log out and the session is destroyed\n- salt and hash is automatically generated by passport-local-mongoose\n- express session package create the cookie\n\n1. passport js framework has 2 separeate libraries\n\n- Passport JS Library (main) - maintain session information for user authentication\n- strategy library - methodology for authenticate an user - passport-local, passport-facebook, passport-oauth2 etc.\n\n2. Login process handled by 2 steps: i) session management (Passport.js), ii) authentication (strategy)\n   `npm install passport-local`\n   `npm install passport-facebook`\n\n3. for managing session Passport.js library takes help from express-session library\n   `npm install passport express-session`\n\n4. source code\n\n- bootstrap the project\n\n  - installing \u0026 requiring packages\n    `npm install express nodemon dotenv mongoose ejs cors`\n  - creating server\n\n    ```js\n    //app.js\n    const express = require(\"express\");\n    const cors = require(\"cors\");\n    const ejs = require(\"ejs\");\n\n    const app = express();\n\n    app.set(\"view engine\", \"ejs\");\n    app.use(cors());\n    app.use(express.urlencoded({ extended: true }));\n    app.use(express.json());\n\n    module.exports = app;\n\n    //index.js\n    const app = require(\"./app\");\n    const PORT = 4000;\n    app.listen(PORT, () =\u003e {\n      console.log(`app is running at http://localhost:${PORT}`);\n    });\n    ```\n\n  - creating routes including try,catch\n\n    ```js\n    // base url\n    app.get(\"/\", (req, res) =\u003e {\n      res.render(\"index\");\n    });\n\n    // register routes\n    app.get(\"/register\", (req, res) =\u003e {\n      res.render(\"register\");\n    });\n\n    app.post(\"/register\", (req, res) =\u003e {\n      try {\n        res.status(201).send(\"user is registered\");\n      } catch (error) {\n        req.status(500).send(error.message);\n      }\n    });\n\n    // login routes\n    app.get(\"/login\", (req, res) =\u003e {\n      res.render(\"login\");\n    });\n\n    app.post(\"/login\", (req, res) =\u003e {\n      try {\n        res.status(201).send(\"user is logged in\");\n      } catch (error) {\n        req.status(500).send(error.message);\n      }\n    });\n\n    // logout routes\n    app.get(\"/logout\", (req, res) =\u003e {\n      res.redirect(\"/\");\n    });\n\n    // profile protected routes\n    app.get(\"/profile\", (req, res) =\u003e {\n      res.render(\"profile\");\n    });\n    ```\n\n  - creating ejs files\n\n    - create layout\n\n      ```html\n      \u003c!-- views/layout/header.ejs --\u003e\n      \u003c!DOCTYPE html\u003e\n      \u003chtml lang=\"en\"\u003e\n        \u003chead\u003e\n          \u003cmeta charset=\"UTF-8\" /\u003e\n          \u003cmeta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" /\u003e\n          \u003cmeta\n            name=\"viewport\"\n            content=\"width=device-width, initial-scale=1.0\"\n          /\u003e\n          \u003ctitle\u003eDocument\u003c/title\u003e\n        \u003c/head\u003e\n        \u003cbody\u003e\n          \u003cheader\u003e\n            \u003cnav\u003e\n              \u003ca href=\"/\"\u003eHome\u003c/a\u003e\n              \u003ca href=\"/register\"\u003eRegister\u003c/a\u003e\n              \u003ca href=\"/login\"\u003eLogin\u003c/a\u003e\n              \u003ca href=\"/profile\"\u003eProfile\u003c/a\u003e\n              \u003ca href=\"/logout\"\u003eLogout\u003c/a\u003e\n            \u003c/nav\u003e\n          \u003c/header\u003e\n        \u003c/body\u003e\n      \u003c/html\u003e\n\n      \u003c!-- views/layout/footer.ejs --\u003e\n          \u003cfooter\u003e\n            \u003cp\u003ecopyright by Rahatul Rabbi\u003c/p\u003e\n          \u003c/footer\u003e\n        \u003c/body\u003e\n      \u003c/html\u003e\n      ```\n\n    - create pages\n\n      ```html\n      \u003c!-- views/index.ejs --\u003e\n      \u003c%-include(\"layout/header\")%\u003e\n      \u003cmain\u003e\n        \u003ch1\u003eHome Page\u003c/h1\u003e\n      \u003c/main\u003e\n      \u003c%-include(\"layout/footer\")%\u003e\n\n      \u003c!-- views/register.ejs --\u003e\n      \u003c%-include(\"layout/header\")%\u003e\n      \u003cmain\u003e\n        \u003ch1\u003eRegister Page\u003c/h1\u003e\n        \u003cform action=\"/register\" method=\"post\"\u003e\n          \u003cdiv\u003e\n            \u003clabel for=\"username\"\u003eusername: \u003c/label\u003e\n            \u003cinput type=\"text\" id=\"username\" name=\"username\" /\u003e\n          \u003c/div\u003e\n          \u003cbr /\u003e\n          \u003cdiv\u003e\n            \u003clabel for=\"password\"\u003epassword: \u003c/label\u003e\n            \u003cinput type=\"password\" id=\"password\" name=\"password\" /\u003e\n          \u003c/div\u003e\n          \u003cbr /\u003e\n          \u003cbutton type=\"submit\"\u003eRegister\u003c/button\u003e\n        \u003c/form\u003e\n      \u003c/main\u003e\n      \u003c%-include(\"layout/footer\")%\u003e\n\n      \u003c!-- views/login.ejs --\u003e\n      \u003c%-include(\"layout/header\")%\u003e\n      \u003cmain\u003e\n        \u003ch1\u003eLogin Page\u003c/h1\u003e\n        \u003cform action=\"/register\" method=\"post\"\u003e\n          \u003cdiv\u003e\n            \u003clabel for=\"username\"\u003eusername: \u003c/label\u003e\n            \u003cinput type=\"text\" id=\"username\" name=\"username\" /\u003e\n          \u003c/div\u003e\n          \u003cbr /\u003e\n          \u003cdiv\u003e\n            \u003clabel for=\"password\"\u003epassword: \u003c/label\u003e\n            \u003cinput type=\"password\" id=\"password\" name=\"password\" /\u003e\n          \u003c/div\u003e\n          \u003cbr /\u003e\n          \u003cbutton type=\"submit\"\u003eLogin\u003c/button\u003e\n        \u003c/form\u003e\n      \u003c/main\u003e\n      \u003c%-include(\"layout/footer\")%\u003e\n\n      \u003c!-- views/profile.ejs --\u003e\n      \u003c%-include(\"layout/header\")%\u003e\n      \u003cmain\u003e\n        \u003ch1\u003eProfile Page\u003c/h1\u003e\n      \u003c/main\u003e\n      \u003c%-include(\"layout/footer\")%\u003e\n      ```\n\n- create model and connect to mongodb\n\n  ```js\n  // models/user.model.js\n  const mongoose = require(\"mongoose\");\n  const userSchema = mongoose.Schema({\n    username: {\n      type: String,\n      require: true,\n      unique: true,\n    },\n    password: {\n      type: String,\n      require: true,\n    },\n  });\n  const User = mongoose.model(\"User\", userSchema);\n  module.exports = User;\n\n  // config/database.js\n  const mongoose = require(\"mongoose\");\n  mongoose\n    .connect(\"mongodb://localhost:27017/passportDB\")\n    .then(() =\u003e {\n      console.log(\"db is connected\");\n    })\n    .catch((error) =\u003e {\n      console.log(error.message);\n    });\n\n  // app.js\n  require(\"./config/database\");\n  ```\n\n- register an user\n\n```js\n//app.js\nconst User = require(\"./models/user.model\");\n\napp.post(\"/register\", async (req, res) =\u003e {\n  try {\n    const user = await User.findOne({ username: req.body.username });\n    if (user) return res.status(400).send(\"User already exist\");\n    const newUser = new User(req.body);\n    await newUser.save();\n    res.status(201).send(newUser);\n  } catch (error) {\n    req.status(500).send(error.message);\n  }\n});\n```\n\n- encrypt the user password using bcrypt hashing+salting\n  `npm install bcrypt`\n\n```js\n//app.js\nconst bcrypt = require(\"bcrypt\");\nconst saltRounds = 10;\n\napp.post(\"/register\", async (req, res) =\u003e {\n  try {\n    const user = await User.findOne({ username: req.body.username });\n    if (user) return res.status(400).send(\"User already exist\");\n\n    bcrypt.hash(req.body.password, saltRounds, async (err, hash) =\u003e {\n      const newUser = new User({\n        username: req.body.username,\n        password: hash,\n      });\n      await newUser.save();\n      res.redirect(\"/login\");\n    });\n  } catch (error) {\n    res.status(500).send(error.message);\n  }\n});\n```\n\n- create and add session\n  `npm install passport express-session connect-mongo`\n\n  ```js\n  //Import the main Passport and Express-Session library\n  const passport = require(\"passport\");\n  const session = require(\"express-session\");\n  // for storing session in different collection\n  const MongoStore = require(\"connect-mongo\");\n\n  // setting middleware\n  app.set(\"trust proxy\", 1); // trust first proxy\n  app.use(\n    session({\n      secret: \"keyboard cat\",\n      resave: false,\n      saveUninitialized: true,\n      store: MongoStore.create({\n        mongoUrl: \"mongodb://localhost:27017/testPassportDB\",\n        collectionName: \"sessions\",\n      }),\n      // cookie: { secure: true },\n      // cookie: { maxAge: 1000 * 60 * 60 * 24 },\n    })\n  );\n\n  app.use(passport.initialize());\n  // init passport on every route call.\n  app.use(passport.session());\n  // allow passport to use \"express-session\".\n  ```\n\n- set passport-local configuration\n  `npm install passport-local`\n\n  ```js\n  // passport.js\n  const User = require(\"../model/user.model\");\n  const passport = require(\"passport\");\n  const bcrypt = require(\"bcrypt\");\n  const LocalStrategy = require(\"passport-local\").Strategy;\n  passport.use(\n    new LocalStrategy(async function (username, password, done) {\n      try {\n        const user = await User.findOne({ username: username });\n        // wrong username\n        if (!user) {\n          return done(null, false, { message: \"Incorrect Username\" });\n        }\n\n        // wrong password\n        if (!bcrypt.compare(password, user.password)) {\n          return done(null, false, { message: \"Incorrect Password\" });\n        }\n\n        // if user found\n        return done(null, user);\n      } catch (error) {\n        return done(error);\n      }\n    })\n  );\n\n  // create session id\n  // whenever we login it creares user id inside session\n  passport.serializeUser((user, done) =\u003e {\n    done(null, user.id);\n  });\n\n  // find session info using session id\n  passport.deserializeUser(async (id, done) =\u003e {\n    try {\n      const user = await User.findById(id);\n      done(null, user);\n    } catch (error) {\n      done(error, false);\n    }\n  });\n  ```\n\n- authenticate user using passport-local\n\n```js\n// app.js\n// login using passport-local strategy\nconst checkLoggedIn = (req, res, next) =\u003e {\n  if (req.isAuthenticated()) {\n    return res.redirect(\"/profile\");\n  }\n  next();\n};\n\n// login routes\napp.get(\"/login\", checkLoggedIn, (req, res) =\u003e {\n  try {\n    res.render(\"login\");\n  } catch (error) {\n    req.status(500).send(error.message);\n  }\n});\n\n// register routes\napp.get(\"/register\", checkLoggedIn, (req, res) =\u003e {\n  res.render(\"register\");\n});\n```\n\n- check user is already logged in or not\n\n  ```js\n  const checkAuthenticated = (req, res, next) =\u003e {\n    if (req.isAuthenticated()) {\n      return next();\n    }\n    res.redirect(\"/login\");\n  };\n\n  // profile protected routes\n  app.get(\"/profile\", checkAuthenticated, (req, res) =\u003e {\n    res.render(\"profile\");\n  });\n  ```\n\n- logout route setup\n  ```js\n  // logout routes\n  app.get(\"/logout\", (req, res) =\u003e {\n    try {\n      req.logout((err) =\u003e {\n        if (err) {\n          return next(err);\n        }\n        res.redirect(\"/\");\n      });\n    } catch (error) {\n      req.status(500).send(error.message);\n    }\n  });\n  ```\n- finally the entire app.js\n\n  ```js\n  const express = require(\"express\");\n  const cors = require(\"cors\");\n  const ejs = require(\"ejs\");\n  const bcrypt = require(\"bcrypt\");\n  const saltRounds = 10;\n  const passport = require(\"passport\");\n  const session = require(\"express-session\");\n  // for storing session in different collection\n  const MongoStore = require(\"connect-mongo\");\n\n  require(\"./config/database\");\n  require(\"./config/passport\");\n\n  const User = require(\"./model/user.model\");\n\n  const app = express();\n\n  app.set(\"view engine\", \"ejs\");\n  app.use(cors());\n  app.use(express.urlencoded({ extended: true }));\n  app.use(express.json());\n\n  // setting middleware\n  app.set(\"trust proxy\", 1); // trust first proxy\n  app.use(\n    session({\n      secret: \"keyboard cat\",\n      resave: false,\n      saveUninitialized: true,\n      store: MongoStore.create({\n        mongoUrl: \"mongodb://localhost:27017/passportDB\",\n        collectionName: \"sessions\",\n      }),\n      // cookie: { maxAge: 1000 * 60 * 60 * 24 },\n    })\n  );\n\n  app.use(passport.initialize());\n  // init passport on every route call.\n  app.use(passport.session());\n  // allow passport to use \"express-session\".\n\n  const checkLoggedIn = (req, res, next) =\u003e {\n    if (req.isAuthenticated()) {\n      return res.redirect(\"/profile\");\n    }\n    next();\n  };\n\n  // base url\n  app.get(\"/\", (req, res) =\u003e {\n    res.render(\"index\");\n  });\n\n  // register routes\n  app.get(\"/register\", checkLoggedIn, (req, res) =\u003e {\n    res.render(\"register\");\n  });\n\n  app.post(\"/register\", async (req, res) =\u003e {\n    try {\n      const user = await User.findOne({ username: req.body.username });\n      if (user) return res.status(400).send(\"User already exist\");\n\n      bcrypt.hash(req.body.password, saltRounds, async (err, hash) =\u003e {\n        const newUser = new User({\n          username: req.body.username,\n          password: hash,\n        });\n        await newUser.save();\n        res.redirect(\"/login\");\n      });\n    } catch (error) {\n      res.status(500).send(error.message);\n    }\n  });\n\n  // login routes\n  app.get(\"/login\", checkLoggedIn, (req, res) =\u003e {\n    res.render(\"login\");\n  });\n\n  app.post(\n    \"/login\",\n    passport.authenticate(\"local\", { successRedirect: \"/profile\" })\n  );\n\n  // logout routes\n  app.get(\"/logout\", (req, res) =\u003e {\n    try {\n      req.logout((err) =\u003e {\n        if (err) {\n          return next(err);\n        }\n        res.redirect(\"/\");\n      });\n    } catch (error) {\n      req.status(500).send(error.message);\n    }\n  });\n\n  const checkAuthenticated = (req, res, next) =\u003e {\n    if (req.isAuthenticated()) {\n      return next();\n    }\n    res.redirect(\"/login\");\n  };\n\n  // profile protected routes\n  app.get(\"/profile\", checkAuthenticated, (req, res) =\u003e {\n    res.render(\"profile\");\n  });\n\n  module.exports = app;\n  ```\n\n## Level 6: Google OAuth with passport session based\n\n- setup database name in db and also for session\n- change in schema\n\n  ```js\n  const mongoose = require(\"mongoose\");\n  const userSchema = mongoose.Schema({\n    username: {\n      type: String,\n      require: true,\n      unique: true,\n    },\n    googleId: {\n      type: String,\n      require: true,\n    },\n  });\n\n  const User = mongoose.model(\"User\", userSchema);\n  module.exports = User;\n  ```\n\n- inside login ejs add\n  ` \u003ca href=\"/auth/google\"\u003eLogin with Google\u003c/a\u003e`\n\n- create dynamic user name in profile page `Welcome \u003c%=username%\u003e`\n\n- configure strategy\n\n  - we need client id, client secret\n\n  ```js\n  // passport.js\n  require(\"dotenv\").config();\n  const User = require(\"../models/user.model\");\n  const passport = require(\"passport\");\n\n  const GoogleStrategy = require(\"passport-google-oauth20\").Strategy;\n\n  passport.use(\n    new GoogleStrategy(\n      {\n        clientID: process.env.GOOGLE_CLIENT_ID,\n        clientSecret: process.env.GOOGLE_CLIENT_SECRET,\n        callbackURL: \"http://localhost:5000/auth/google/callback\",\n      },\n      function (accessToken, refreshToken, profile, cb) {\n        User.findOne({ googleId: profile.id }, (err, user) =\u003e {\n          if (err) return cb(err, null);\n\n          // not a user; so create a new user with new google id\n          if (!user) {\n            let newUser = new User({\n              googleId: profile.id,\n              username: profile.displayName,\n            });\n            newUser.save();\n            return cb(null, newUser);\n          } else {\n            // if we find an user just return return user\n            return cb(null, user);\n          }\n        });\n      }\n    )\n  );\n\n  // create session id\n  // whenever we login it creares user id inside session\n  passport.serializeUser((user, done) =\u003e {\n    done(null, user.id);\n  });\n\n  // find session info using session id\n  passport.deserializeUser(async (id, done) =\u003e {\n    try {\n      const user = await User.findById(id);\n      done(null, user);\n    } catch (error) {\n      done(error, false);\n    }\n  });\n\n  // app.js\n  const express = require(\"express\");\n  const cors = require(\"cors\");\n  const ejs = require(\"ejs\");\n  const app = express();\n  require(\"./config/database\");\n  require(\"dotenv\").config();\n  require(\"./config/passport\");\n  const User = require(\"./models/user.model\");\n\n  const passport = require(\"passport\");\n  const session = require(\"express-session\");\n  const MongoStore = require(\"connect-mongo\");\n\n  app.set(\"view engine\", \"ejs\");\n  app.use(cors());\n  app.use(express.urlencoded({ extended: true }));\n  app.use(express.json());\n\n  app.set(\"trust proxy\", 1); // trust first proxy\n  app.use(\n    session({\n      secret: \"keyboard cat\",\n      resave: false,\n      saveUninitialized: true,\n      store: MongoStore.create({\n        mongoUrl: process.env.MONGO_URL,\n        collectionName: \"sessions\",\n      }),\n      // cookie: { secure: true },\n    })\n  );\n\n  app.use(passport.initialize());\n  app.use(passport.session());\n\n  // base url\n  app.get(\"/\", (req, res) =\u003e {\n    res.render(\"index\");\n  });\n\n  const checkLoggedIn = (req, res, next) =\u003e {\n    if (req.isAuthenticated()) {\n      return res.redirect(\"/profile\");\n    }\n    next();\n  };\n\n  // login : get\n  app.get(\"/login\", checkLoggedIn, (req, res) =\u003e {\n    res.render(\"login\");\n  });\n\n  app.get(\n    \"/auth/google\",\n    passport.authenticate(\"google\", { scope: [\"profile\"] })\n  );\n\n  app.get(\n    \"/auth/google/callback\",\n    passport.authenticate(\"google\", {\n      failureRedirect: \"/login\",\n      successRedirect: \"/profile\",\n    }),\n    function (req, res) {\n      // Successful authentication, redirect home.\n      res.redirect(\"/\");\n    }\n  );\n\n  const checkAuthenticated = (req, res, next) =\u003e {\n    if (req.isAuthenticated()) {\n      return next();\n    }\n    res.redirect(\"/login\");\n  };\n\n  // profile protected route\n  app.get(\"/profile\", checkAuthenticated, (req, res) =\u003e {\n    res.render(\"profile\", { username: req.user.username });\n  });\n\n  // logout route\n  app.get(\"/logout\", (req, res) =\u003e {\n    try {\n      req.logout((err) =\u003e {\n        if (err) {\n          return next(err);\n        }\n        res.redirect(\"/\");\n      });\n    } catch (error) {\n      res.status(500).send(error.message);\n    }\n  });\n\n  module.exports = app;\n  ```\n\n## Level 7: passport-jwt (token based)\n\n- how token based works\n  - user register using username, password to the server -\u003e server creates a token for the user -\u003e so next time when user make any request server give access by validating the given token\n- folder and file structure\n  - server\n    - models\n      - user.model.js\n    - config\n    - app.js\n    - index.js\n    - .env\n    - .gitignore\n- initialize npm and install package\n  `npm init -y \u0026\u0026 npm install express nodemon cors dotenv bcrypt mongoose`\n- test\n\n## Follow Me\n\n\u003cimg src =\"https://www.edigitalagency.com.au/wp-content/uploads/Facebook-logo-blue-circle-large-transparent-png.png\" height=\"15px\" width=\"15px\"/\u003e [Facebook](http://facebook.com/learnwithfair), \u003cimg src =\"https://image.similarpng.com/very-thumbnail/2021/10/Youtube-icon-design-on-transparent-background-PNG.png\" height=\"20px\" width=\"20px\"/\u003e [Youtube](http://youtube.com/@learnwithfair), \u003cimg src =\"https://i.pinimg.com/originals/fa/ea/02/faea02f412415becfb4939d2b6431c28.jpg\" height=\"15px\" width=\"15px\"/\u003e [Instagram](http://instagram.com/learnwithfair)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flearnwithfair%2Fweb-authentication-documentation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flearnwithfair%2Fweb-authentication-documentation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flearnwithfair%2Fweb-authentication-documentation/lists"}