{"action":"created","issue":{"url":"https://api.github.com/repos/SocketCluster/socketcluster-client/issues/9","labels_url":"https://api.github.com/repos/SocketCluster/socketcluster-client/issues/9/labels{/name}","comments_url":"https://api.github.com/repos/SocketCluster/socketcluster-client/issues/9/comments","events_url":"https://api.github.com/repos/SocketCluster/socketcluster-client/issues/9/events","html_url":"https://github.com/SocketCluster/socketcluster-client/issues/9","id":82406415,"number":9,"title":"Authentication without cookies","user":{"login":"simplesmiler","id":550229,"avatar_url":"https://avatars.githubusercontent.com/u/550229?v=3","gravatar_id":"","url":"https://api.github.com/users/simplesmiler","html_url":"https://github.com/simplesmiler","followers_url":"https://api.github.com/users/simplesmiler/followers","following_url":"https://api.github.com/users/simplesmiler/following{/other_user}","gists_url":"https://api.github.com/users/simplesmiler/gists{/gist_id}","starred_url":"https://api.github.com/users/simplesmiler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/simplesmiler/subscriptions","organizations_url":"https://api.github.com/users/simplesmiler/orgs","repos_url":"https://api.github.com/users/simplesmiler/repos","events_url":"https://api.github.com/users/simplesmiler/events{/privacy}","received_events_url":"https://api.github.com/users/simplesmiler/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":9,"created_at":"2015-05-29T12:24:34Z","updated_at":"2015-06-07T14:08:35Z","closed_at":null,"body":"There are use cases where cookie-based authentication cannot be used.\r\nFor example, in a hybrid mobile application page is served from the 'file://', and it is not possible to use cookies neither to store jwt token (cookies are recommended against in hybrid applications) nor to send the token to the server (there's no way to customize websocket connection headers from javascript).\r\n\r\nFor such use cases there should be:\r\n1. An option to customize the way token is stored.\r\n2. Some standard way to authenticate after connection is established.\r\n\r\nMy current workaround is:\r\n1. `socket.auth._setCookie` is monkey-patched to store token in localStorage.\r\n2. After connection is established, client reads token from localStorage and emits a custom event with this token. Server pick it up with the following (some error checks are omitted for clarity):\r\n```js\r\n// @EXPECTS:\r\n// - encToken: '<encToken>'\r\nfunction onHello(data, next) {\r\n  var encToken = data.encToken;\r\n  var key = scServer.auth.key; // @NOTE: whacky\r\n  jwt.verify(encToken, key, function(err, token) {\r\n    if (err) {\r\n      socket.emit('badAuthToken', err); // @NOTE: whacky\r\n    } else {\r\n      socket._authToken = token; // @NOTE: whacky\r\n    }\r\n    next();\r\n  });\r\n}\r\n```\r\n\r\nIs there a better way to do this?"},"comment":{"url":"https://api.github.com/repos/SocketCluster/socketcluster-client/issues/comments/109759145","html_url":"https://github.com/SocketCluster/socketcluster-client/issues/9#issuecomment-109759145","issue_url":"https://api.github.com/repos/SocketCluster/socketcluster-client/issues/9","id":109759145,"user":{"login":"jondubois","id":1187447,"avatar_url":"https://avatars.githubusercontent.com/u/1187447?v=3","gravatar_id":"","url":"https://api.github.com/users/jondubois","html_url":"https://github.com/jondubois","followers_url":"https://api.github.com/users/jondubois/followers","following_url":"https://api.github.com/users/jondubois/following{/other_user}","gists_url":"https://api.github.com/users/jondubois/gists{/gist_id}","starred_url":"https://api.github.com/users/jondubois/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jondubois/subscriptions","organizations_url":"https://api.github.com/users/jondubois/orgs","repos_url":"https://api.github.com/users/jondubois/repos","events_url":"https://api.github.com/users/jondubois/events{/privacy}","received_events_url":"https://api.github.com/users/jondubois/received_events","type":"User","site_admin":false},"created_at":"2015-06-07T14:08:35Z","updated_at":"2015-06-07T14:08:35Z","body":"Ok this was resolved in v2.2.25 - Now the token is stored in localStorage by default if available, if localStorage is not available, the token will be stored as an instance property - This would be the case if you run the client on Node.js. So client sockets can now use SC's authentication flow regardless of where they are running.\r\n\r\nThe other improvement which was added in v2.2.25 is that you can now fully customize the authentication behaviour on both the client and the server.\r\n\r\nOn the client, when creating the socket, you can provide a custom authEngine instance with the following methods:\r\n\r\n-  ```saveToken(name, token, options, callback)```\r\n- ```loadToken(name, callback)``` \r\n- ```removeToken(name, callback)``` method\r\n\r\nNote that callback needs to be invoked with error as first argument and the value as the second argument.\r\n\r\nOn the server, you can also provide a custom auth engine by calling ```scServer.setAuthEngine(authEngine)``` - On the server-side, the auth engine needs to provide the following methods: \r\n\r\n- ```signToken(token, key, options, callback)```\r\n- ```verifyToken(encryptedToken, key, callback)```\r\n"}}