Youcef Madadi
Web and game development teacher
Chapter 6 : REST TO API AUTHENTICATION
Authentication Introduction
Authorization Introduction
Types of Authentications
Hashing the password
Setting log/sign - in routes
Setting JWT
Creating Authorization middleware
What is Authentication ?
Authentication is the process of verifying a user’s identification through the acquisition of credentials and using those credentials to confirm the user’s identity.
What is Authorization?
Authorization is the process of allowing authenticated users access to resources by determining whether they have system access permissions. By giving or denying specific licenses to an authenticated user, authorization enables you to control access privileges.
What are the types of Authentications ?
API Keys Authentication
Basic Authentication
Bearer Authentication
OAuth 2.0
OpenID Connect Discovery
Cookie Authentication
API Keys Authentication
Some APIs use API keys for authorization. An API key is a token that a client provides when making API calls.
The key can be sent in the query string :
GET /something?api_key=abcdef12345
As a request header
GET /something HTTP/1.1
X-API-Key: abcdef12345
As a cookie
GET /something HTTP/1.1
Cookie: X-API-KEY=abcdef12345
Basic Authentication
Basic authentication is a simple authentication scheme built into the HTTP protocol. The client sends HTTP requests with the Authorization header that contains the word Basic word followed by a space and a base64-encoded string username:password.
Authorization: Basic ZGVtbzpwQDU1dzByZA==
Bearer authentication
Bearer authentication (also called token authentication) is an HTTP authentication scheme that involves security tokens called bearer tokens. The bearer token is a cryptic string, usually generated by the server in response to a login request. The client must send this token in the Authorization header when making requests to protected resources:
Authorization: Bearer <token>
Why hashing passwords
For security reasons, you may want to store passwords in hashed form. This guards against the possibility that someone who gains unauthorized access to the database can retrieve the passwords of every user in the system. Hashing performs a one-way transformation on a password, turning the password into another String, called the hashed password.
How to hash passwords in Node?
> npm i bcrypt
userSchema.pre("save", async function (next) {
try {
if (this.isModified("password"))
this.password = await bcrypt.hash(this.password, 10);
next();
} catch (e) {
next(e);
}
});
const bcrypt = require("bcrypt");
Sign up route
app.post("/signup", async (req, res) => {
const { email, username, first_Name, last_Name, password } = req.body;
try {
const user = await User.create({ email, username, first_Name, last_Name, password });
res.json(user); // create auth token
} catch (e) {
res.json({ error: e.message });
}
});
Sign in route (log in)
app.post("/login", async (req, res) => {
const { username, password } = req.body;
try {
const user = await User.findOne({ username });
if (!user) throw new Error("Couldn't find a user using this username");
if (!(await user.comparePasswords(password))) throw new Error("Wrong password");
res.json(user); // create auth token
} catch (e) {
res.json({ error: e.message });
}
});
Password comparation Middleware
userSchema.methods.comparePasswords = async function (candidatePass, next) {
try {
return await bcrypt.compare(candidatePass, this.password);
} catch (e) {
next(e);
}
};
What is JWT ?
JSON Web Token is a proposed Internet standard for creating data with optional signature and/or optional encryption whose payload holds JSON that asserts some number of claims. The tokens are signed either using a private secret or a public/private key.
How to implement JWT?
> npm i jsonwebtoken
userSchema.methods.insertToken = function (token) {
let user = this.toObject();
delete user.password;
user.token = jwt.sign(
{ id: user._id, username: user.username },
process.env.SECRET_KEY, {
expiresIn: "100h",
});
return user;
};
const jwt = require("jsonwebtoken");
Use Token insertion
res.json(user.insertToken());
Replace in Sing in/up
res.json(user);
BY
Check user is logged in
async function isLoggedin(req, res, next) {
if (!req.headers.authorization) return res.status(400).send("No authorization's token");
req.token = req.headers.authorization.split(" ")[1];
try {
let decoded = jwt.verify(req.token, process.env.SECRET_KEY);
req.user = await User.findById(decoded.id).select("-password");
console.log(req.user);
next();
} catch (e) {
switch (e.constructor) {
case jwt.TokenExpiredError:
return res.send("Expired Token");
case jwt.JsonWebTokenError:
return res.send("Invalid Token");
}
}
}
Check user is an Admin
async function isAdmin(req, res, next) {
if (!req.user) return res.status(400).send("No authorization's token");
if (!req.user.isAdmin) return res.status(400).send("user is not an Admin");
next();
}
By Youcef Madadi