diff --git a/docs/web/authentication.md b/docs/web/authentication.md
index fda750757f..14338e1306 100644
--- a/docs/web/authentication.md
+++ b/docs/web/authentication.md
@@ -9,26 +9,28 @@ the results stored on a server.
Table of Contents
=================
-* [Server-side configuration](#server-side-configuration)
- * [Dictionary authentication](#dictionary-authentication)
- * [External authentication methods](#external-auth-methods)
- * [PAM authentication](#pam-authentication)
- * [LDAP authentication](#ldap-authentication)
- * [Configuration options](#configuration-options)
- * [Membership in custom groups with regex_groups](#regex_groups-authentication)
- * [OAuth authentication](#oauth-authentication)
- * [OAuth Configuration options](#oauth-configuration-options)
- * [OAuth details per each provider](#oauth-details-per-each-provider)
-* [Client-side configuration](#client-side-configuration)
- * [Web-browser client](#web-browser-client)
- * [Command-line client](#command-line-client)
- * [Preconfigured credentials](#preconfigured-credentials)
- * [Automatic login](#automatic-login)
- * [Currently active tokens](#currently-active-tokens)
-* [Personal access token](#personal-access-token)
- * [`new`](#new-personal-access-token)
- * [`list`](#list-personal-access-token)
- * [`del`](#remove-personal-access-token)
+- [CodeChecker authentication subsystem](#codechecker-authentication-subsystem)
+- [Table of Contents](#table-of-contents)
+- [Server-side configuration ](#server-side-configuration-)
+ - [Dictionary authentication ](#dictionary-authentication-)
+ - [External authentication methods ](#external-authentication-methods-)
+ - [PAM authentication ](#pam-authentication-)
+ - [LDAP authentication ](#ldap-authentication-)
+ - [Configuration options ](#configuration-options-)
+ - [Membership in custom groups with regex\_groups](#membership-in-custom-groups-with-regex_groups)
+ - [OAuth authentication ](#oauth-authentication-)
+ - [OAuth Configuration options ](#oauth-configuration-options-)
+ - [OAuth Details per each provider ](#oauth-details-per-each-provider-)
+- [Client-side configuration ](#client-side-configuration-)
+ - [Web-browser client ](#web-browser-client-)
+ - [Command-line client ](#command-line-client-)
+ - [Preconfigured credentials ](#preconfigured-credentials-)
+ - [Automatic login ](#automatic-login-)
+ - [Currently active tokens ](#currently-active-tokens-)
+- [Personal access token ](#personal-access-token-)
+ - [New personal access token ](#new-personal-access-token-)
+ - [List personal access tokens ](#list-personal-access-tokens-)
+ - [Remove personal access token ](#remove-personal-access-token-)
# Server-side configuration
@@ -360,7 +362,7 @@ Specific behavior related to each provider is configured by a provider `template
A key-value table that is used to set variables across all providers, for convenience.
Any variable can be specified. If using the `host` variable, it should be in the format `https://example.com`, including the protocol.
-
+
The `callback_url`'s default value uses the `host` and `provider` variables.
Template `ms_entra/v2.0` uses the `tenant_id` variable.
@@ -394,7 +396,7 @@ Specific behavior related to each provider is configured by a provider `template
* `variables`
- A key-value table that is used to set variables used inside parameters.
+ A key-value table that is used to set variables used inside parameters.
To use a variable, specify it using `{variable}`.
The `{provider}` variable is automatically set.
@@ -494,7 +496,7 @@ Specific behavior related to each provider is configured by a provider `template
*Default*: Set by template.
### 🔧 Example: OAuth Configuration using templates
-
+
```jsonc
"github": {
"enabled": false,
@@ -622,7 +624,14 @@ To alleviate the need for supplying authentication in the command-line every
time a server is connected to, users can pre-configure their credentials to be
used in authentication.
-To do so first copy the `config/session_client.json` file from the CodeChecker
+You can pass the credential used as a password or personal access token
+in the `.codechecker.password.json` or
+directly in the `CC_PASSWORD` environment variable.
+If this environment variable is set, the credentials
+described in `.codechecker.password.json` will be ignored.
+
+If you wish to provide (multiple different) credentials in a password configuration file,
+first copy the `config/session_client.json` file from the CodeChecker
package to your home directory and rename it to `.codechecker.passwords.json`
After creating the new file open `~/.codechecker.passwords.json`.
@@ -656,10 +665,9 @@ authenticate in the name of the given user. This way no need to store passwords
in text files. For more information [see](#personal-access-token).
The location of the password file can be configured by the `CC_PASS_FILE`
-environment variable. This environment variable can also be used to setup
-different credential files to login to the same server with a different user.
+environment variable.
-Furthermore, the location of the session file can be configured by the
+The location of the session file can be configured by the
`CC_SESSION_FILE` environment variable. This can be useful if CodeChecker does
not have the permission to create a session file under the user's home
directory (e.g. in some CI environments).
diff --git a/web/client/codechecker_client/cli/store.py b/web/client/codechecker_client/cli/store.py
index afe025b2c3..a027527765 100644
--- a/web/client/codechecker_client/cli/store.py
+++ b/web/client/codechecker_client/cli/store.py
@@ -165,6 +165,10 @@ def get_argparser_ctor_args():
'epilog': """
Environment variables
------------------------------------------------
+ CC_PASSWORD You can provide authentication credentials directly in this
+ variable. "CodeChecker cmd login" will use it as a
+ password or personal access token if set.
+
CC_PASS_FILE The location of the password file for auto login. By default
CodeChecker will use '~/.codechecker.passwords.json' file.
It can also be used to setup different credential files to
diff --git a/web/client/codechecker_client/client.py b/web/client/codechecker_client/client.py
index e6a5745f32..47c9ccc5d4 100644
--- a/web/client/codechecker_client/client.py
+++ b/web/client/codechecker_client/client.py
@@ -111,11 +111,19 @@ def login_user(protocol, host, port, username, login=False):
methods = auth_client.getAcceptedAuthMethods()
# Attempt username-password auth first.
if 'Username:Password' in str(methods):
-
# Try to use a previously saved credential from configuration file if
# autologin is enabled.
saved_auth = None
- if session.is_autologin_enabled():
+ if env.get_password_string():
+ # if CC_PASSWORD env var is defined use that
+ LOG.info("Using credentials from CC_PASSWORD env var to log in.")
+ if not username:
+ LOG.error("Cannot login. CC_PASSWORD env var is defined,"
+ "but username is not provided!")
+ sys.exit(1)
+ saved_auth = f"{username}:{env.get_password_string()}"
+
+ if session.is_autologin_enabled() and not saved_auth:
saved_auth = session.get_auth_string(host, port)
if saved_auth:
diff --git a/web/codechecker_web/shared/env.py b/web/codechecker_web/shared/env.py
index 08a58855ca..aa944c1fa9 100644
--- a/web/codechecker_web/shared/env.py
+++ b/web/codechecker_web/shared/env.py
@@ -26,6 +26,11 @@ def get_default_workspace():
return workspace
+def get_password_string():
+ """ Return the location of the CodeChecker password credential. """
+ return os.environ.get("CC_PASSWORD", None)
+
+
def get_password_file():
""" Return the location of the CodeChecker password file. """
return os.environ.get("CC_PASS_FILE",
diff --git a/web/tests/functional/authentication/test_authentication.py b/web/tests/functional/authentication/test_authentication.py
index 5edb4485a3..a829b7426a 100644
--- a/web/tests/functional/authentication/test_authentication.py
+++ b/web/tests/functional/authentication/test_authentication.py
@@ -542,6 +542,40 @@ def test_nonauth_storage(self):
subprocess.check_output(
store_cmd, encoding="utf-8", errors="ignore")
+ def test_cc_password_env_auth(self):
+ """
+ Tests authentication if credential is passed
+ in the CC_PASSWORD env var.
+ """
+
+ codechecker_cfg = self._test_cfg['codechecker_cfg']
+
+ # Login with good password
+ my_env = os.environ.copy()
+ my_env["CC_PASSWORD"] = "test"
+
+ login_cmd = [env.codechecker_cmd(), 'cmd', 'login', 'cc',
+ '--url', env.parts_to_url(codechecker_cfg)]
+
+ login_response = subprocess.check_output(
+ login_cmd, env=my_env, encoding="utf-8", errors="ignore")
+ self.assertTrue(login_response,
+ "Server reported successful authentication")
+
+ logout_cmd = [env.codechecker_cmd(), 'cmd', 'login', 'cc',
+ '-d', '--url', env.parts_to_url(codechecker_cfg)]
+ subprocess.check_output(
+ logout_cmd, env=my_env, encoding="utf-8", errors="ignore")
+ # Login with wrong password
+ my_env["CC_PASSWORD"] = "wrong"
+
+ login_cmd = [env.codechecker_cmd(), 'cmd', 'login', 'cc',
+ '--url', env.parts_to_url(codechecker_cfg)]
+
+ with self.assertRaises(subprocess.CalledProcessError):
+ subprocess.check_output(
+ login_cmd, env=my_env, encoding="utf-8", errors="ignore")
+
def test_group_auth(self):
"""
Test for case insensitive group comparison at authorization.