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

Implement SQL-backed user accounts #6

Open
simonw opened this issue Jul 13, 2020 · 5 comments
Open

Implement SQL-backed user accounts #6

simonw opened this issue Jul 13, 2020 · 5 comments
Labels
design enhancement New feature or request

Comments

@simonw
Copy link
Owner

simonw commented Jul 13, 2020

Again following the example of https://github.com/simonw/datasette-auth-tokens/blob/d6f45da578419177c260628db5f8352a839e45f2/README.md#tokens-from-your-database

@simonw
Copy link
Owner Author

simonw commented Jul 13, 2020

The trick here is making it so that hashed passwords are protected by default, without leaving people room to mess things up.

To do that, the default configuration should work as follows:

  • User accounts live in an independent database, e.g. users.db - which is specified by name in the plugin configuration
  • The plugin sets up default permission handlers that deny ALL access to tables in that database
  • The plugin adds a canned query for inserting users into the database, which is only available to root
  • That canned query includes a call to a datasette_auth_passwords_hash(password) custom SQLite function which generates the hash when the user account is created

This is the default way things work. Advanced users can customize SQL queries and even (by jumping through some "I know this is not safe" hoops) completely customize the SQL that loads the password hash.

@simonw simonw added the design label Jul 13, 2020
@simonw
Copy link
Owner Author

simonw commented Jul 15, 2020

It's only the password hashes that need to be kept secure - not the other details of the user account (whatever shape that might be).

So the configuration SQL should be "given this username, how do I retrieve the corresponding password hash".

These hashes can then be stored in a separate database entirely.

@simonw
Copy link
Owner Author

simonw commented Jul 16, 2020

Configuration design:

{
    "plugins": {
        "datasette-auth-passwords": {
            "query": {
                "sql": "select password_hash from passwords where username = :username",
                "database": "passwords"
            }
        }
    }
}

This will "protect" the entire passwords.db database. It will add permissions that lock down that database entirely.

You can disable the default protections by adding "protect_database": False in that block.

Maybe also support an update_password_sql key, which would look something like this:

"query": {
    "sql": "select password_hash from passwords where username = :username",
    "update_password_sql": "update passwords set password_hash = hash_password(:password) where username = :username",
    "database": "passwords"
}

This would then become a canned query.

Is this necessary though? The existing canned query mechanism can be used for that maybe? Except that doesn't get setup with the right root-only permissions by default.

Ensuring people use the right default configuration is really important here, so I think the plugin should lean towards doing that.

@simonw
Copy link
Owner Author

simonw commented Jul 16, 2020

Idea: if you leave off the sql key it could create a default table shape and set up default queries for you. So you'd just do this:

"query": {
    "database": "passwords"
}

Your only responsibility would be attaching a passwords.db database to Datasette. It looks like a 0 byte file will work for this, so users can run touch passwords.db to create one.

@simonw
Copy link
Owner Author

simonw commented Mar 12, 2021

Came up in office hours today!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant