Skip to content

Commit

Permalink
Merge pull request #1423 from argos-ci/fix-auth-error
Browse files Browse the repository at this point in the history
fix: fix auth error handling
  • Loading branch information
gregberge authored Nov 17, 2024
2 parents 8198f13 + 05f5c19 commit f77006d
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 24 deletions.
33 changes: 19 additions & 14 deletions apps/backend/src/auth/request.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import { invariant } from "@argos/util/invariant";
import * as authorization from "auth-header";
import type { Request } from "express";

import { Account, User } from "@/database/models/index.js";
import { boom } from "@/web/util.js";

import { verifyJWT } from "./jwt.js";

export class AuthError extends Error {}

const getTokenFromAuthHeader = (authHeader: string) => {
const auth = authorization.parse(authHeader);
if (auth.scheme !== "Bearer") {
throw new AuthError(`Invalid auth scheme: ${auth.scheme || "no scheme"}`);
}
if (typeof auth.token !== "string" || !auth.token) {
throw new AuthError("Invalid auth token");
try {
const auth = authorization.parse(authHeader);
if (auth.scheme !== "Bearer") {
return null;
}
if (typeof auth.token !== "string" || !auth.token) {
return null;
}
return auth.token;
} catch {
return null;
}
return auth.token;
};

export type AuthPayload = {
Expand All @@ -26,17 +30,15 @@ export type AuthPayload = {
const getAuthPayloadFromToken = async (token: string): Promise<AuthPayload> => {
const jwt = verifyJWT(token);
if (!jwt) {
throw new AuthError("Invalid JWT");
throw boom(401, "Invalid JWT");
}
const account = await Account.query()
.withGraphFetched("user")
.findById(jwt.account.id);
if (!account) {
throw new AuthError("Account not found");
}
if (!account.user) {
throw new AuthError("Account has no user");
throw boom(401, "Account not found");
}
invariant(account.user, "Account has no user");
return { account, user: account.user };
};

Expand All @@ -48,5 +50,8 @@ export async function getAuthPayloadFromRequest(
return null;
}
const token = getTokenFromAuthHeader(authHeader);
if (!token) {
return null;
}
return getAuthPayloadFromToken(token);
}
9 changes: 3 additions & 6 deletions apps/backend/src/graphql/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ import type { BaseContext } from "@apollo/server";
import type { Request } from "express";
import { GraphQLError } from "graphql";

import {
AuthError,
AuthPayload,
getAuthPayloadFromRequest,
} from "@/auth/request.js";
import { AuthPayload, getAuthPayloadFromRequest } from "@/auth/request.js";
import { HTTPError } from "@/web/util.js";

import { createLoaders } from "./loaders.js";

Expand All @@ -28,7 +25,7 @@ export async function getContext(request: Request): Promise<Context> {
const auth = await getContextAuth(request);
return { auth, loaders: createLoaders() };
} catch (error) {
if (error instanceof AuthError) {
if (error instanceof HTTPError && error.statusCode === 401) {
throw new GraphQLError("User is not authenticated", {
originalError: error,
extensions: {
Expand Down
10 changes: 8 additions & 2 deletions apps/backend/src/web/middlewares/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { RequestHandler } from "express";

import { AuthPayload, getAuthPayloadFromRequest } from "@/auth/request.js";

import { asyncHandler } from "../util.js";
import { asyncHandler, HTTPError } from "../util.js";

declare global {
namespace Express {
Expand All @@ -15,7 +15,13 @@ declare global {
}

export const auth: RequestHandler = asyncHandler(async (req, _res, next) => {
const account = await getAuthPayloadFromRequest(req);
const account = await getAuthPayloadFromRequest(req).catch((error) => {
if (error instanceof HTTPError && error.statusCode === 401) {
return null;
}

throw error;
});
req.auth = account;
next();
});
8 changes: 6 additions & 2 deletions apps/backend/src/web/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import config from "@/config/index.js";
export const asyncHandler =
(requestHandler: RequestHandler): RequestHandler =>
(req, res, next) => {
Promise.resolve(requestHandler(req, res, next)).catch(next);
try {
Promise.resolve(requestHandler(req, res, next)).catch(next);
} catch (error) {
next(error);
}
};

export const subdomain =
Expand Down Expand Up @@ -49,7 +53,7 @@ type HttpErrorOptions = ErrorOptions & {
/**
* HTTPError is a subclass of Error that includes an HTTP status code.
*/
class HTTPError extends Error {
export class HTTPError extends Error {
public statusCode: number;
public details:
| {
Expand Down

0 comments on commit f77006d

Please sign in to comment.