{"action":"created","issue":{"url":"https://api.github.com/repos/superpowers/superpowers/issues/55","labels_url":"https://api.github.com/repos/superpowers/superpowers/issues/55/labels{/name}","comments_url":"https://api.github.com/repos/superpowers/superpowers/issues/55/comments","events_url":"https://api.github.com/repos/superpowers/superpowers/issues/55/events","html_url":"https://github.com/superpowers/superpowers/issues/55","id":126719269,"number":55,"title":"Implement authentication, access rights and user settings","user":{"login":"elisee","id":446986,"avatar_url":"https://avatars.githubusercontent.com/u/446986?v=3","gravatar_id":"","url":"https://api.github.com/users/elisee","html_url":"https://github.com/elisee","followers_url":"https://api.github.com/users/elisee/followers","following_url":"https://api.github.com/users/elisee/following{/other_user}","gists_url":"https://api.github.com/users/elisee/gists{/gist_id}","starred_url":"https://api.github.com/users/elisee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elisee/subscriptions","organizations_url":"https://api.github.com/users/elisee/orgs","repos_url":"https://api.github.com/users/elisee/repos","events_url":"https://api.github.com/users/elisee/events{/privacy}","received_events_url":"https://api.github.com/users/elisee/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/superpowers/superpowers/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/superpowers/superpowers/labels/security","name":"security","color":"eb6420"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2016-01-14T18:38:31Z","updated_at":"2016-01-16T09:20:45Z","closed_at":null,"body":"OK, I think we finally have a decent proposal for how to deal with user authentication and settings in Superpowers. Feedback welcome!\r\n\r\nFirst of all, some goals:\r\n\r\n * Avoid single points of failure and costly (both money- and time-wise) centralized infrastructure\r\n * Maintain the ability to join a server temporarily without maintaining an account\r\n * Automate as much as possible so users don't have to do drudge work\r\n\r\nAnd some non-goals:\r\n\r\n * We can't protect users from malicious server owners storing a user's password, because the client JS code is provided by the server. This is a core aspect of Superpowers's design and as such, users should only connect to servers they trust and for added security, use a different, unpredictable password on every server. See #53\r\n\r\nNow, with that in mind, here's the proposed design:\r\n\r\n## Authentication\r\n\r\nWe'll use `passport` as the authentication framework, along with a text-based store (with in-memory cache) for user accounts and session objects. We could use `sqlite` but it seems overkill for the small amount of users and connections a Superpowers server will have. Plus being text-based means one could easily version or duplicate the server membership information, if desired.\r\n\r\nThe global server password will be re-purposed as an optional key for restricting access to the sign up form. A separate option will be added to open the server to outside connections or not and it will stay disabled by default, as it currently is, to avoid exposing users exposing their projects to the Internet accidentally.\r\n\r\n### Authentication options\r\n\r\nA server owner will be able to enable various login options:\r\n\r\n**Temporary login:** Clients can enter an available guest username, the account will be tagged visually as guest and will automatically expire after an hour. No one can log in to it without the session key.\r\n\r\n**Local password:** Clients can choose an available username and a password. We should mention in the UI that a unique password should be used. The server will store a bcrypt hash of the user's password. They can also upload a profile picture.\r\n\r\n**Login with external service:** Using OAuth, server owners can setup authentication with GitHub, Twitter or whatever other service they want. It is up to the server owner to setup an OAuth id/secret on the external service and fill them in the server config. After logging in with the service, the client will have still provide a local username (though the field can be pre-filled with the one from the external service used to log in). The OAuth-provided profile picture will automatically be used.\r\n\r\nEach user account will be stored in a `users` folder, with the username as the folder name.\r\nIt will contain an `auth.json` that looks something like this:\r\n\r\n```json\r\n{\r\n  \"auth\": {\r\n    \"guest\": { \"expires\": \"some timestamp\" },\r\n    \"local\": { \"passwordHash\": \"some bcrypt hash\" },\r\n    \"github or twitter or whatever\": {\r\n      \"token\": \"oauth token\",\r\n      \"pictureURL\": \"url\"\r\n    },\r\n    /* etc. */\r\n  },\r\n  \"picture\": \"url of the active picture if any, otherwise it'll automatically use the local one\"\r\n}\r\n```\r\n\r\nWe'll store a local `picture.png` file in the same folder if the user uploads one.\r\n\r\nQUESTION: The primary key for the user account would then be its username. Is that a bad thing? Do we care about renaming accounts on servers? If so, where will we reference user accounts in Superpowers? do we need to have a never-changing user ID instead?\r\n\r\n## Access rights\r\n\r\nThe server can have one of several default settings:\r\n\r\n * No access to anything (not even the list of projects)\r\n * Read-only access to every project\r\n * Read/write access to every project for everyone (does not apply to temporary logins)\r\n\r\nEach user can then have custom access rights for each project. That information should be stored in the user's folder, not in project's folder, to avoid versioning it accidentally.\r\n\r\n## User settings\r\n\r\nUser settings will be stored in `localStorage`. Each namespace (similar to resource IDs) will be stored as a separate key, something like `superpowers.textEditor`. It should have a format version for migration.\r\n\r\nEditors interested should subscribe to [localStorage events](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Responding_to_storage_changes_with_the_StorageEvent) and react to changes as needed.\r\n\r\nEach settings tool plugin will be able to add a user-specific section for user-specific settings.\r\n\r\nIn the browser, the `settings` tool will provide buttons to import and export user settings as a JSON file.\r\n\r\nIn the app, the launcher will provide those buttons in the settings instead. The `settings` tool of a project will notify Electron of changes to the settings so that it can keep the global copy updated and update the localStorage of other origins currently open. And it will update it when opening a server, too."},"comment":{"url":"https://api.github.com/repos/superpowers/superpowers/issues/comments/172176345","html_url":"https://github.com/superpowers/superpowers/issues/55#issuecomment-172176345","issue_url":"https://api.github.com/repos/superpowers/superpowers/issues/55","id":172176345,"user":{"login":"Xstoudi","id":2575182,"avatar_url":"https://avatars.githubusercontent.com/u/2575182?v=3","gravatar_id":"","url":"https://api.github.com/users/Xstoudi","html_url":"https://github.com/Xstoudi","followers_url":"https://api.github.com/users/Xstoudi/followers","following_url":"https://api.github.com/users/Xstoudi/following{/other_user}","gists_url":"https://api.github.com/users/Xstoudi/gists{/gist_id}","starred_url":"https://api.github.com/users/Xstoudi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Xstoudi/subscriptions","organizations_url":"https://api.github.com/users/Xstoudi/orgs","repos_url":"https://api.github.com/users/Xstoudi/repos","events_url":"https://api.github.com/users/Xstoudi/events{/privacy}","received_events_url":"https://api.github.com/users/Xstoudi/received_events","type":"User","site_admin":false},"created_at":"2016-01-16T09:20:45Z","updated_at":"2016-01-16T09:20:45Z","body":">QUESTION: The primary key for the user account would then be its username. Is that a bad thing? Do we care about renaming accounts on servers? If so, where will we reference user accounts in Superpowers? do we need to have a never-changing user ID instead?\r\n\r\nI think primary key should never be a concret information. Create an unique user ID can prevent many problems."}}