Skip to content

Commit

Permalink
fix(security): add basic auth to articles
Browse files Browse the repository at this point in the history
  • Loading branch information
HoseaCodes committed May 15, 2024
1 parent fb3aae9 commit b4e635d
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 26 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ See [wiki](https://github.com/HoseaCodes/Blog/wiki/Frontend) for details.

## Backend

### Security

#### Basic Auth

![Security](https://i.imgur.com/ZD1gtVH.png)


See [wiki](https://github.com/HoseaCodes/Blog/wiki/Backend) for details.

## Dev Ops
Expand Down
10 changes: 6 additions & 4 deletions routes/articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ import {
createComment,
deleteComment
} from '../controllers/comment.js';
import {nodecache} from '../utils/cache.js';
import { nodecache } from '../utils/cache.js';
import { basicAuth } from '../utils/auth.js';

const router = express.Router();
const commentRouter = express.Router({mergeParams: true});
router.use('/articles/:id/comments', commentRouter);

router.route('/articles')
.get(nodecache, getArticle)
.post(createArticle)
router
.route("/articles")
.get(basicAuth, nodecache, getArticle)
.post(basicAuth, createArticle);

router.route('/articles/:id')
.get(getArticleByID)
Expand Down
10 changes: 9 additions & 1 deletion src/API/ArticlesAPI.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState, useEffect } from 'react';
import axios from 'axios'
import { getBasicAuth } from '../Utils/helperFunctions';

function ArticlesAPI() {
const [articles, setArticles] = useState([])
Expand All @@ -9,7 +10,14 @@ function ArticlesAPI() {

useEffect(() => {
const getArticles = async () => {
const res = await axios.get(`/api/articles`)
const username = process.env.USERNAME || 'admin';
const password = process.env.PASSWORD || 'password';
const auth = getBasicAuth(username, password);
const res = await axios.get(`/api/articles`, {
headers: {
Authorization: auth,
}
});
setArticles(res.data.articles)
setResult(res.data.result)
}
Expand Down
15 changes: 13 additions & 2 deletions src/Pages/Articles/CreateArticle.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { articleTempltes } from "./ArticleTemplate";
import Preview from "../../Components/Article/Preview";
import AITemplate from "../../Components/OpenAI/AITemplate";
import { Button } from "../../Components/Button/Button";
import { sleep } from "../../Utils/helperFunctions";
import { sleep, getBasicAuth } from "../../Utils/helperFunctions";

function CreatArticle() {
const [markdown, setMarkdown] = useState(articleTempltes[3].markdown);
Expand Down Expand Up @@ -154,7 +154,18 @@ function CreatArticle() {
...article,
["slug"]: article.title.toLowerCase().replace(/ /g, "-"),
});
await axios.post("/api/articles", { ...article, images, ...user });
const username = process.env.USERNAME || "admin";
const password = process.env.PASSWORD || "password";
const auth = getBasicAuth(username, password);
await axios.post(
"/api/articles",
{ ...article, images, ...user },
{
headers: {
Authorization: auth,
},
},
);
setImages(false);
setArticle(initialState);
}
Expand Down
9 changes: 8 additions & 1 deletion src/Utils/helperFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,11 @@ const truncate = (str) => {
return str.length > 10 ? str.substring(0, 150) + "..." : str;
};

export { copyTextToClipboard, responsive, sleep, truncate };
const getBasicAuth = (username, password) => {
const encoded = btoa(`${username}:${password}`);
const auth = `Basic ${encoded}`;
return auth;
};


export { copyTextToClipboard, responsive, sleep, truncate, getBasicAuth };
59 changes: 41 additions & 18 deletions utils/auth.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,51 @@
import jwt from "jsonwebtoken";

const auth = (req, res, next) => {
try {
const token = req.header("Authorization");
if (!token)
return res.status(400).json({ msg: "Invalid Authentication - no token" });
try {
const token = req.header("Authorization");
if (!token)
return res.status(400).json({ msg: "Invalid Authentication - no token" });

jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if (err instanceof jwt.TokenExpiredError) {
return res
.status(400)
.json({ msg: "Token Expired Error", err});
return res.status(400).json({ msg: "Token Expired Error", err });
}
if (err)
return res
.status(400)
.json({ msg: "Invalid Authentication - invalid token"});

req.user = user;
next();
});
} catch (err) {
return res.status(500).json({ msg: err.message });
}
return res
.status(400)
.json({ msg: "Invalid Authentication - invalid token" });

req.user = user;
next();
});
} catch (err) {
return res.status(500).json({ msg: err.message });
}
};

export function basicAuth(req, res, next) {
const authheader = req.headers.authorization;
console.log({ authheader });
if (!authheader) {
res.setHeader("WWW-Authenticate", "Basic");
return res.status(401).json({ msg: "Unauthentication - Auth401" });
}

const auth = new Buffer.from(authheader.split(" ")[1], "base64")
.toString()
.split(":");

const user = auth[0];
const pass = auth[1];

if (user == "admin" && pass == "password") {
// If Authorized user

next();
} else {
res.setHeader("WWW-Authenticate", "Basic");
return res.status(401).json({ msg: "Unauthentication - Auth401" });
}
}

export default auth;

0 comments on commit b4e635d

Please sign in to comment.