diff --git a/src/node/cli.ts b/src/node/cli.ts
index b3017b666175..d21f6464fd40 100644
--- a/src/node/cli.ts
+++ b/src/node/cli.ts
@@ -43,6 +43,11 @@ export interface Args extends VsArgs {
   port?: number
   "bind-addr"?: string
   socket?: string
+  "enable-get-requests"?: boolean
+  tokens?: string[]
+  "generate-token"?: boolean
+  "list-tokens"?: boolean
+  "revoke-token"?: string
   version?: boolean
   force?: boolean
   "list-extensions"?: boolean
@@ -147,6 +152,27 @@ const options: Options<Required<Args>> = {
   port: { type: "number", description: "" },
 
   socket: { type: "string", path: true, description: "Path to a socket (bind-addr will be ignored)." },
+  "enable-get-requests": {
+    type: "boolean",
+    description: `Enable authentication via the url with a query parameter. (Usage: ?pass=[password] after the rest of the url.)`
+  },
+  "tokens": {
+    type: "string[]",
+    description: ""
+  },
+  "list-tokens": {
+    type: "boolean",
+    short: "t",
+    description: "List currently active tokens."
+  },
+  "generate-token": {
+    type: "boolean",
+    description: "Generate a new token for quick access."
+  },
+  "revoke-token": {
+    type: "string",
+    description: "Remove and disable a specific token from use."
+  },
   version: { type: "boolean", short: "v", description: "Display version information." },
   _: { type: "string[]" },
 
@@ -541,6 +567,31 @@ export async function readConfigFile(configPath?: string): Promise<ConfigArgs> {
   }
 }
 
+export async function writeConfigFile(configPath?: string, data? : object) {
+  if (!configPath) {
+    configPath = process.env.CODE_SERVER_CONFIG
+    if (!configPath) {
+      configPath = path.join(paths.config, "config.yaml")
+    }
+  }
+
+  if (!(await fs.pathExists(configPath))) {
+    await fs.outputFile(configPath, await defaultConfigFile())
+    logger.info(`Wrote default config file to ${humanPath(configPath)}`)
+  }
+
+  const configFile = await fs.readFile(configPath)
+  const config = yaml.safeLoad(configFile.toString(), {
+    filename: configPath,
+  })
+  if (!config || typeof config === "string") {
+    throw new Error(`invalid config: ${config}`)
+  }
+
+  const dumpedData = yaml.safeDump({...config, ...data});
+  await fs.outputFile(configPath, dumpedData)
+}
+
 function parseBindAddr(bindAddr: string): Addr {
   const u = new URL(`http://${bindAddr}`)
   return {
diff --git a/src/node/entry.ts b/src/node/entry.ts
index ac615da68352..50e5345d58a2 100644
--- a/src/node/entry.ts
+++ b/src/node/entry.ts
@@ -11,6 +11,7 @@ import {
   optionDescriptions,
   parse,
   readConfigFile,
+  writeConfigFile,
   setDefaults,
   shouldOpenInExistingInstance,
   shouldRunVsCodeCli,
@@ -19,7 +20,7 @@ import { coderCloudBind } from "./coder_cloud"
 import { commit, version } from "./constants"
 import * as proxyAgent from "./proxy_agent"
 import { register } from "./routes"
-import { humanPath, isFile, open } from "./util"
+import { humanPath, isFile, open, generatePassword } from "./util"
 import { isChild, wrapper } from "./wrapper"
 
 export const runVsCodeCli = (args: DefaultedArgs): void => {
@@ -125,6 +126,10 @@ const main = async (args: DefaultedArgs): Promise<void> => {
     logger.info(`  - Authentication is disabled ${args.link ? "(disabled by --link)" : ""}`)
   }
 
+  if (args["enable-get-requests"]) {
+    logger.info(`  - Login via GET is enabled ${args.auth === AuthType.None ? "(however auth is disabled)" : ""}`)
+  }
+
   if (args.cert) {
     logger.info(`  - Using certificate for HTTPS: ${humanPath(args.cert.value)}`)
   } else {
@@ -202,6 +207,55 @@ async function entry(): Promise<void> {
     return
   }
 
+  if (args.tokens) {
+    args.tokens = args.tokens[0].split(",")
+  }
+
+  if (args["list-tokens"]) {
+    console.log("code-server", version, commit)
+    console.log("")
+    if (!args.tokens) {
+      return console.log("No tokens currently exist")
+    }
+    console.log("Tokens")
+    args.tokens.forEach(token => {
+      console.log("  -", token)
+    })
+    return
+  }
+
+  if (args["generate-token"]) {
+    console.log("code-server", version, commit)
+    console.log("")
+
+    if (!args.tokens) {
+      args.tokens = []
+    }
+
+    const token = await generatePassword()
+    args.tokens.push(token)
+    writeConfigFile(cliArgs.config, { tokens: args.tokens })
+    console.log("Generated token:", token)
+    return
+  }
+
+  if (args["revoke-token"]) {
+    console.log("code-server", version, commit)
+    console.log("")
+
+    if (args.tokens?.includes(args["revoke-token"])) {
+      args.tokens = args.tokens.filter(token => {
+        return token != args["revoke-token"]
+      })
+      writeConfigFile(cliArgs.config, { tokens: args.tokens })
+      console.log("The token has successfully been revoked")
+    }
+    else {
+      console.log("The token specified does not exist")
+    }
+    return
+  }
+
   if (shouldRunVsCodeCli(args)) {
     return runVsCodeCli(args)
   }
diff --git a/src/node/routes/login.ts b/src/node/routes/login.ts
index 4db7fd825d13..201a7eb602de 100644
--- a/src/node/routes/login.ts
+++ b/src/node/routes/login.ts
@@ -1,4 +1,4 @@
-import { Router, Request } from "express"
+import { Router, Request, Response, NextFunction } from "express"
 import { promises as fs } from "fs"
 import { RateLimiter as Limiter } from "limiter"
 import * as path from "path"
@@ -43,45 +43,35 @@ const getRoot = async (req: Request, error?: Error): Promise<string> => {
 
 const limiter = new RateLimiter()
 
-export const router = Router()
-
-router.use((req, res, next) => {
-  const to = (typeof req.query.to === "string" && req.query.to) || "/"
-  if (authenticated(req)) {
-    return redirect(req, res, to, { to: undefined })
-  }
-  next()
-})
-
-router.get("/", async (req, res) => {
-  res.send(await getRoot(req))
-})
-
-router.post("/", async (req, res) => {
+const login = async (req : Request, res : Response, password : string) => {
   try {
     if (!limiter.try()) {
       throw new Error("Login rate limited!")
     }
 
-    if (!req.body.password) {
+    if (!password) {
       throw new Error("Missing password")
     }
 
     if (
       req.args.hashedPassword
-        ? safeCompare(hash(req.body.password), req.args.hashedPassword)
-        : req.args.password && safeCompare(req.body.password, req.args.password)
+        ? safeCompare(hash(password), req.args.hashedPassword)
+        : req.args.password && safeCompare(password, req.args.password)
     ) {
       // 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(Cookie.Key, hash(req.body.password), {
+      res.cookie(Cookie.Key, hash(password), {
         domain: getCookieDomain(req.headers.host || "", req.args["proxy-domain"]),
         path: req.body.base || "/",
         sameSite: "lax",
       })
 
       const to = (typeof req.query.to === "string" && req.query.to) || "/"
-      return redirect(req, res, to, { to: undefined })
+      return redirect(req, res, to, {
+        to: undefined, 
+        password: undefined,
+        pass: undefined,
+      })
     }
 
     console.error(
@@ -98,4 +88,34 @@ router.post("/", async (req, res) => {
   } catch (error) {
     res.send(await getRoot(req, error))
   }
+}
+
+export const router = Router()
+
+router.use((req : Request, res : Response, next : NextFunction) => {
+  const to = (typeof req.query.to === "string" && req.query.to) || "/"
+  if (authenticated(req)) {
+    return redirect(req, res, to, {
+      to: undefined, 
+      password: undefined,
+      pass: undefined,
+    })
+  }
+  next()
+})
+
+router.get("/", async (req : Request, res : Response) => {
+  if (req.args["enable-get-requests"]) {
+    // `?password` overrides `?pass`
+    if (req.query.password && typeof req.query.password === "string") {
+      return await login(req, res, req.query.password)
+} else if (req.query.pass && typeof req.query.pass === "string") {
+      return await login(req, res, req.query.pass)
+    }
+  }
+  res.send(await getRoot(req))
+})
+
+router.post("/", async (req : Request, res : Response) => {
+  await login(req, res, req.body.password)
 })