{"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291406219", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291406219, "node_id": "IC_kwDOBm6k_c5M-UuL", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T02:19:54Z", "updated_at": "2022-10-26T02:59:52Z", "author_association": "OWNER", "body": "I'm going to split the remaining work into separate issues:\r\n\r\n - [x] #1856\r\n - [ ] #1855\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291431132", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291431132, "node_id": "IC_kwDOBm6k_c5M-azc", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T02:59:50Z", "updated_at": "2022-10-26T02:59:50Z", "author_association": "OWNER", "body": "Documentation: https://docs.datasette.io/en/1.0-dev/authentication.html#api-tokens", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291397623", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291397623, "node_id": "IC_kwDOBm6k_c5M-Sn3", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T02:11:40Z", "updated_at": "2022-10-26T02:11:40Z", "author_association": "OWNER", "body": "Built a prototype of the `actor_from_request()` hook for this and now:\r\n\r\n```\r\n% curl http://127.0.0.1:8001/-/actor.json -H 'Authorization: Bearer dstok_eyJhIjoicm9vdCIsImUiOm51bGx9.6O1OxgNTFkAU6uw7xNcmXYX949A'\r\n{\"actor\": {\"id\": \"root\", \"dstok\": true}}\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291392887", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291392887, "node_id": "IC_kwDOBm6k_c5M-Rd3", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T02:04:48Z", "updated_at": "2022-10-26T02:04:48Z", "author_association": "OWNER", "body": "Implemented that `dstok_` prefix and the thing where only the `actor[\"id\"]` is copied to the `\"a\"` field.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291290451", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291290451, "node_id": "IC_kwDOBm6k_c5M94dT", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:49:56Z", "updated_at": "2022-10-26T00:49:56Z", "author_association": "OWNER", "body": "Prefix: `dstok_` - for Datasette signed token.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291289369", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291289369, "node_id": "IC_kwDOBm6k_c5M94MZ", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:47:46Z", "updated_at": "2022-10-26T00:47:46Z", "author_association": "OWNER", "body": "The tokens also need something that can be used to differentiate them from alternative token mechanisms that other plugins might provide.\r\n\r\nMaybe a prefix before the signed value.\r\n\r\nPrefixes are also useful for scanning to check they were not accidentally committed to source control.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291272280", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291272280, "node_id": "IC_kwDOBm6k_c5M90BY", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:16:09Z", "updated_at": "2022-10-26T00:46:21Z", "author_association": "OWNER", "body": "Other options:\r\n\r\n- `--setting default_api_tokens off`\r\n- `--setting signed_api_tokens off`\r\n- `--setting allow_create_token off`\r\n\r\nThese feel inconsistent because they don't use the `allow_` prefix - but they're also a bit less ugly to look at.\r\n\r\nI like that last one.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291281243", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291281243, "node_id": "IC_kwDOBm6k_c5M92Nb", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:32:21Z", "updated_at": "2022-10-26T00:32:21Z", "author_association": "OWNER", "body": "Rather than duplicating the entire actor into the \"a\" field, maybe just copy the actor ID?\r\n\r\nWould need to restrict token creation to just actors with an ID set.\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291277913", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291277913, "node_id": "IC_kwDOBm6k_c5M91ZZ", "user": {"value": 4399499, "label": "ocdtrekkie"}, "created_at": "2022-10-26T00:26:11Z", "updated_at": "2022-10-26T00:26:11Z", "author_association": "NONE", "body": "> On that basis, I think the model described above where tokens mainly work to provide an \"act on behalf of this actor\" - but with optional additional constraints - is a good one.\n\nThis is what we do for Sandstorm essentially and I fully agree it's the right way to do API tokens in multiuser systems.\n\nConstraints will definitely be important though. I know I want a token to submit error reports programmatically, but I wouldn't want that token to convey my right to delete tables and records, Little Bobby Tables is out there somewhere, and he's all grown up now.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291274835", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291274835, "node_id": "IC_kwDOBm6k_c5M90pT", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:20:48Z", "updated_at": "2022-10-26T00:22:26Z", "author_association": "OWNER", "body": "Tests failed because I added a view without also adding documentation!\r\n\r\nI forgot that the deploy still goes out for branches other than `main` even if the tests aren't passing:\r\n https://github.com/simonw/datasette/blob/c7dd76c26257ded5bcdfd0570e12412531b8b88f/.github/workflows/deploy-latest.yml#L34-L38", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291273609", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291273609, "node_id": "IC_kwDOBm6k_c5M90WJ", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:18:40Z", "updated_at": "2022-10-26T00:18:40Z", "author_association": "OWNER", "body": "Another thought about tokens that can act on behalf of the user.\r\n\r\nImagine a user has permission to access a table. They create a token that can create that table... but then their permission is revoked. It would be bad if they could still use that token they created earlier to access that table!\r\n\r\nOn that basis, I think the model described above where tokens mainly work to provide an \"act on behalf of this actor\" - but with optional additional constraints - is a good one.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291272612", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291272612, "node_id": "IC_kwDOBm6k_c5M90Gk", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:16:53Z", "updated_at": "2022-10-26T00:16:53Z", "author_association": "OWNER", "body": "Next step: make these tokens actually do something.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291272414", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291272414, "node_id": "IC_kwDOBm6k_c5M90De", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:16:28Z", "updated_at": "2022-10-26T00:16:28Z", "author_association": "OWNER", "body": "If I'm going to change the naming conventions for settings I should do it before Datasette 1.0.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291271580", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291271580, "node_id": "IC_kwDOBm6k_c5M9z2c", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:14:49Z", "updated_at": "2022-10-26T00:15:06Z", "author_association": "OWNER", "body": "If I'm going to have a setting to disable this feature I need to decide what it will be called.\r\n\r\nClosest existing setting is this one, since it's for a feature that is turned on by default:\r\n\r\n datasette mydatabase.db --setting allow_download off\r\n\r\nSo maybe this?\r\n\r\n datasette mydatabase.db --setting allow_signed_api_tokens off\r\n\r\nI like `allow_signed_api_tokens` more than `allow_api_tokens` because if you install a plugin such as https://datasette.io/plugins/datasette-auth-tokens then API tokens will work even though you disabled this default signed token feature.\r\n\r\n`allow_signed_api_tokens` does feel a bit clumsy/verbose though.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291270227", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291270227, "node_id": "IC_kwDOBm6k_c5M9zhT", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:12:18Z", "updated_at": "2022-10-26T00:12:18Z", "author_association": "OWNER", "body": "Demo is now live at https://latest-1-0-dev.datasette.io/-/create-token - visit https://latest-1-0-dev.datasette.io/login-as-root first to sign in.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291269607", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291269607, "node_id": "IC_kwDOBm6k_c5M9zXn", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:11:15Z", "updated_at": "2022-10-26T00:11:15Z", "author_association": "OWNER", "body": "If you click \"Create token\" for \"Token never expires\" multiple times you currently get exactly the same token each time, since it's just a signed token containing a copy of your actor dictionary.\r\n\r\nI'm not sure if I like that. I could give each token a random ID (maybe using `secrets.token_hex()`) such that different tokens have different identities, which would be useful for logging and auditing and maybe even revocation at some point in the future.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1852#issuecomment-1291268380", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1852", "id": 1291268380, "node_id": "IC_kwDOBm6k_c5M9zEc", "user": {"value": 9599, "label": "simonw"}, "created_at": "2022-10-26T00:09:06Z", "updated_at": "2022-10-26T00:09:06Z", "author_association": "OWNER", "body": "Demo:\r\n\r\n![token-demo](https://user-images.githubusercontent.com/9599/197904595-e5651d6c-bafc-4124-b762-71ad94c06ced.gif)\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1421552095, "label": "Default API token authentication mechanism"}, "performed_via_github_app": null}