My first system of authentification
- App
- Screenshots
- General info
- API
- Front
- Vuelidate
- Persisted-state
- Token in front
- Vuex
- VueRouter
- Technologies
- Pratice
- Difficulty
- Contact
This authentification app crypt password and use token identification
- You can create a user
- You can authentifiate a register user
- A register user can add, delete a contact and update the contact email
The password is hash with bcrypt.
When an user sign-in with the token (jwt) we give him acces to "dashboard", where he can manage his contact
Finally the user can logout (no acces to dashboard).
And the API end point are secure, check for token (authentification midlleware)
Aim of the project, create a system of authentification using SQL databe, b-crypt password, token identification, vue.js... 👩🎓 👨🎓
In the assets folder you can find a pdf with all the requierements ask.
node index.js
- crypt password:
// hash the password
let pass = bcrypt.hashSync(passwordNotHash, saltRounds);
This route is use to log in.
- handle email error:
if (!Array.isArray(results) || !results.length) {
console.log("email error");
// res.status(401).send("Sorry, email incorrect");
res.send("Sorry, email incorrect");
}
- token:
let token = jwt.sign(
{ email: email, name: name, id: id },
config.secret,
{
expiresIn: 86400,
}
);
- handle password error, check for token , finally send token and authorization:
bcrypt.compare(pass, hash, function(err, result) {
if (result == true) {
// get the decoded payload ignoring signature, no secretOrPrivateKey needed
var decoded = jwt.decode(token);
// get the decoded payload and header
var decoded = jwt.decode(token, { complete: true });
console.log("Header", decoded.header);
console.log("Payload", decoded.payload);
res.status(200).send({
auth: true,
token: token,
email: email,
name: name,
id: id,
});
} else {
console.log("pass error");
res.send("password error")
}
});
This route use sql request for return only the contacts who belongs to the connected user.
- mysql inner join.
/*********************** get contact whith the users ID same as id_user_affiliat ***************/
await app.get("/get-contacts/:id", auth, function(req, res) {
let userId = req.params.id;
let getAll = `SELECT contacts.name,contacts.email,contacts.id_user_affiliate
from users inner join contacts on users.id =
contacts.id_user_affiliate where users.id = ${connection.escape(userId)}`;
connection.query(getAll, function(err, results) {
if (err) throw err;
res.send(results);
});
});
const jwt = require('jsonwebtoken');
const config = require("../modules/config");
module.exports = (req, res, next) => {
try {
const token = req.headers.authorization.split(' ')[1];
const decodedToken = jwt.verify(token, config.secret);
console.log(decodedToken);
if (token>0) {
console.log(token);
} else {
next();
}
} catch {
res.status(401).json({
error: new Error('Invalid request!')
});
}
};
- then to import :
const auth = require("../middleware/auth");
- then to use: put "auth" just after your end point adress in your request.
await app.post("/add-new-contact", auth, function(req, res) {}
- post /add-new-contact ==> to add a new contact
- delete /users/:email ==> to delete an user with this email
- put /users/:email ==> update email of the contact
Vue.js Front-End.
- import vuelidate in the component "SignUpForm.vue".
//vuelidate
import { validationMixin } from "vuelidate";
import { required, minLength, email } from "vuelidate/lib/validators";
- in export default{}
mixins: [validationMixin],
- and:
// vuelidate
validations: {
form: {
email: {
required,
email: email,
},
name: {
required,
minLength: minLength(3),
},
password: {
required,
minLength: minLength(8),
},
},
},
- finnaly in methods{}
validateState(name) {
const { $dirty, $error } = this.$v.form[name];
return $dirty ? !$error : null;
},
- Example for email:
<b-form-group
id="input-group-1"
label="Email address:"
label-for="input-1"
invalid-feedback="Valid email is required">
- then
<b-form-input
:state="validateState('email')"
id="input-1"
v-model="$v.form.email.$model"
type="email"
placeholder="Enter email">
</b-form-input>
- tips: to reset vuelidate
this.$v.$reset()
- In the store import persistedstate
import createPersistedState from "vuex-persistedstate";
- And pass it in vuex store
let store = new Vuex.Store({
state: state,
mutations: mutations,
getters: getters,
actions: actions,
plugins: [createPersistedState()],
});
- During the axios post request in components "SignInForm.vue" stock the token in state (thank vuex)
if (response.data.auth == true) {
//to store in state the name, id and token
that.$store.dispatch("ADD_NAME", response.data.name);
that.$store.dispatch("ADD_ID", response.data.id);
that.$store.dispatch("ADD_TOKEN", response.data.token);
//change the route
that.$router.push("/Dashboard");
}
Example of actions and mutation to store the token in state:
- Actions:
ADD_TOKEN: (context, token) => {
context.commit("ADDED_TOKEN", token);
},
- Mutations
ADDED_TOKEN: (state, token) => {
state.token = token;
},
- State
let state = {
token: false,
name: "",
id: "",
contact: [],
};
- import the needed components:
import Dashboard from "../components/Dashboard";
import MyJumbotron from "../components/MyJumbotron";
import AuthStore from "../components/AuthStore";
- the routes:
const routes = [
{
path: "/dashboard",
name: "Dashboard",
component: Dashboard,
meta: { requiresAuth: true },
},
{ path: "/", name: "MyJumbotron", component: MyJumbotron },
];
- handle acces to the routes:
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some((record) => record.meta.requiresAuth);
if (requiresAuth == true && AuthStore.state.token) {
next();
} else if (requiresAuth == true && AuthStore.state.token == false) {
next({ name: "MyJumbotron" });
} else {
next();
}
});
- node.js
- mysql
- SQL database
- bcrypt
- jsonwebtoken
- express
- middleware
- vue.js
- vuex
- vueRouter
- vuelidate
- vue-axios
- vuex-persistedstate
- bootstrap-vue
- ...
- Node.js and many module
- Build an API
- work with express
- Database in mysql
- bcrypt (hash, salt)
- JWT (jsonwebtoken)
- How to make middleware and use them
- Vue.js and vue CLI to create the prject
- Vue-axios and how to connect back and front
- Vue-router and how to handle the acces of route
- Vuex and is fabulous store
- vuex-persistedstate
- Vuelidate so efficient
- Bootstrap.vue make life easier
- Postman for test the api
- ...
- How to make the project structure
- Sql syntax
- Create header for token
- Create midlleware for token
- Token in general (but finally it's ok)
- Vuelidate setting
- Handle the acces of routes in vueRouter ==> router.beforeEach()
Project is: Finish