diff --git a/src/node/http.ts b/src/node/http.ts index e0309542..5160d17f 100644 --- a/src/node/http.ts +++ b/src/node/http.ts @@ -45,8 +45,13 @@ export const replaceTemplates = ( /** * Throw an error if not authorized. Call `next` if provided. */ -export const ensureAuthenticated = (req: express.Request, _?: express.Response, next?: express.NextFunction): void => { - if (!authenticated(req)) { +export const ensureAuthenticated = async ( + req: express.Request, + _?: express.Response, + next?: express.NextFunction, +): Promise => { + const isAuthenticated = await authenticated(req) + if (!isAuthenticated) { throw new HttpError("Unauthorized", HttpCode.Unauthorized) } if (next) { @@ -57,17 +62,19 @@ export const ensureAuthenticated = (req: express.Request, _?: express.Response, /** * Return true if authenticated via cookies. */ -export const authenticated = (req: express.Request): boolean => { +export const authenticated = async (req: express.Request): Promise => { switch (req.args.auth) { case AuthType.None: return true case AuthType.Password: // The password is stored in the cookie after being hashed. + // TODO@jsjoeio this also needs to be refactored to check if they're using the legacy password + // or the new one. we can't assume hashed-password means legacy return !!( req.cookies.key && (req.args["hashed-password"] ? safeCompare(req.cookies.key, req.args["hashed-password"]) - : req.args.password && isHashMatch(req.args.password, req.cookies.key)) + : req.args.password && (await isHashMatch(req.args.password, req.cookies.key))) ) default: throw new Error(`Unsupported auth type ${req.args.auth}`) diff --git a/src/node/routes/domainProxy.ts b/src/node/routes/domainProxy.ts index 6b527255..26a3fa6f 100644 --- a/src/node/routes/domainProxy.ts +++ b/src/node/routes/domainProxy.ts @@ -32,14 +32,15 @@ const maybeProxy = (req: Request): string | undefined => { return port } -router.all("*", (req, res, next) => { +router.all("*", async (req, res, next) => { const port = maybeProxy(req) if (!port) { return next() } // Must be authenticated to use the proxy. - if (!authenticated(req)) { + const isAuthenticated = await authenticated(req) + if (!isAuthenticated) { // Let the assets through since they're used on the login page. if (req.path.startsWith("/static/") && req.method === "GET") { return next() diff --git a/src/node/routes/login.ts b/src/node/routes/login.ts index ecbc1804..4d0420eb 100644 --- a/src/node/routes/login.ts +++ b/src/node/routes/login.ts @@ -49,9 +49,9 @@ const limiter = new RateLimiter() export const router = Router() -router.use((req, res, next) => { +router.use(async (req, res, next) => { const to = (typeof req.query.to === "string" && req.query.to) || "/" - if (authenticated(req)) { + if (await authenticated(req)) { return redirect(req, res, to, { to: undefined }) } next() diff --git a/src/node/routes/static.ts b/src/node/routes/static.ts index 30eed031..5ba6983e 100644 --- a/src/node/routes/static.ts +++ b/src/node/routes/static.ts @@ -43,7 +43,8 @@ router.get("/(:commit)(/*)?", async (req, res) => { // Make sure it's in code-server if you aren't authenticated. This lets // unauthenticated users load the login assets. - if (!resourcePath.startsWith(rootPath) && !authenticated(req)) { + const isAuthenticated = await authenticated(req) + if (!resourcePath.startsWith(rootPath) && !isAuthenticated) { throw new HttpError("Unauthorized", HttpCode.Unauthorized) } diff --git a/src/node/routes/vscode.ts b/src/node/routes/vscode.ts index 40c63e92..7e59d52c 100644 --- a/src/node/routes/vscode.ts +++ b/src/node/routes/vscode.ts @@ -19,7 +19,8 @@ export const router = Router() const vscode = new VscodeProvider() router.get("/", async (req, res) => { - if (!authenticated(req)) { + const isAuthenticated = await authenticated(req) + if (!isAuthenticated) { return redirect(req, res, "login", { // req.baseUrl can be blank if already at the root. to: req.baseUrl && req.baseUrl !== "/" ? req.baseUrl : undefined,