27
loading...
This website collects cookies to deliver better user experience
local
authentication.npx create-nuxt-app front
yarn add --exact @nuxtjs/auth-next
yarn add @nuxtjs/axios
npm install --save-exact @nuxtjs/auth-next
npm install @nuxtjs/axios
{
modules: [
'@nuxtjs/axios',
'@nuxtjs/auth-next'
],
auth: {
// Options
}
}
auth: {
strategies: {
local: {
// scheme: "refresh",
token: {
property: "token", //property name that the Back-end sends for you as a access token for saving on localStorage and cookie of user browser
global: true,
required: true,
type: "Bearer"
},
user: {
property: "user",
autoFetch: true
},
// refreshToken: { // it sends request automatically when the access token expires, and its expire time has set on the Back-end and does not need to we set it here, because is useless
// property: "refresh_token", // property name that the Back-end sends for you as a refresh token for saving on localStorage and cookie of user browser
// data: "refresh_token", // data can be used to set the name of the property you want to send in the request.
// },
endpoints: {
login: { url: "/api/auth/login", method: "post" },
// refresh: { url: "/api/auth/refresh-token", method: "post" },
logout: false, // we don't have an endpoint for our logout in our API and we just remove the token from localstorage
user: { url: "/api/auth/user", method: "get" }
}
}
}
},
axios: {
baseURL: "http://localhost:8080" // here set your API url
},
refresh
endpoint and change it to the right endpoint which your back-end gave you and also you should uncomment these refreshToken
object and also scheme: refresh
/components/Auth/Login/index.vue
<template>
<div>
<form @submit.prevent="login">
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input
type="email"
class="form-control"
id="email"
v-model="loginData.email"
aria-describedby="emailHelp"
/>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input
type="password"
v-model="loginData.password"
class="form-control"
id="password"
/>
</div>
<button type="submit" class="btn btn-primary w-100">login</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
loginData: {
email: "",
password: ""
}
};
},
methods: {
async login() {
try {
let response = await this.$auth.loginWith("local", {
data: this.loginData
});
this.$router.push("/");
console.log(response);
} catch (err) {
console.log(err);
}
}
}
};
</script>
<style></style>
/components/Auth/Register/index.vue
<template>
<div>
<form @submit.prevent="register">
<div class="mb-3">
<label for="fullname" class="form-label">Full Name</label>
<input
type="text"
v-model="registerData.fullname"
class="form-control"
id="fullname"
/>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input
type="email"
class="form-control"
id="email"
v-model="registerData.email"
aria-describedby="emailHelp"
/>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input
type="password"
v-model="registerData.password"
class="form-control"
id="password"
/>
</div>
<button type="submit" class="btn btn-primary w-100">Register</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
registerData: {
fullname: "",
email: "",
password: ""
}
};
},
methods: {
async register() {
try {
const user = await this.$axios.$post("/api/auth/signin", {
fullname: this.registerData.fullname,
email: this.registerData.email,
password: this.registerData.password
});
console.log(user);
} catch (err) {
console.log(err);
}
}
}
};
</script>
<style></style>
/components/Home/index.vue
<template>
<div>
<h2>You're in home page</h2>
</div>
</template>
<script>
export default {};
</script>
<style></style>
/components/User/index.vue
<template>
<div>
Hello dear <b style="color:red">{{ getUserInfo.fullname }}</b> you're in
profile page
<hr />
This is your information:
<br /><br />
<table class="table">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">FullName</th>
<th scope="col">Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ getUserInfo.id }}</td>
<td>{{ getUserInfo.fullname }}</td>
<td>{{ getUserInfo.email }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
computed: {
getUserInfo() {
return this.$store.getters.getUserInfo;
}
}
};
</script>
<style></style>
/components/Layouts/Header/index.vue
<template>
<div>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<nuxt-link class="navbar-brand" to="/">Navbar</nuxt-link>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<template v-if="!isAuthenticated">
<li class="nav-item">
<nuxt-link
class="nav-link active"
aria-current="page"
to="/auth/login"
>Login</nuxt-link
>
</li>
<li class="nav-item">
<nuxt-link
class="nav-link active"
aria-current="page"
to="/auth/register"
>Register</nuxt-link
>
</li>
</template>
<template v-else>
<li class="nav-item" @click="logout">
<nuxt-link class="nav-link active" aria-current="page" to="#"
>Logout</nuxt-link
>
</li>
<li>
<nuxt-link
class="nav-link active"
aria-current="page"
to="/profile"
>
Profile
</nuxt-link>
</li>
</template>
</ul>
</div>
</div>
</nav>
</div>
</template>
<script>
export default {
methods: {
async logout() {
await this.$auth.logout(); // this method will logout the user and make token to false on the local storage of the user browser
}
},
computed: {
isAuthenticated() {
return this.$store.getters.isAuthenticated; // it check if user isAuthenticated
}
}
};
</script>
<style></style>
/layouts/default.vue
<template>
<div>
<layouts-header />
<div class="container">
<br />
<Nuxt />
</div>
</div>
</template>
<script>
export default {};
</script>
<style>
@import url("https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.min.css");
</style>
/pages/index.vue
<template>
<div>
<home />
</div>
</template>
<script>
export default {};
</script>
/pages/auth/login/index.vue
<template>
<div>
<auth-login />
</div>
</template>
<script>
export default {};
</script>
<style></style>
/pages/auth/register/index.vue
<template>
<div>
<auth-register />
</div>
</template>
<script>
export default {};
</script>
<style></style>
/pages/profile/index.vue
<template>
<div>
<user />
</div>
</template>
<script>
export default {
middleware: "isAuthenticated" // it will use `isAuthenticated` middleware
};
</script>
<style></style>
export default function({ store, redirect }) {
if (!store.state.auth.loggedIn) {
return redirect("/auth/login");
}
}
export const getters = {
isAuthenticated(state) {
return state.auth.loggedIn; // auth object as default will be added in vuex state, when you initialize nuxt auth
},
getUserInfo(state) {
return state.auth.user;
}
};
npm init -y
npm install express body-parser bcryptjs jsonwebtoken mongoose
npm install --save-dev nodemon
it will add nodemon as a dev dependencynodemon.js root direcotry that you just made
{
"env": {
"MONGO_USER": "mohammadali", // your cluster name
"MONGO_PASS": "20212021", // your cluster password
"MONGO_DB": "auth" // your db name
}
}
on package.json will be on root directory add these lines of codes on scripts like as I did in below
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start-server": "node app.js",
"dev": "nodemon app.js"
},
app.js on root direcotry that you just made
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
// routes
const authRouter = require("./routes/authRouter");
const app = express();
app.use(bodyParser.json());
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"OPTIONS, GET, POST, PUT, PATCH, DELETE"
);
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
app.use("/api/auth/", authRouter);
app.use((error, req, res, next) => {
console.log(error);
const status = error.statusCode || 500;
const message = error.message;
const data = error.data;
res.status(status).json({ message: message, data: data });
});
// connect to db
const MONGOOSE_URI = `mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASS}@cluster0.4r3gv.mongodb.net/${process.env.MONGO_DB}`;
mongoose
.connect(MONGOOSE_URI)
.then((result) => {
app.listen(process.env.PORT || 8080);
})
.catch((err) => console.log(err));
/controllers/authController.js
const bcrypt = require("bcryptjs");
const userModel = require("../models/userModel");
const jwt = require("jsonwebtoken");
exports.postSignin = async (req, res, next) => {
const { fullname, email, password } = req.body;
try {
const exsitUser = await userModel.findOne({ email: email });
if (exsitUser) {
const error = new Error(
"Eamil already exist, please pick another email!"
);
res.status(409).json({
error: "Eamil already exist, please pick another email! ",
});
error.statusCode = 409;
throw error;
}
const hashedPassword = await bcrypt.hash(password, 12);
const user = new userModel({
fullname: fullname,
email: email,
password: hashedPassword,
});
const result = await user.save();
res.status(200).json({
message: "User created",
user: { id: result._id, email: result.email },
});
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};
let loadedUser;
exports.postLogin = async (req, res, next) => {
const { email, password } = req.body;
try {
const user = await userModel.findOne({ email: email });
if (!user) {
const error = new Error("user with this email not found!");
error.statusCode = 401;
throw error;
}
loadedUser = user;
const comparePassword = bcrypt.compare(password, user.password);
if (!comparePassword) {
const error = new Error("password is not match!");
error.statusCode = 401;
throw error;
}
const token = jwt.sign({ email: loadedUser.email }, "expressnuxtsecret", {
expiresIn: "20m", // it will expire token after 20 minutes and if the user then refresh the page will log out
});
res.status(200).json({ token: token });
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};
exports.getUser = (req, res, next) => { // this function will send user data to the front-end as I said above authFetch on the user object in nuxt.config.js will send a request and it will execute
res.status(200).json({
user: {
id: loadedUser._id,
fullname: loadedUser.fullname,
email: loadedUser.email,
},
});
};
/middleware/isAuth.js
const jwt = require("jsonwebtoken");
module.exports = (req, res, next) => {
const authHeader = req.get("Authorization");
if (!authHeader) {
const error = new Error("Not authenticated.");
error.statusCode = 401;
throw error;
}
const token = authHeader.split(" ")[1];
let decodedToken;
try {
decodedToken = jwt.verify(token, "expressnuxtsecret");
} catch (err) {
err.statusCode = 500;
throw err;
}
if (!decodedToken) {
const error = new Error("Not authenticated.");
error.statusCode = 401;
throw error;
}
req.userId = decodedToken.userId;
next();
};
/models/userModel.js
const express = require("express");
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema(
{
fullname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
},
{ timestamps: true }
);
module.exports = mongoose.model("User", UserSchema);
/routes/routes.js
const express = require("express");
const router = express.Router();
const authController = require("../controllers/authController");
router.post("/signin", authController.postSignin);
router.post("/login", authController.postLogin);
router.get("/user", authController.getUser);
module.exports = router;
27