diff --git a/src/controller/read.ts b/src/controller/read.ts index a51262d..356e8aa 100644 --- a/src/controller/read.ts +++ b/src/controller/read.ts @@ -54,12 +54,12 @@ router.post("/login/", loginSlowDown, async function postLogin(req: Request, res return createError(res, 422, "Body does not contain all expected information", next); } - cryptedPassword = crypt(req.body.password); + cryptedPassword = crypt(password); // Loop through all environment variables for (const key in process.env) { if (!key.startsWith('USER')) { continue; } - if (key.substring(5) == req.body.user && + if (key.substring(5) == user && process.env[key] == cryptedPassword) { validLogin = true; break; @@ -68,7 +68,7 @@ router.post("/login/", loginSlowDown, async function postLogin(req: Request, res // only allow test user in test environment - if (user == "test" && validLogin && process.env.NODE_ENV != "production") { + if (user == "test" && validLogin && process.env.NODE_ENV == "production") { validLogin = false; } @@ -76,7 +76,7 @@ router.post("/login/", loginSlowDown, async function postLogin(req: Request, res const token = createToken(req, res); res.json({ "token": token }); } else { - res.redirect("/read/login"); + return createError(res, 403, `invalid login credentials`, next); } }); }); @@ -102,7 +102,7 @@ function validateToken(req: Request, res: Response) { } catch (err) { res.status(401).send({ code: 123, message: 'Invalid or expired token.' }); } - console.log("payload: " + payload + " _ " + !!payload); + console.log("payload: " + JSON.stringify(payload) + " _ " + !!payload); // don't allow test user in production environment if (typeof payload == "object" && !!payload && payload.user == "test" && process.env.NODE_ENV == "production") { @@ -120,7 +120,8 @@ function createToken(req: Request, res: Response) { if (!key) { throw new Error('KEYA is not defined in the environment variables'); } const id = Math.random().toString(36).substring(2, 8); const payload = { - _id: id + _id: id, + user: req.body.user }; const token = jwt.sign(payload, key, { expiresIn: 60 * 1 }); res.locals.token = token; diff --git a/src/tests/integration.test.ts b/src/tests/integration.test.ts index 85c37e7..2d052fb 100644 --- a/src/tests/integration.test.ts +++ b/src/tests/integration.test.ts @@ -1,4 +1,5 @@ import axios, { AxiosError } from 'axios'; +import qs from 'qs'; import fs from "fs"; import path from "path"; @@ -41,6 +42,17 @@ function isInRange(actual: string | number, expected: number, range: number) { return Math.abs(Number(actual) - expected) <= range; } +async function verifiedRequest(url:string, token:string) { + const response = await axios({ + method: 'get', + url: url, + headers: { + 'Authorization': `Bearer ${token}`, + } + }); + return response; +} + describe('HEAD /write', () => { it('with all parameters correctly set it should succeed', async () => { await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 200); @@ -203,8 +215,12 @@ describe('API calls', () => { }); -describe('/read', () => { - let token = ""; +describe('read and login', () => { + let token = ""; + const testData = qs.stringify({ + user: "test", + password: "test", + }); test(`redirect without logged in`, async () => { const path = "/read"; const response = await axios.get("http://localhost:80" + path); @@ -212,25 +228,34 @@ describe('/read', () => { expect(response.request.path).toContain("login"); }); + it('test user can login', async () => { + const response = await axios.post('http://localhost:80/read/login', testData); + expect(response.headers['content-type']).toEqual(expect.stringContaining('application/json')); + expect(response).toHaveProperty('data.token'); + expect(response.data.token).not.toBeNull(); + token = response.data.token; + }) + + test('verified request returns json', async () => { + const response = await verifiedRequest("http://localhost:80/read?index=0", token); + expect(response.status).toBe(200); + expect(response.headers['content-type']).toEqual(expect.stringContaining('application/json')); + }); + + test(`index parameter to long`, async () => { + try { + await verifiedRequest("http://localhost:80/read?index=1234",token); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response) { + expect(axiosError.response.status).toBe(400); + } else { + console.error(axiosError); + } + } + }); - // test(`returns json`, async () => { - // const response = await axios.get("http://localhost:80/read?index=0"); - // expect(response.status).toBe(200); - // expect(response.headers['content-type']).toEqual(expect.stringContaining('application/json')); - // }); - // test(`index parameter to long`, async () => { - // try { - // await axios.get("http://localhost:80/read?index=1234"); - // } catch (error) { - // const axiosError = error as AxiosError; - // if (axiosError.response) { - // expect(axiosError.response.status).toBe(400); - // } else { - // console.error(axiosError); - // } - // } - // }); // test(`index parameter to be a number`, async () => { // try { // await axios.get("http://localhost:80/read?index=a9"); diff --git a/src/tests/login.test.ts b/src/tests/login.test.ts index a48429d..3fefe2d 100644 --- a/src/tests/login.test.ts +++ b/src/tests/login.test.ts @@ -1,15 +1,14 @@ import axios, { AxiosError } from 'axios'; -import exp from 'constants'; import qs from 'qs'; -const userData = qs.stringify({ +const userDataLarge = qs.stringify({ user: "user", password: "pass", kilobyte: 'BPSwVu5vcvhWB17HcfIdyQK83mHJZKChv7zDihBJoifWK9EJFzK7VYf3kUgIqkc0io8DnSdewzc9U0GpzodQUFz0KLMaogsJruEbNSKvxnzUxS5UqSR64lLOmGumoPcn2InC0Ebpqfdiw90HFVZVlE3AY6Lhgbx8ILHi55RvpuGefDjBsePgow8Jh9sc8uVMCDglLmHQ0zk3PumMj0KlOszbMmX9fG0pPUsvLLc40biPBv9t97K3BFjYd3fGriRAQ3bFhGHBz2wzGbNQfHjKFDHuSvXOw8KReM7Wwd4Cl02QQ3RnDJVwH6cayh4BqFRXlP3i6uXw0l9qxdTv0q1CtV9rJho6zwo04gkGLvsS3AoYJQtHnOtUDdHPExu7l3nMKnPoRUwl7K2ePfHRuppFGqa43Q49bI04VjEhrB9k5S2uZJoxZdm63rIUrydmkZWdvBLVVZUIXwwIRnwLmoa26htKOz9FPKwWIPOM0NZj4jAoPhKqLDJwziNZn5UupzxBXoUM3BIyEk3K8GXs7eBduH9GCK2z2HPF0fJNtGiHASe7jCOC2mhSC5zGf9k0Yu1Ey63oQQZUtT7L57lp7UzPE2p6wzKDlbJZOn0Ho5OUfq3hE2C8fQRO1M6jDvRTiUIKhhxSHYd75Pvh4SG9lD8w5OHASusLDxmzKBUuG4GrGrQYpd0awJkqnKp5lk7psLD22YTtjTuDgI500tQLXSslxI1kIuB8RnN1LsxHyRQMVtXmNFOKKZV2U2frWpImIz2wSHCYrwRGygwDtiFfwtVwTapjhQqUMyb1vrWWi3EL1Y50fDCjDDHlvLI4N2tr2DULFf3a9m2SYWSoE6CYP4og5YyqjhqFQFm9urREInyZi9L0iQoMYxEqxTjGiVJfKmaSChSd0kQz6z2OdsxFbkMWJ2CAHOL1XNK8iFFSp93fIspaNMIonRVDCj4ZIP1LaPHDmIYcYTNU4k3Uz6VBHSIc1VjiG3sc2MZpKw9An0tJVlWbtVSk2RGYWIANAYyr5pQS' }); -const testData = qs.stringify({ - user: "TEST", - password: "test", +const userData = qs.stringify({ + user: "user", + password: "pass" }); describe('Login', () => { @@ -29,7 +28,7 @@ describe('Login', () => { it('server is blocking requests with large body', async () => { try { - await axios.post('http://localhost:80/read/login', userData); + await axios.post('http://localhost:80/read/login', userDataLarge); } catch (error) { const axiosError = error as AxiosError; if (axiosError.response) { @@ -40,13 +39,17 @@ describe('Login', () => { } }) - it('test user can login', async () => { - const response = await axios.post('http://localhost:80/read/login', testData); - - expect(response.headers['content-type']).toEqual(expect.stringContaining('application/json')); - expect(response).toHaveProperty('data.token'); - expect(response.data.token).not.toBeNull(); - console.log(response.data); + it('invalid login verification test', async () => { + try { + await axios.post('http://localhost:80/read/login', userData); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response) { + expect(axiosError.response.status).toBe(403); + } else { + console.error(axiosError); + } + } }) })