diff --git a/typescript/lunargame/api/.eslintrc.json b/typescript/lunargame/api/.eslintrc.json
index aa811e8..0d4778c 100644
--- a/typescript/lunargame/api/.eslintrc.json
+++ b/typescript/lunargame/api/.eslintrc.json
@@ -20,6 +20,7 @@
     },
     "rules": {
         "@typescript-eslint/explicit-function-return-type": 0,
-        "@typescript-eslint/no-object-literal-type-assertion": 0
+        "@typescript-eslint/no-object-literal-type-assertion": 0,
+        "@typescript-eslint/no-parameter-properties": 0
     }
 }
diff --git a/typescript/lunargame/api/.gitignore b/typescript/lunargame/api/.gitignore
index 55d646f..5d42849 100644
--- a/typescript/lunargame/api/.gitignore
+++ b/typescript/lunargame/api/.gitignore
@@ -1,4 +1,5 @@
 node_modules
 .env
 test/db.sqlite
-db/db.sqlite
\ No newline at end of file
+db/db.sqlite
+coverage
\ No newline at end of file
diff --git a/typescript/lunargame/api/jest.config.js b/typescript/lunargame/api/jest.config.js
index dc44255..c4e5f08 100644
--- a/typescript/lunargame/api/jest.config.js
+++ b/typescript/lunargame/api/jest.config.js
@@ -5,5 +5,7 @@ module.exports = {
     },
     testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
     moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
-    testEnvironment: 'node'
+    testEnvironment: 'node',
+    collectCoverage: true,
+    coverageReporters: ['json', 'html']
 }
diff --git a/typescript/lunargame/api/src/common/validation/middleware/validate.test.ts b/typescript/lunargame/api/src/common/validation/middleware/validate.test.ts
new file mode 100644
index 0000000..bb92f22
--- /dev/null
+++ b/typescript/lunargame/api/src/common/validation/middleware/validate.test.ts
@@ -0,0 +1,62 @@
+import Joi from 'joi'
+import { validate, validationField } from './validate'
+import { Context } from 'koa'
+import { fakeNext } from '../../../../test/utils/fakeNext'
+
+describe('The validate middleware', () => {
+    const schema = Joi.object({
+        name: Joi.required()
+    })
+
+    const fields: validationField[] = ['body', 'params', 'query']
+
+    for (const field of fields) {
+        describe(`The request ${field} validator`, () => {
+            const middleware = validate(schema, field)
+
+            const getContext = (name?: number) => {
+                if (field === 'body') {
+                    return {
+                        request: {
+                            body: {
+                                name
+                            }
+                        }
+                    } as Context
+                } else {
+                    return {
+                        [field]: {
+                            name
+                        }
+                    } as Context
+                }
+            }
+
+            test('should throw an error if the validation fails', () => {
+                // arrange
+                const context = getContext()
+
+                // act
+                const check = () => {
+                    middleware(context, fakeNext())
+                }
+
+                // assert
+                expect(check).toThrow()
+            })
+
+            test('should call next if the validation passed', () => {
+                // arrange
+                const context = getContext(7)
+
+                const next = jest.fn(fakeNext())
+
+                // act
+                middleware(context, next)
+
+                // assert
+                expect(next).toBeCalled()
+            })
+        })
+    }
+})
diff --git a/typescript/lunargame/api/src/common/validation/middleware/validate.ts b/typescript/lunargame/api/src/common/validation/middleware/validate.ts
index 5089995..4554d10 100644
--- a/typescript/lunargame/api/src/common/validation/middleware/validate.ts
+++ b/typescript/lunargame/api/src/common/validation/middleware/validate.ts
@@ -2,6 +2,11 @@ import { ObjectSchema } from 'joi'
 import { Middleware } from 'koa'
 import { HttpError } from '../../../modules/network/classes/HttpError'
 
+/**
+ * The field wich the validate validator can use
+ */
+export type validationField = 'params' | 'body' | 'query'
+
 /**
  * Middlware to validate a joi schema against a request
  *
@@ -10,15 +15,17 @@ import { HttpError } from '../../../modules/network/classes/HttpError'
  *
  * @throws HttpError if the validation fails
  */
