# User Login

We'll need to...

1. Install dependencies, `passport` and `passport-local`
2. Configure Passport to use our user model
3. Initialize Passport to use our session module
4. Add login and logout functionality to the `auth` controller

## Passport and passport-local

From the [passport website](http://www.passportjs.org/)

> Passport is authentication middleware for Node.js. Extremely flexible and modular, Passport can be unobtrusively dropped in to any Express-based web application.

Passport has a lot of different strategies for authenticating users—github, linkedin, and more! (Passport website lists 502 different strategies!) We're using the Local strategy.

> This module lets you authenticate using a username and password in your Node.js applications. By plugging into Passport, local authentication can be easily and unobtrusively integrated into any application or framework that supports Connect-style middleware, including Express.

## Install passport and passport-local

We'll use Passport in order to provide login functionality, and `passport-local` in order to provide local user authentication.

```
npm i passport passport-local
```

## Configure Passport to use our user model

Create the Passport configuration inside of the config folder. This will be a javascript file

```
touch config/ppConfig.js
```

**config/ppConfig.js**

```javascript
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const db = require('../models');

/*
 * Passport "serializes" objects to make them easy to store, converting the
 * user to an identifier (id)
 */
passport.serializeUser((user, cb) => {
  cb(null, user.id);
});

/*
 * Passport "deserializes" objects by taking the user's serialization (id)
 * and looking it up in the database
 */
passport.deserializeUser((id, cb) => {
  db.user.findByPk(id).then(user => {
    cb(null, user);
  }).catch(cb);
});

/*
 * This is Passport's strategy to provide local authentication. We provide the
 * following information to the LocalStrategy:
 *
 * Configuration: An object of data to identify our authentication fields, the
 * username and password
 *
 * Callback function: A function that's called to log the user in. We can pass
 * the email and password to a database query, and return the appropriate
 * information in the callback. Think of "cb" as a function that'll later look
 * like this:
 *
 * login(error, user) {
 *   // do stuff
 * }
 *
 * We need to provide the error as the first argument, and the user as the
 * second argument. We can provide "null" if there's no error, or "false" if
 * there's no user.
 */
passport.use(new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password'
}, (email, password, cb) => {
  db.user.findOne({ 
    where: { email }
  }).then(user => {
    if (!user || !user.validPassword(password)) {
      cb(null, false);
    } else {
      cb(null, user);
    }
  }).catch(cb);
}));

// export the Passport configuration from this module
module.exports = passport;
```

## Initialize Passport to use our session module

Now that we've created the configuration, we need to make our app *aware of its existence*. This can be done by requiring the configuration and including it as middleware.

**index.js**

```javascript
// require the configuration at the top of the file
const passport = require('./config/ppConfig');

// initialize the passport configuration and session as middleware
app.use(passport.initialize());
app.use(passport.session());
```

**IMPORTANT NOTE:** You must include the passport configuration **below your session configuration.** This ensures that Passport is aware that the session module exists.

## Add login and logout functionality

> Before continuing, verify that this test is passing
>
> **Auth Controller - GET /auth/login - should return a 200 response**

### Login

Luckily, all of that configuration and middleware means a straightforward login route. Let's go ahead and add the POST route for login.

**controllers/auth.js**

```javascript
// require the passport configuration at the top of the file
const passport = require('../config/ppConfig');

router.post('/login', passport.authenticate('local', {
  successRedirect: '/',
  failureRedirect: '/auth/login'
}));
```

> This should pass the following tests
>
> **Auth Controller - POST /auth/login - should redirect to / on success**
>
> **Auth Controller - POST /auth/login - should redirect to /auth/login on failure**

### Login after Signup

Ideally, we want to already be logged in after signup. We can modify the signup route to call the `passport.authenticate` function again. Note that we'll need to call it as an IIFE, passing the request and response.

**controllers/auth.js**

```javascript
router.post('/signup', (req, res) => {
  db.user.findOrCreate({
    where: {
      email: req.body.email
    }, defaults: {
      name: req.body.name,
      password: req.body.password
    }
  }).then(([user, created]) => {
    if (created) {
      console.log('user created');
      passport.authenticate('local', {
        successRedirect: '/',
      })(req, res);
    } else {
      console.log('email already exists');
      res.redirect('/auth/signup');
    }
  }).catch(err => {
    console.log('💩 Error occured finding or creating user');
    console.log(err);
    res.redirect('/auth/signup');
  });
});
```

### Logout

Including the Passport configuration in our app means that logging out is really really easy. You can now call a function attached to `req` to log out. Let's implement the final route.

**controllers/auth.js**

```javascript
router.get('/logout', (req, res) => {
  req.logout();
  res.redirect('/');
});
```

> This should pass the following test
>
> **Auth Controller - GET /auth/logout - should redirect to /**

## Login/Logout Finished

Congrats, your login/logout functionality should be finished! Verify by running the tests. You should have 17 passing and only one failing.

```
npm test
```

Now for one more section...


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tmdarneille.gitbook.io/seirfx/unit-2/express-auth/practice/05loginuser.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
