feat: As a user, I want to store basic auth credentials in hashed form, to not leak them to authorized admins
- Dominant language
- Lua
- Stars
- 17.1k
- Forks
- 2.9k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 63
Description
### Description
As a User, I want to store basic auth credentials in a hashed way, to not leak credentials to other admin users.
Hi, we are manaiging APISIX with a team of people using the apisix-dashboard.
There is a different set of users that have authenticated access to some APIs exposed via APISIX (not the admin API). We use consumers and a combination of `basic-auth` and `restrict-consumers`-plugins to restrict access. We have noticed, that all basic-auth credentials of consumers are stored in a readable format for admins (i.e. if you go to `consumers` -> `` -> `credentials` -> ``, you can see the plain password for this user.
This allows for trivial impersonation of people and API access for admin users. Thus, I would like to see at least the option to store `basic-auth` passwords in a hashed way. Sane defaults would be to use SHA512 or bcrypt (depending on which algorithms are supported by lua), with a defined salt, e.g. SHA512(USERNAME.PASSWORD).
The same is true for `key-auth` API keys.
I am open to help with both code fragments, testing and QA, although I am not very familiar with lua.
The schema for configuration would be something like:
~~~json
# user config
{
"username": "testuser",
"plugins": {
"basic-auth": {
"username": "my-basic-credential", # existing
"password": "my-password", # existing
"hashed_password": "", # mutually exclusive to password, allows outside hashing
"hash": "sha512" # sane default, future-proofing if algorithm needs to be changed
}
}
}
~~~
Regarding implementation, there need to be 2 sections:
- saving new credentials - didn't find that in a quick search. There needs to be some logic for differentation between `password`and `hashed_password` parameter
- checking the credentials (pseudocode, `plugins/basic-auth.lua:151`)
~~~lua
# snippet of basic-auth.lua
# import library
local hash = require("lua-hash")
...
# within find_consumer(ctx), before line 151
if cur_consumer.auth_conf.hash != "" then
local password_to_check = hash.oneshot(cur_consumer.auth_conf.hash, username .. password)
else
local password_to_check = password
fi
if cur_consumer.auth_conf.password ~= password_to_check then
~~~
Please let me know what you think of the idea. Let me know if you need any more information; as I said, I can contribute code as well, but I will need some pointers in regards to boilerplate (requirements, tests, ...) that need to be implented.
Contributor guide
Research direction
Start with plugins/basic-auth.lua around the referenced line 151 and trace how consumer credentials are saved and checked; the issue says the saving path was not identified. Compare the proposed hashed_password and hash configuration with the existing basic-auth and key-auth behavior, then define tests covering credential storage and authentication. Done should include an agreed hashing design, compatible configuration behavior, and QA for both credential types.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- lua
- Domain
- authentication, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100