Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support HTTP BasicAuth for authentication if $AUTH_USER is set #7143

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

gaberudy
Copy link

Fixes #7142

@gaberudy gaberudy requested a review from a team as a code owner December 29, 2024 04:49
Copy link
Member

@code-asher code-asher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat, thank you! I know we are not generally adding auth methods, but this seems simple enough to maintain.

@@ -0,0 +1,45 @@
#!/bin/bash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Docker image seems unrelated to the auth changes, could we remove it from this PR? Happy to read about it in another PR/issue, but at first glance I am not sure it is something we should be maintaining here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I didn't meant to include this.

@@ -0,0 +1,15 @@
github.copilot
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we omit this file? Seems unrelated to code-server itself.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, unintended

@@ -0,0 +1,12 @@
#!/bin/bash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also seems unrelated to this particular PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, unintended

@@ -0,0 +1,44 @@
#!/bin/bash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, unintended

@@ -86,6 +86,7 @@
"safe-buffer": "^5.2.1",
"safe-compare": "^1.1.4",
"semver": "^7.5.4",
"tslib": "^2.8.1",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was this added for? We have no direct dependency on tslib, do we?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove it, but I had a packaging issue without it.

} else if (args.auth === AuthType.HttpBasic) {
logger.info(" - HTTP basic authentication is enabled")
logger.info(" - Using user from $AUTH_USER")
logger.info(" - Using password from $PASSWORD")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The password might be from the config, so we would need to check args.usingEnvPassword (just like the block above). We can maybe combine these blocks. Something like:

  if (args.auth === AuthType.Password || args.auth === AuthType.HttpBasic) {
    logger.info("  - Authentication is enabled")
    if (args.usingEnvPassword) {
      logger.info("    - Using password from $PASSWORD")
    } else if (args.usingEnvHashedPassword) {
      logger.info("    - Using password from $HASHED_PASSWORD")
    } else {
      logger.info(`    - Using password from ${args.config}`)
    }
    if (args.auth === AuthType.HttpBasic) {
      logger.info("    - With user ${args["auth-user"]}") // or add an args.usingEnvAuthUser and switch on it as appropriate
    }
  } else {
    logger.info("  - Authentication is disabled")
  }

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll incorporate this change

@@ -118,6 +119,11 @@ router.get("/", ensureVSCodeLoaded, async (req, res, next) => {
const FOLDER_OR_WORKSPACE_WAS_CLOSED = req.query.ew

if (!isAuthenticated) {
// If auth is HttpBasic, return a 401.
if (req.args.auth === AuthType.HttpBasic) {
res.setHeader('WWW-Authenticate', 'Basic realm="Access to the site"')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to set this header on the other places where we throw unauthorized for basic auth? And in the ensureAuthenticated middleware as well.

Also, could be cool to put the name in the realm, maybe:

`Basic realm=${req.args["app-name"] || "code-server"}`

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only place a fresh browser load hits and thus needs this header to prompt the user. I'll update the realm

@@ -0,0 +1,27 @@
#!/bin/bash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to the PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@@ -132,6 +151,9 @@ export const authenticated = async (req: express.Request): Promise<boolean> => {

return await isCookieValid(isCookieValidArgs)
}
case AuthType.HttpBasic: {
return validateBasicAuth(req.headers.authorization, req.args["auth-user"], req.args.password);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if someone sets HASHED_PASSWORD but not PASSWORD and then sets auth=basic-auth? I think it would use the config password instead (a default one is always generated), which might be unexpected. We could use handlePasswordValidation to support both HASHED_PASSWORD and PASSWORD, or we could error when HASHED_PASSWORD is set and say it can only be used with PASSWORD.

Copy link
Author

@gaberudy gaberudy Jan 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can check HASHED_PASSWORD in this context. The password has to come through standard basic auth format. I think the use case for basic auth is to specify a user and password.

const base64Credentials = authHeader.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('utf-8');
const [username, password] = credentials.split(':');
return username === authUser && password === authPassword;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use safeCompare instead of === probably.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll switch the password comparison to safeCompare

Copy link
Member

@code-asher code-asher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, did not mean to approve quite yet. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support HTTP BasicAuth as alternative authentication
2 participants