html_url,issue_url,id,node_id,user,user_label,created_at,updated_at,author_association,body,reactions,issue,issue_label,performed_via_github_app https://github.com/simonw/datasette/issues/699#issuecomment-636494374,https://api.github.com/repos/simonw/datasette/issues/699,636494374,MDEyOklzc3VlQ29tbWVudDYzNjQ5NDM3NA==,9599,simonw,2020-05-31T16:29:48Z,2020-05-31T16:29:48Z,OWNER,"If Datasette were to support authentication out-of-the-box, without plugins (which makes more sense with writable canned queries, #698) what would that look like? Some options: - Jupyter notebook style: output a magic URL on the console with a one-time token to authenticate the user as an ""admin"" - Really simple password authentication - via an environment variable perhaps? - SQL based authentication: I was going to do this as a plugin, but maybe it should be default? A way of configuring a SQL query which can be used to authenticate a user based on their username and password.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636495005,https://api.github.com/repos/simonw/datasette/issues/699,636495005,MDEyOklzc3VlQ29tbWVudDYzNjQ5NTAwNQ==,9599,simonw,2020-05-31T16:35:10Z,2020-05-31T16:35:26Z,OWNER,I think I want to keep full username/password authentication against a database table as a plugin. I'll experiment with Jupyter-style URLs as a starting point.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636495124,https://api.github.com/repos/simonw/datasette/issues/699,636495124,MDEyOklzc3VlQ29tbWVudDYzNjQ5NTEyNA==,9599,simonw,2020-05-31T16:36:08Z,2020-05-31T16:36:08Z,OWNER,HTTP Basic auth would be a good default option. No need to build a custom login UI for it.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636498770,https://api.github.com/repos/simonw/datasette/issues/699,636498770,MDEyOklzc3VlQ29tbWVudDYzNjQ5ODc3MA==,9599,simonw,2020-05-31T17:03:38Z,2020-05-31T17:03:38Z,OWNER,"I'm going to draw the line here: default Datasette supports authentication but only for a single user account (""admin""). Plugins can then add support for multiple user accounts, social auth, SSO etc.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636498913,https://api.github.com/repos/simonw/datasette/issues/699,636498913,MDEyOklzc3VlQ29tbWVudDYzNjQ5ODkxMw==,9599,simonw,2020-05-31T17:04:50Z,2020-05-31T17:06:40Z,OWNER,"This also means some writable canned queries can allow writes from unauthenticated users (for stuff like feedback forms), while others can require an authenticated user - all with core Datasette without any plugins needed.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636499075,https://api.github.com/repos/simonw/datasette/issues/699,636499075,MDEyOklzc3VlQ29tbWVudDYzNjQ5OTA3NQ==,9599,simonw,2020-05-31T17:06:09Z,2020-05-31T17:06:09Z,OWNER,"I believe that this plugin hook design is flexible enough that role-based permissions could be built on top of it as a separate plugin. Would be good to check that with a proof of concept though.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636510303,https://api.github.com/repos/simonw/datasette/issues/699,636510303,MDEyOklzc3VlQ29tbWVudDYzNjUxMDMwMw==,9599,simonw,2020-05-31T18:35:17Z,2020-05-31T18:35:17Z,OWNER,"Keeping the structure of the actor dictionary completely undefined doesn't make sense if Datasette is going to ship with a default authentication mechanism for admin users. I'm going to define a small set of required keys for the actor dictionary, and enforce them in code. But which keys? I feel I need a unique key representing the identity of the actor, plus a key that can be displayed in the ""You are logged in as X"" navigation. Maybe these are the same key? So the single required key could be `id`. Problem is: is that a string or an integer? Some use-cases may call for an integer, which matches to how SQLite auto incrementing primary keys work. `admin` is a string. Maybe `id` is required, `name` is optional - but if `name` is present then the ""You are logged in as..."" uses that in preference to `id`. `id` has to be a string, and if you want to store integer IDs in your database you need to remember to convert them to a string in your `actor_from_request` implementation.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636510398,https://api.github.com/repos/simonw/datasette/issues/699,636510398,MDEyOklzc3VlQ29tbWVudDYzNjUxMDM5OA==,9599,simonw,2020-05-31T18:35:57Z,2020-05-31T18:36:05Z,OWNER,Again I will use exploratory prototyping to inform a decision on the minimum subset design for the `actor` dictionary.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636510647,https://api.github.com/repos/simonw/datasette/issues/699,636510647,MDEyOklzc3VlQ29tbWVudDYzNjUxMDY0Nw==,9599,simonw,2020-05-31T18:37:39Z,2020-05-31T18:37:39Z,OWNER,Maybe the default single account should be called something other than `admin`? The problem with `admin` is that it sounds like more of a role - in larger installations one can expect multiple admins. `root` may be better since there's clearly only one root account. Bit of a technical term though.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/699#issuecomment-636510761,https://api.github.com/repos/simonw/datasette/issues/699,636510761,MDEyOklzc3VlQ29tbWVudDYzNjUxMDc2MQ==,9599,simonw,2020-05-31T18:38:30Z,2020-05-31T18:38:30Z,OWNER,"I quite like `root` - it supports the idea that best practice is to NOT do things as the root account, but to use a plugin to set up separate accounts for different purposes.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",582526961,Authentication (and permissions) as a core concept, https://github.com/simonw/datasette/issues/784#issuecomment-636510838,https://api.github.com/repos/simonw/datasette/issues/784,636510838,MDEyOklzc3VlQ29tbWVudDYzNjUxMDgzOA==,9599,simonw,2020-05-31T18:39:08Z,2020-05-31T18:39:08Z,OWNER,"I'm calling this the `root` account now, for reasons discussed in these two comments: https://github.com/simonw/datasette/issues/699#issuecomment-636510647","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628003707,Ability to sign in to Datasette as a root account, https://github.com/simonw/datasette/issues/784#issuecomment-636514974,https://api.github.com/repos/simonw/datasette/issues/784,636514974,MDEyOklzc3VlQ29tbWVudDYzNjUxNDk3NA==,9599,simonw,2020-05-31T19:12:48Z,2020-05-31T19:12:48Z,OWNER,"For the first version of this I'm not going to use passwords at all. I'll implement this: $ datasette fixtures.db --root The `--root` option will cause Datasette to output a URL with a one-time-use token in it which, when clicked, will authenticate the user as the root account (by setting a signed cookie). Signed cookie means Datasette needs a secrets recipe. I'll open a new issue for that.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628003707,Ability to sign in to Datasette as a root account, https://github.com/simonw/datasette/issues/785#issuecomment-636515599,https://api.github.com/repos/simonw/datasette/issues/785,636515599,MDEyOklzc3VlQ29tbWVudDYzNjUxNTU5OQ==,9599,simonw,2020-05-31T19:17:43Z,2020-05-31T19:17:43Z,OWNER,"I previously solved this for the `datasette-auth-existing-cookies` plugin as described in this issue: https://github.com/simonw/datasette-auth-existing-cookies/issues/1 > Concrete plan: you have to pass a secret to the class constructor. The Datasette plugin (the code in `__init__.py`) uses the following in order of preference (first things are most preferred): > > - A plugin configuration option called `cookie_secret` - which can be protected by this mechanism: https://datasette.readthedocs.io/en/stable/plugins.html#secret-configuration-values > - A JSON configuration file in the `user_state_dir` file, if it exists > - If that does not exist, a secret is generated and written to that JSON file > > I originally planned to have separate support for an environment variable, but the existence of the [secret configuration values](https://datasette.readthedocs.io/en/stable/plugins.html#secret-configuration-values) mechanism means this is already handled.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636515671,https://api.github.com/repos/simonw/datasette/issues/785,636515671,MDEyOklzc3VlQ29tbWVudDYzNjUxNTY3MQ==,9599,simonw,2020-05-31T19:18:18Z,2020-05-31T19:18:18Z,OWNER,That `user_state_dir` solution may have been more trouble than it was worth though - I seem to remember it causing issues on some hosting providers.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636515763,https://api.github.com/repos/simonw/datasette/issues/785,636515763,MDEyOklzc3VlQ29tbWVudDYzNjUxNTc2Mw==,9599,simonw,2020-05-31T19:19:03Z,2020-05-31T19:19:13Z,OWNER,Maybe Datasette should have a `--secrets=path/to/secrets.json` command-line option for storing these?,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636537679,https://api.github.com/repos/simonw/datasette/issues/785,636537679,MDEyOklzc3VlQ29tbWVudDYzNjUzNzY3OQ==,9599,simonw,2020-05-31T22:09:23Z,2020-05-31T22:09:23Z,OWNER,"I'm going to use https://github.com/pallets/itsdangerous for this. Annoyingly they're very close to release v2.0 which adds support for key rotation... but it's not quite out of pre-release yet. I'll go with 1.1.0 for the moment and upgrade to 2.0 as soon as that is out.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636537921,https://api.github.com/repos/simonw/datasette/issues/785,636537921,MDEyOklzc3VlQ29tbWVudDYzNjUzNzkyMQ==,9599,simonw,2020-05-31T22:11:29Z,2020-05-31T22:11:29Z,OWNER,First version of cookie signing will use a secret that is either pulled from `DATASETTE_SECRET` environment variable or generated every time the server starts. I'll add a non-environment-variable based secret later.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636538298,https://api.github.com/repos/simonw/datasette/issues/785,636538298,MDEyOklzc3VlQ29tbWVudDYzNjUzODI5OA==,9599,simonw,2020-05-31T22:14:43Z,2020-05-31T22:15:01Z,OWNER,"... actually no I'll do it using a CLI option that can also be in an environment variable: https://click.palletsprojects.com/en/7.x/options/#values-from-environment-variables ```python @click.command() @click.option('--secret', envvar='DATASETTE_SECRET') def greet(secret): ... ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636539295,https://api.github.com/repos/simonw/datasette/issues/785,636539295,MDEyOklzc3VlQ29tbWVudDYzNjUzOTI5NQ==,9599,simonw,2020-05-31T22:24:14Z,2020-05-31T22:28:27Z,OWNER,"I'll add two utility methods to the Datasette class: - `datasette.sign(value, ""namespace"")` - returns signed string - `datasette.unsign(signed, ""namespace"")` - returns value OR raises `BadSignature`","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636541630,https://api.github.com/repos/simonw/datasette/issues/785,636541630,MDEyOklzc3VlQ29tbWVudDYzNjU0MTYzMA==,9599,simonw,2020-05-31T22:45:07Z,2020-05-31T22:45:07Z,OWNER,Documentation for those new methods: https://github.com/simonw/datasette/blob/e28207e76ec3b26b2c396370fd3fb325a60bfd49/docs/internals.rst#signvalue-namespacedefault,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636541827,https://api.github.com/repos/simonw/datasette/issues/785,636541827,MDEyOklzc3VlQ29tbWVudDYzNjU0MTgyNw==,9599,simonw,2020-05-31T22:46:34Z,2020-06-01T00:17:35Z,OWNER,This is nearly ready to close. I'm going to add documentation for `--secret` and the `DATASETTE_SECRET` environment variable.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies, https://github.com/simonw/datasette/issues/785#issuecomment-636541929,https://api.github.com/repos/simonw/datasette/issues/785,636541929,MDEyOklzc3VlQ29tbWVudDYzNjU0MTkyOQ==,9599,simonw,2020-05-31T22:47:17Z,2020-05-31T22:47:17Z,OWNER,I'll add a section about secrets to this page: https://datasette.readthedocs.io/en/latest/config.html,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",628025100,Datasette secret mechanism - initially for signed cookies,