Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/common/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ export class HttpError extends Error {
}
}

export enum CookieKeys {
Session = "code-server-session",
export function getCookieSessionName(suffix?: string): string {
return suffix ? `code-server-session-${suffix.replace(/[^a-zA-Z0-9\-]/g, "-")}` : "code-server-session";
}
11 changes: 11 additions & 0 deletions src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface UserProvidedCodeArgs {
"disable-getting-started-override"?: boolean
"disable-proxy"?: boolean
"session-socket"?: string
"cookie-suffix"?: string
"link-protection-trusted-domains"?: string[]
// locale is used by both VS Code and code-server.
locale?: string
Expand Down Expand Up @@ -172,6 +173,12 @@ export const options: Options<Required<UserProvidedArgs>> = {
"session-socket": {
type: "string",
},
"cookie-suffix": {
type: "string",
description:
"Adds a suffix to the cookie. This can prevent a collision of cookies for subdomains, making them explixit. \n" +
"Without this flag, no suffix is used. This can also be set with CODE_SERVER_COOKIE_SUFFIX set to any string.",
},
"disable-file-downloads": {
type: "boolean",
description:
Expand Down Expand Up @@ -616,6 +623,10 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
usingEnvPassword = false
}

if (process.env.CODE_SERVER_COOKIE_SUFFIX) {
args["cookie-suffix"] = process.env.CODE_SERVER_COOKIE_SUFFIX
}

if (process.env.GITHUB_TOKEN) {
args["github-auth"] = process.env.GITHUB_TOKEN
}
Expand Down
5 changes: 3 additions & 2 deletions src/node/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as http from "http"
import * as net from "net"
import qs from "qs"
import { Disposable } from "../common/emitter"
import { CookieKeys, HttpCode, HttpError } from "../common/http"
import { HttpCode, HttpError } from "../common/http"
import { normalize } from "../common/util"
import { AuthType, DefaultedArgs } from "./cli"
import { version as codeServerVersion } from "./constants"
Expand Down Expand Up @@ -40,6 +40,7 @@ declare global {
heart: Heart
settings: SettingsProvider<CoderSettings>
updater: UpdateProvider
cookieSessionName: string
}
}
}
Expand Down Expand Up @@ -124,7 +125,7 @@ export const authenticated = async (req: express.Request): Promise<boolean> => {
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
const isCookieValidArgs: IsCookieValidArgs = {
passwordMethod,
cookieKey: sanitizeString(req.cookies[CookieKeys.Session]),
cookieKey: sanitizeString(req.cookies[req.cookieSessionName]),
passwordFromArgs: req.args.password || "",
hashedPasswordFromArgs: req.args["hashed-password"],
}
Expand Down
5 changes: 4 additions & 1 deletion src/node/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { promises as fs } from "fs"
import * as path from "path"
import * as tls from "tls"
import { Disposable } from "../../common/emitter"
import { HttpCode, HttpError } from "../../common/http"
import { getCookieSessionName, HttpCode, HttpError } from "../../common/http"
import { plural } from "../../common/util"
import { App } from "../app"
import { AuthType, DefaultedArgs } from "../cli"
Expand Down Expand Up @@ -61,6 +61,8 @@ export const register = async (
const settings = new SettingsProvider<CoderSettings>(path.join(args["user-data-dir"], "coder.json"))
const updater = new UpdateProvider("https://api.github.com/repos/coder/code-server/releases/latest", settings)

const cookieSessionName = getCookieSessionName(args["cookie-suffix"])

const common: express.RequestHandler = (req, _, next) => {
// /healthz|/healthz/ needs to be excluded otherwise health checks will make
// it look like code-server is always in use.
Expand All @@ -75,6 +77,7 @@ export const register = async (
req.heart = heart
req.settings = settings
req.updater = updater
req.cookieSessionName = cookieSessionName

next()
}
Expand Down
3 changes: 1 addition & 2 deletions src/node/routes/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Router, Request } from "express"
import { promises as fs } from "fs"
import { RateLimiter as Limiter } from "limiter"
import * as path from "path"
import { CookieKeys } from "../../common/http"
import { rootPath } from "../constants"
import { authenticated, getCookieOptions, redirect, replaceTemplates } from "../http"
import i18n from "../i18n"
Expand Down Expand Up @@ -95,7 +94,7 @@ router.post<{}, string, { password?: string; base?: string } | undefined, { to?:
if (isPasswordValid) {
// The hash does not add any actual security but we do it for
// obfuscation purposes (and as a side effect it handles escaping).
res.cookie(CookieKeys.Session, hashedPassword, getCookieOptions(req))
res.cookie(req.cookieSessionName, hashedPassword, getCookieOptions(req))

const to = (typeof req.query.to === "string" && req.query.to) || "/"
return redirect(req, res, to, { to: undefined })
Expand Down
3 changes: 1 addition & 2 deletions src/node/routes/logout.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { Router } from "express"
import { CookieKeys } from "../../common/http"
import { getCookieOptions, redirect } from "../http"
import { sanitizeString } from "../util"

export const router = Router()

router.get<{}, undefined, undefined, { base?: string; to?: string }>("/", async (req, res) => {
// Must use the *identical* properties used to set the cookie.
res.clearCookie(CookieKeys.Session, getCookieOptions(req))
res.clearCookie(req.cookieSessionName, getCookieOptions(req))

const to = sanitizeString(req.query.to) || "/"
return redirect(req, res, to, { to: undefined, base: undefined, href: undefined })
Expand Down