You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6.9 KiB

MEAN Stack Auth

Create toggle to show app vs login/signup

index.html:

<section ng-if="ctrl.loggedInUser === false">
    <h2>Sign Up</h2>
    <form>
        Username: <input type="text" /><br/>
        Password: <input type="password" /><br/>
        <input type="submit" value="Sign Up">
    </form>
    <h2>Log In</h2>
    <form>
        Username: <input type="text" /><br/>
        Password: <input type="password" /><br/>
        <input type="submit" value="Log In">
    </form>
</section>
<section ng-if="ctrl.loggedInUser !== false">
    <!-- previous code: ul and form -->
</section>

app.js inside controller:

this.loggedInUser = false;

Make fake signup/login forms call angular methods

app.js:

this.signup = function(){
    this.loggedInUser = {
        username: 'Matthew'
    }
}

this.login = function(){
    this.loggedInUser = {
        username: 'matt'
    }
}

index.html:

<section ng-if="ctrl.loggedInUser === false">
    <form ng-submit="ctrl.signup()"><!-- add ng-submit -->
        Username: <input type="text" /><br/>
        Password: <input type="password" /><br/>
        <input type="submit" value="Sign Up">
    </form>
    <h2>Log In</h2>
    <form ng-submit="ctrl.login()"><!-- add ng-submit -->
        Username: <input type="text" /><br/>
        Password: <input type="password" /><br/>
        <input type="submit" value="Log In">
    </form>
</section>
<section ng-if="ctrl.loggedInUser !== false">
    <h2>Welcome {{ctrl.loggedInUser.username}}</h2>
    <!-- rest of code -->
</section>

Create user create route for api:

create controllers/users.js:

const express = require('express');
const router = express.Router();

router.post('/', (req, res) => {
    res.json(req.body);
});

module.exports = router;

server.js:

const usersController = require('./controllers/users.js');
app.use('/users', usersController);

Create User model

create models/users.js:

const mongoose = require('mongoose');

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

const User = mongoose.model('User', userSchema);

module.exports = User;

controllers/users.js:

const User = require('../models/users.js');

router.post('/', (req, res) => {
    User.create(req.body, (error, createdUser) => {
        res.json(createdUser);
    })
});

Add bcrypt to sign up

npm install bcrypt

controllers/users.js:

const bcrypt = require('bcrypt');
//...
router.post('/', (req, res) => {
    req.body.password = bcrypt.hashSync(req.body.password, bcrypt.genSaltSync(10));
    User.create(req.body, (error, createdUser) => {
        res.json(createdUser);
    })
});

Make request to create user api route in angular

index.html:

Username: <input type="text" ng-model="ctrl.signupUsername" /><br/>
Password: <input type="password" ng-model="ctrl.signupPassword"/><br/>

app.js:

this.signup = function(){
    $http({
        url:'/users',
        method:'POST',
        data: {
            username: this.signupUsername,
            password: this.signupPassword
        }
    }).then(function(response){
        controller.loggedInUser = response.data;
    })
}

Create session create route

create controllers/session.js:

const express = require('express');
const router = express.Router();
const User = require('../models/users.js');

router.post('/', (req, res) => {
    User.findOne({username:req.body.username}, (error, foundUser) => {
        res.json(foundUser)
    });
});

module.exports = router;

server.js:

const sessionController = require('./controllers/session.js');
app.use('/session', sessionController);

Check password

controllers/session.js:

const bcrypt = require('bcrypt');
//...
router.post('/', (req, res) => {
    User.findOne({username:req.body.username}, (error, foundUser) => {
        if(foundUser === null){
            res.json({
                message:'user not found',
            });
        } else {
            const doesPasswordMatch = bcrypt.compareSync(req.body.password, foundUser.password);
            if(doesPasswordMatch){
                res.json(foundUser)
            } else {
                res.json({
                    message:'user not found'
                });
            }
        }
    });
});

Integrate with Angular

<h2>Log In</h2>
<form ng-submit="ctrl.login()">
    Username: <input type="text" ng-model="ctrl.loginUsername"/><br/>
    Password: <input type="password" ng-model="ctrl.loginPassword"/><br/>
    <input type="submit" value="Log In">
</form>
this.login = function(){
    $http({
        url:'/session',
        method:'POST',
        data: {
            username: this.loginUsername,
            password: this.loginPassword
        }
    }).then(function(response){
        if(response.data.username){
            controller.loggedInUser = response.data;
        } else {
            controller.loginUsername = null;
            controller.loginPassword = null;
        }
    })
}

Set up sessions

npm install express-session

app.js:

const session = require('express-session');
//...
app.use(session({
    secret:'feedmeseymour',
    resave:false,
    saveUninitialized:false
}))

Set session on login

controllers/session.js:

const doesPasswordMatch = bcrypt.compareSync(req.body.password, foundUser.password);
if(doesPasswordMatch){
    req.session.user = foundUser; //add this line
    res.json(foundUser)
} else {
    res.json({
        message:'user not found'
    });
}

Set session on sign up

controllers/users.js:

User.create(req.body, (error, createdUser) => {
    req.session.user = createdUser; //add this line
    res.json(createdUser);
})

Test to see if user is logged in on page load

app.js:

// bottom of controller
this.getTodos();

$http({
    method:'GET',
    url:'/session'
}).then(function(response){
    console.log(response);
});

controllers/session.js:

router.get('/', (req, res) => {
    res.json(req.session.user);
})

Set session data in angular

app.js:

$http({
    method:'GET',
    url:'/session'
}).then(function(response){
    if(response.data.username){
        controller.loggedInUser = response.data;
    }
});

Log out functionality

controllers/session.js:

router.delete('/', (req, res) => {
    req.session.destroy(() => {
        res.json({
            destroyed:true
        });
    })
});

index.html (after welcome h2):

<button ng-click="ctrl.logout()">Log Out</button>

app.js:

this.logout = function(){
    $http({
        url:'/session',
        method:'DELETE'
    }).then(function(){
        controller.loggedInUser = false;
    })
}