Skip to content

Commit

Permalink
Refactor server
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasamonrc committed Sep 4, 2024
1 parent dacd810 commit 9d32f1e
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 272 deletions.
341 changes: 98 additions & 243 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"dotenv": "^16.4.5",
"drizzle-orm": "^0.33.0",
"express": "^4.19.2",
"express-async-errors": "^3.1.1",
"uuid": "^10.0.0"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export default {
rpName: "@lucasamonrc:passkeys",
rpId: process.env.RP_ID || "localhost",
acceptedOrigin: process.env.ACCEPTED_ORIGIN || [
"http://localhost:3000",
"http://localhost:3001",
],
rpId: process.env.RP_ID || "localhost",
rpName: "@lucasamonrc:passkeys",
};
21 changes: 11 additions & 10 deletions src/controllers/authentication.controller.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { eq } from "drizzle-orm";
import {
generateAuthenticationOptions,
verifyAuthenticationResponse,
} from "@simplewebauthn/server";

import { db } from "../database/connection";
import { users, credentials, challenges } from "../database/schema";
import constants from "../constants";
import {
AuthenticationResponseJSON,
AuthenticatorTransportFuture,
} from "@simplewebauthn/server/script/deps";
import { eq } from "drizzle-orm";

import { db } from "../database/connection";
import { users, credentials, challenges } from "../database/schema";
import constants from "../constants";
import AppError from "../errors/AppError";

export default {
startAuthentication: async (email: string) => {
const [user] = await db.select().from(users).where(eq(users.email, email));

if (!user) {
throw new Error("Cannot authenticate this user");
throw new AppError("Cannot authenticate this user");
}

const passkeys = await db.select().from(credentials).where(eq(credentials.userId, user.id));
Expand Down Expand Up @@ -47,7 +48,7 @@ export default {
const [user] = await db.select().from(users).where(eq(users.email, email));

if (!user) {
throw new Error("Cannot authenticate this user");
throw new AppError("Cannot authenticate this user");
}

const [challenge] = await db
Expand All @@ -56,7 +57,7 @@ export default {
.where(eq(challenges.userId, user.id));

if (!challenge) {
throw new Error("Cannot authenticate this user");
throw new AppError("Cannot authenticate this user");
}

const [credential] = await db
Expand All @@ -65,7 +66,7 @@ export default {
.where(eq(credentials.id, response.rawId));

if (!credential) {
throw new Error("Cannot authenticate this user");
throw new AppError("Cannot authenticate this user");
}

const transports = credential.transports as string;
Expand All @@ -85,7 +86,7 @@ export default {
});

if (!auth.verified) {
throw new Error("Cannot authenticate this user");
throw new AppError("Cannot authenticate this user");
}

if (auth.authenticationInfo) {
Expand Down
18 changes: 10 additions & 8 deletions src/controllers/registration.controller.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { v4 as uuid } from "uuid";

import { eq } from "drizzle-orm";
import {
generateRegistrationOptions,
verifyRegistrationResponse,
} from "@simplewebauthn/server";
import { isoUint8Array } from "@simplewebauthn/server/helpers";
import { RegistrationResponseJSON } from "@simplewebauthn/server/script/deps";
import { eq } from "drizzle-orm";
import { v4 as uuid } from "uuid";

import { db } from "../database/connection";
import { users, credentials, challenges } from "../database/schema";
import constants from "../constants";
import { RegistrationResponseJSON } from "@simplewebauthn/server/script/deps";
import { isoUint8Array } from "@simplewebauthn/server/helpers";
import AppError from "../errors/AppError";

export default {
startRegistration: async (email: string, name: string) => {
const [result] = await db.select().from(users).where(eq(users.email, email));

if (result) {
throw new Error("This email is already registered");
throw new AppError("This email is already registered");
}

const userId = uuid();
Expand Down Expand Up @@ -52,7 +52,7 @@ export default {
const [user] = await db.select().from(users).where(eq(users.email, email));

if (!user) {
throw new Error("User not found");
throw new AppError("User not found", 404);
}

const [challenge] = await db
Expand All @@ -61,7 +61,7 @@ export default {
.where(eq(challenges.userId, user.id));

if (!challenge) {
throw new Error("This user currently has no active challenge");
throw new AppError("This user currently has no active challenge", 401);
}

const verification = await verifyRegistrationResponse({
Expand Down Expand Up @@ -90,5 +90,7 @@ export default {
userId: user.id,
})
.execute();

await db.delete(challenges).where(eq(challenges.value, challenge.value)).execute();
},
};
8 changes: 8 additions & 0 deletions src/errors/AppError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default class AppError extends Error {
public readonly status: number;

constructor(message: string, status = 400) {
super(message);
this.status = status;
}
}
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import "express-async-errors";

import express, { urlencoded, json } from "express";
import path from "path";

import api from "./routes";
import exceptions from "./middleware/exceptions";

const port = process.env.PORT || 3000;
const app = express();
Expand All @@ -10,9 +13,10 @@ app.use(urlencoded({ extended: true }));
app.use(json());

app.use("/", express.static(path.join(__dirname, "../public")));

app.use("/api", api);

app.use(exceptions);

app.listen(port, () => {
console.log(`Server is listening at port ${port}`);
});
18 changes: 18 additions & 0 deletions src/middleware/exceptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { NextFunction, Request, Response } from "express";

import AppError from "../errors/AppError";

export default async function exceptions(
error: Error,
request: Request,
response: Response,
_: NextFunction,
) {
if (error instanceof AppError) {
return response.status(error.status).json({ message: error.message });
}

console.error(error);

return response.status(500).json({ message: "Internal server error" });
}
4 changes: 0 additions & 4 deletions src/routes/authentication.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@ const authentication = express.Router();

authentication.post("/start", async (request, response) => {
const { email } = request.body;

const authenticationOptions = await authenticationController.startAuthentication(email);

return response.json(authenticationOptions);
});

authentication.post("/complete", async (request, response) => {
const { email, data } = request.body;

const user = await authenticationController.completeAuthentication(email, data);

return response.json({
user,
});
Expand Down
4 changes: 0 additions & 4 deletions src/routes/registration.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@ const registration = express.Router();

registration.post("/start", async (request, response) => {
const { email, name } = request.body;

const registrationOptions = await registrationController.startRegistration(email, name);

return response.json(registrationOptions);
});

registration.post("/complete", async (request, response) => {
const { email, data } = request.body;

await registrationController.completeRegistration(email, data);

return response.status(204).send();
});

Expand Down

0 comments on commit 9d32f1e

Please sign in to comment.