-export const validate = (
-    schema: ObjectSchema,
-    field: 'params' | 'body' | 'query'
-): Middleware => async (context, next) => {
-    const result = schema.validate(
-        field === 'body' ? context.request.body : context[field]
-    )
+export const validate = (schema: ObjectSchema, field: validationField): Middleware => (
+    context,
+    next
+) => {
+    const result = schema.validate(field === 'body' ? context.request.body : context[field], {
+        abortEarly: true
+    })
 
-    if (result.error) throw new HttpError(400, result.error.message)
+    if (result.error !== null) {
+        throw new HttpError(422, result.error.message)
+    }
 
     return next()
 }
diff --git a/typescript/lunargame/api/src/modules/auth/helpers/checkPassword.test.ts b/typescript/lunargame/api/src/modules/auth/helpers/checkPassword.test.ts
index 24ddc61..5358f6f 100644
--- a/typescript/lunargame/api/src/modules/auth/helpers/checkPassword.test.ts
+++ b/typescript/lunargame/api/src/modules/auth/helpers/checkPassword.test.ts
@@ -1,20 +1,59 @@
 import { checkPassword } from './checkPassword'
 import { passwordEncryption } from '../types/passwordEncryption'
+import { hash, genSalt } from 'bcryptjs'
 
 describe('The checkPassword helper', () => {
     const pass = 'this is a test password'
 
-    test("should throw an error if the encryption method doesn't exist", () => {
-        expect(() => {
-            checkPassword(pass, pass, '12212' as passwordEncryption)
-        }).toThrow()
+    test("should throw an error if the encryption method doesn't exist", async () => {
+        // arrange
+        const check = checkPassword(pass, pass, '12212' as passwordEncryption)
+
+        // assert
+        await expect(check).rejects.toThrow()
     })
 
-    test('should return true if the password matches the hash and the encryption = plain', () => {
-        expect(checkPassword(pass, pass, 'plain')).toBe(true)
+    describe("The 'plain' encryption", () => {
+        test('should return true if the password is correct', async () => {
+            // act
+            const check = await checkPassword(pass, pass, 'plain')
+
+            // assert
+            expect(check).toBe(true)
+        })
+
+        test('shoud return false if the password is wrong', async () => {
+            // act
+            const check = await checkPassword(pass, pass + 'something', 'plain')
+
+            // assert
+            expect(check).toBe(false)
+        })
     })
 
-    test('shoud return false if the password is wrong and the encryption = plain', () => {
-        expect(checkPassword(pass, pass + 'something', 'plain')).toBe(false)
+    describe("The 'bcrypt' encryption", () => {
+        let passwordHash: string
+
+        beforeEach(async () => {
+            const salt = await genSalt(3)
+
+            passwordHash = await hash(pass, salt)
+        })
+
+        test('should return true if the password is correct', async () => {
+            // act
+            const check = await checkPassword(passwordHash, pass, 'bcrypt')
+
+            // assert
+            expect(check).toBe(true)
+        })
+
+        test('shoud return false if the password is wrong', async () => {
+            // act
+            const check = await checkPassword(passwordHash, pass + 'something', 'bcrypt')
+
+            // assert
+            expect(check).toBe(false)
+        })
     })
 })
diff --git a/typescript/lunargame/api/src/modules/auth/helpers/checkPassword.ts b/typescript/lunargame/api/src/modules/auth/helpers/checkPassword.ts
index bd85788..cdf589d 100644
--- a/typescript/lunargame/api/src/modules/auth/helpers/checkPassword.ts
+++ b/typescript/lunargame/api/src/modules/auth/helpers/checkPassword.ts
@@ -1,5 +1,6 @@
 import { passwordEncryption } from '../types/passwordEncryption'
 import { HttpError } from '../../network/classes/HttpError'
+import { compare } from 'bcryptjs'
 
 /**
  * Comparesa apssword with it's hash
@@ -8,13 +9,15 @@ import { HttpError } from '../../network/classes/HttpError'
  * @param password The actual password
  * @param encryption The encription of the password
  */
-export const checkPassword = (
+export const checkPassword = async (
     hash: string,
     password: string,
     encryption: passwordEncryption = 'plain'
 ) => {
     if (encryption === 'plain') {
         return hash === password
+    } else if (encryption === 'bcrypt') {
+        return await compare(password, hash)
     } else {
         throw new HttpError(400, `Encription ${encryption} doesn't exist`)
     }
diff --git a/typescript/lunargame/api/src/modules/auth/helpers/encryptPassword.test.ts b/typescript/lunargame/api/src/modules/auth/helpers/encryptPassword.test.ts
index c53cea4..33b380e 100644
--- a/typescript/lunargame/api/src/modules/auth/helpers/encryptPassword.test.ts
+++ b/typescript/lunargame/api/src/modules/auth/helpers/encryptPassword.test.ts
@@ -4,19 +4,25 @@ import { compare } from 'bcryptjs'
 
 describe('The encryptPassword helper', () => {
     test("should return the same password if the method is 'plain'", async () => {
+        // arrange
         const password = internet.password()
+
+        // act
         const hash = await encryptPassword(password, 'plain')
 
+        // assert
         expect(hash).toBe(password)
     })
 
     test("should return a mactching hash if the method is 'bcrypt'", async () => {
+        // arrange
         const password = internet.password()
-
-        // the amount of rounds is small because this is just a test
         const hash = await encryptPassword(password, 'bcrypt', 3)
+
+        // act
         const match = await compare(password, hash)
 
+        // assert
         expect(match).toBe(true)
     })
 })
diff --git a/typescript/lunargame/api/src/modules/auth/middleware/isUnauthorized.test.ts b/typescript/lunargame/api/src/modules/auth/middleware/requireAnonymous.test.ts
similarity index 51%
rename from typescript/lunargame/api/src/modules/auth/middleware/isUnauthorized.test.ts
rename to typescript/lunargame/api/src/modules/auth/middleware/requireAnonymous.test.ts
index f332c5d..af4bb06 100644
--- a/typescript/lunargame/api/src/modules/auth/middleware/isUnauthorized.test.ts
+++ b/typescript/lunargame/api/src/modules/auth/middleware/requireAnonymous.test.ts
@@ -1,28 +1,35 @@
 import { Context } from 'koa'
-import { isUnauthorized } from './isUnauthorized'
-
-describe('The isUnauthorized middleware', () => {
-    const fakeNext = () => async () => {}
+import { requireAnonymous } from './requireAnonymous'
+import { fakeNext } from '../../../../test/utils/fakeNext'
 
+describe('The requireAnonymous middleware', () => {
     test('should throw an error if the user is logged in', () => {
+        // act
         const fakeContext = ({
             session: {
                 uid: 7
             }
         } as unknown) as Context
 
-        expect(() => isUnauthorized()(fakeContext, fakeNext())).toThrow()
+        // arrange
+        const runMiddleware = () => requireAnonymous()(fakeContext, fakeNext())
+
+        // assert
+        expect(runMiddleware).toThrow()
     })
 
     test("should call next if the user isn't logged in", () => {
+        // arrange
         const fakeContext = {
             session: {}
         } as Context
 
         const next = jest.fn(fakeNext())
 
-        isUnauthorized()(fakeContext, next)
+        // act
+        requireAnonymous()(fakeContext, next)
 
+        // assert
         expect(next).toBeCalled()
     })
 })
diff --git a/typescript/lunargame/api/src/modules/auth/middleware/isUnauthorized.ts b/typescript/lunargame/api/src/modules/auth/middleware/requireAnonymous.ts
similarity index 79%
rename from typescript/lunargame/api/src/modules/auth/middleware/isUnauthorized.ts
rename to typescript/lunargame/api/src/modules/auth/middleware/requireAnonymous.ts
index 17d3021..c0be72b 100644
--- a/typescript/lunargame/api/src/modules/auth/middleware/isUnauthorized.ts
+++ b/typescript/lunargame/api/src/modules/auth/middleware/requireAnonymous.ts
@@ -4,7 +4,7 @@ import { HttpError } from '../../network/classes/HttpError'
 /**
  * Middleware wich throws an error if the user is logged in
  */
-export const isUnauthorized = (): Middleware => (context, next) => {
+export const requireAnonymous = (): Middleware => (context, next) => {
     if (context.session.uid === undefined) {
         return next()
     } else {
diff --git a/typescript/lunargame/api/src/modules/auth/middleware/loggedIn.test.ts b/typescript/lunargame/api/src/modules/auth/middleware/requireAuthenticated.test.ts
similarity index 50%
rename from typescript/lunargame/api/src/modules/auth/middleware/loggedIn.test.ts
rename to typescript/lunargame/api/src/modules/auth/middleware/requireAuthenticated.test.ts
index f9caf0f..727160a 100644
--- a/typescript/lunargame/api/src/modules/auth/middleware/loggedIn.test.ts
+++ b/typescript/lunargame/api/src/modules/auth/middleware/requireAuthenticated.test.ts
@@ -1,18 +1,23 @@
-import { isAuthorized } from './isAuthorized'
+import { requireAuthenticated } from './requireAuthenticated'
 import { Context } from 'koa'
+import { fakeNext } from '../../../../test/utils/fakeNext'
 
-describe('The isAuthorized middleware', () => {
-    const fakeNext = () => async () => {}
-
+describe('The requireAuthenticated middleware', () => {
     test("should throw an error if the user isn't logged in", () => {
+        // arrange
         const fakeContext = {
             session: {}
         } as Context
 
-        expect(() => isAuthorized()(fakeContext, fakeNext())).toThrow()
+        // arrange
+        const runMiddleware = () => requireAuthenticated()(fakeContext, fakeNext())
+
+        // assert
+        expect(runMiddleware).toThrow()
     })
 
     test('should call next if the user is logged in', () => {
+        // arrange
         const fakeContext = ({
             session: {
                 uid: Math.random()
@@ -21,8 +26,10 @@ describe('The isAuthorized middleware', () => {
 
         const next = jest.fn(fakeNext())
 
-        isAuthorized()(fakeContext, next)
+        // act
+        requireAuthenticated()(fakeContext, next)
 
+        // assert
         expect(next).toBeCalled()
     })
 })
diff --git a/typescript/lunargame/api/src/modules/auth/middleware/isAuthorized.ts b/typescript/lunargame/api/src/modules/auth/middleware/requireAuthenticated.ts
similarity index 79%
rename from typescript/lunargame/api/src/modules/auth/middleware/isAuthorized.ts
rename to typescript/lunargame/api/src/modules/auth/middleware/requireAuthenticated.ts
index 497cf3d..bdb0b8b 100644
--- a/typescript/lunargame/api/src/modules/auth/middleware/isAuthorized.ts
+++ b/typescript/lunargame/api/src/modules/auth/middleware/requireAuthenticated.ts
@@ -4,7 +4,7 @@ import { HttpError } from '../../network/classes/HttpError'
 /**
  * Middlware wich throws an error if the user isn't logged in
  */
-export const isAuthorized = (): Middleware => (context, next) => {
+export const requireAuthenticated = (): Middleware => (context, next) => {
     if (context.session.uid !== undefined) {
         return next()
     } else {
diff --git a/typescript/lunargame/api/src/modules/auth/routes/authRoute.test.ts b/typescript/lunargame/api/src/modules/auth/routes/authRoute.test.ts
index 99a8126..d0b8368 100644
--- a/typescript/lunargame/api/src/modules/auth/routes/authRoute.test.ts
+++ b/typescript/lunargame/api/src/modules/auth/routes/authRoute.test.ts
@@ -3,93 +3,110 @@ import { app } from '../../../server'
 import { loggedInAgent } from '../../../../test/utils/loggedInAgent'
 import { mockAccounts } from '../../../../test/seeds/01_create-account'
 import { random, internet } from 'faker'
-import { LoginReponseBody } from '../types/LoginReponseBody'
 import { defaultEncryptionMethod } from '../constants'
 
 describe('The /auth route', () => {
     // used to make requests
-    let request = supertest(app.callback())
-
-    describe(`The POST method on the /login subroute`, () => {
-        test('should throw an error if the password field is empty', async () => {
-            const response = await request.post('/auth/login').send({
-                name: mockAccounts[0].name
-            })
-
-            expect(response.status).not.toBe(200)
-        })
-
-        test('should throw an error if the name field is empty', async () => {
-            const response = await request.post('/auth/login').send({
-                password: mockAccounts[0].password
-            })
-
-            expect(response.status).not.toBe(200)
-        })
-
-        test('should throw an error if the password is wrong', async () => {
-            const response = await request.post('/auth/login').send({
-                name: mockAccounts[0].name,
-                password: mockAccounts[0].password + 'something'
-            })
-
-            expect(response.status).not.toBe(200)
-        })
-
-        test('should work just fine when the password is correct', async () => {
-            for (const account of mockAccounts) {
-                const response = await request.post('/auth/login').send({
-                    email: account.email,
-                    password: account.password
-                })
-
-                // i'm making a separate constant for vsc to help me
-                const body: LoginReponseBody = response.body
-
-                expect(response.status).toBe(200)
-                expect(body.uid).not.toBe(undefined)
-                expect(body.encryption).toBe(account.passwordEncryption)
-            }
-        })
-    })
+    const request = supertest(app.callback())
 
     describe(`The GET method on the / subroute`, () => {
         test('should return undefined if the user was not logged in', async () => {
+            // act
             const res = await request.get('/auth')
 
+            // assert
             expect(res.body.uid).toBe(undefined)
         })
 
         test('should return the uid form the session while logged in', async () => {
+            // arrange
             const [agent, cookie] = await loggedInAgent(supertest.agent(app.callback()), {
                 email: mockAccounts[0].email,
                 password: mockAccounts[0].password
             })
 
+            // act
             const response = await agent.get('/auth').set('cookie', cookie)
 
+            // assert
             expect(response.body.uid).not.toBe(undefined)
         })
     })
 
+    describe(`The POST method on the /login subroute`, () => {
+        test('should throw an error if the user is already logged in', async () => {
+            // arrange
+            const [agent, cookie] = await loggedInAgent(supertest.agent(app.callback()), {
+                email: mockAccounts[0].email,
+                password: mockAccounts[0].password
+            })
+
+            // act
+            const reponse = await agent.post('/auth/login').set('cookie', cookie)
+
+            // assert
+            expect(reponse.status).toBe(401)
+        })
+
+        test('should throw an error if the password is wrong', async () => {
+            // act
+            const response = await request.post('/auth/login').send({
+                email: mockAccounts[0].email,
+                password: mockAccounts[0].password + 'something'
+            })
+
+            // assert
+            expect(response.status).toBe(422)
+            expect((response.body.message as string).startsWith('child')).toBe(false) // Not JOI
+        })
+
+        test("should throw an error if the user doesn't exist", async () => {
+            // act
+            const reponse = await request.post('/auth/login').send({
+                email: 'idk' + mockAccounts[0].email,
+                password: mockAccounts[0].password
+            })
+
+            // assert
+            expect(reponse.status).toBe(404)
+        })
+
+        test('should work when the password is correct', async () => {
+            for (const account of mockAccounts) {
+                // act
+                const response = await request.post('/auth/login').send({
+                    email: account.email,
+                    password: account.password
+                })
+
+                // assert
+                expect(response.status).toBe(200)
+                expect(response.body.uid).not.toBe(undefined)
+                expect(response.body.encryption).toBe(account.passwordEncryption)
+            }
+        })
+    })
+
     describe('The POST method on the /signup subroute', () => {
-        test('should return the email name and the encrytion', async () => {
-            const username = random.alphaNumeric(7)
+        test('should work if all fields are correct', async () => {
+            // arrange
+            const name = internet.userName()
             const password = random.alphaNumeric(5)
             const email = internet.email()
 
-            const response = await request.post('/auth/signup').send({
-                name: username,
+            const user = {
+                name,
                 email,
                 password
-            })
+            }
 
-            // i'm making a separate constant for vsc to help me
-            const body: LoginReponseBody = response.body
+            // act
+            const response = await request.post('/auth/signup').send(user)
 
+            // assert
             expect(response.status).toBe(200)
-            expect(body.uid).not.toBe(undefined)
-            expect(body.encryption).toBe(defaultEncryptionMethod)
+            expect(response.body.uid).not.toBe(undefined)
+            expect(response.body.encryption).toBe(defaultEncryptionMethod)
         })
     })
 })
diff --git a/typescript/lunargame/api/src/modules/auth/routes/authRoute.ts b/typescript/lunargame/api/src/modules/auth/routes/authRoute.ts
index 555403f..0b49320 100644
--- a/typescript/lunargame/api/src/modules/auth/routes/authRoute.ts
+++ b/typescript/lunargame/api/src/modules/auth/routes/authRoute.ts
@@ -8,7 +8,7 @@ import { encryptPassword } from '../helpers/encryptPassword'
 import { createAccount } from '../queries/createAccount'
 import { defaultEncryptionMethod } from '../constants'
 import { LoginBodySchema } from '../schemas/LoginBody'
-import { isUnauthorized } from '../middleware/isUnauthorized'
+import { requireAnonymous } from '../middleware/requireAnonymous'
 
 const router = new Router()
 
@@ -22,30 +22,28 @@ router.get('/', (context, next) => {
 
 router.post(
     '/login',
-    isUnauthorized(),
+    requireAnonymous(),
     validate(LoginBodySchema, 'body'),
     async (context, next) => {
         const { email, password } = context.request.body
-
         const passwordData = await getPasswordByEmail(email)
 
         // in case the user doesnt exist
         if (!passwordData) {
-            throw new HttpError(400)
+            throw new HttpError(404)
         }
 
-        const match = checkPassword(
+        const match = await checkPassword(
             passwordData.password,
             password,
             passwordData.passwordEncryption
         )
 
         if (!match) {
-            throw new HttpError(400, 'wrong password')
+            throw new HttpError(422, 'wrong password')
         }
 
         context.session.uid = passwordData.id
-
         context.body = {
             encryption: passwordData.passwordEncryption,
             uid: passwordData.id
@@ -57,7 +55,7 @@ router.post(
 
 router.post(
     '/signup',
-    isUnauthorized(),
+    requireAnonymous(),
     validate(SignupBodySchema, 'body'),
     async (context, next) => {
         const { email, name, password } = context.request.body
diff --git a/typescript/lunargame/api/src/modules/network/classes/HttpError.ts b/typescript/lunargame/api/src/modules/network/classes/HttpError.ts
index 104177d..e8dfd03 100644
--- a/typescript/lunargame/api/src/modules/network/classes/HttpError.ts
+++ b/typescript/lunargame/api/src/modules/network/classes/HttpError.ts
@@ -11,6 +11,7 @@ export enum HttpStatus {
     Conflict = 409,
     Gone = 410,
     PayloadTooLarge = 413,
+    UnprocessableEntity = 422,
     TooManyRequests = 429,
     InternalServerError = 500
 }
@@ -24,6 +25,7 @@ export const HTTP_REASONS: Record<HttpStatus, string> = {
     '409': 'Conflict',
     '410': 'Gone',
     '413': 'Payload too large',
+    '422': 'Validation error',
     '429': 'Too many requests',
     '500': 'Internal server error'
 }
@@ -34,7 +36,7 @@ export class HttpError extends Error {
     // for some reason instanceof stopped working at some point
     public [httpSymbol] = true
 
-    constructor(
+    public constructor(
         public status: HttpStatus = HttpStatus.InternalServerError,
         public reason?: string
     ) {
diff --git a/typescript/lunargame/api/test/utils/fakeNext.ts b/typescript/lunargame/api/test/utils/fakeNext.ts
new file mode 100644
index 0000000..9ea4b81
--- /dev/null
+++ b/typescript/lunargame/api/test/utils/fakeNext.ts
@@ -0,0 +1,4 @@
+/**
+ * Factory for a quick mock of the next function required to test middlewares
+ */
+export const fakeNext = () => async () => {}