{"action":"created","issue":{"url":"https://api.github.com/repos/hassox/warden/issues/106","labels_url":"https://api.github.com/repos/hassox/warden/issues/106/labels{/name}","comments_url":"https://api.github.com/repos/hassox/warden/issues/106/comments","events_url":"https://api.github.com/repos/hassox/warden/issues/106/events","html_url":"https://github.com/hassox/warden/issues/106","id":61726471,"number":106,"title":"JWT Support","user":{"login":"hwhelchel","id":4792375,"avatar_url":"https://avatars.githubusercontent.com/u/4792375?v=3","gravatar_id":"","url":"https://api.github.com/users/hwhelchel","html_url":"https://github.com/hwhelchel","followers_url":"https://api.github.com/users/hwhelchel/followers","following_url":"https://api.github.com/users/hwhelchel/following{/other_user}","gists_url":"https://api.github.com/users/hwhelchel/gists{/gist_id}","starred_url":"https://api.github.com/users/hwhelchel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hwhelchel/subscriptions","organizations_url":"https://api.github.com/users/hwhelchel/orgs","repos_url":"https://api.github.com/users/hwhelchel/repos","events_url":"https://api.github.com/users/hwhelchel/events{/privacy}","received_events_url":"https://api.github.com/users/hwhelchel/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-03-15T01:30:53Z","updated_at":"2015-06-10T15:47:09Z","closed_at":null,"body":"Have y'all considered supporting JWT for authentication?\r\n\r\nWhat I envision is providing access to the response headers in the callbacks. Then a hook can be set up to add a JWT in the headers sent back to the client on each response. The client would then use this JWT in the next request. Thanks for a great gem."},"comment":{"url":"https://api.github.com/repos/hassox/warden/issues/comments/110806968","html_url":"https://github.com/hassox/warden/issues/106#issuecomment-110806968","issue_url":"https://api.github.com/repos/hassox/warden/issues/106","id":110806968,"user":{"login":"TiagoCardoso1983","id":215707,"avatar_url":"https://avatars.githubusercontent.com/u/215707?v=3","gravatar_id":"","url":"https://api.github.com/users/TiagoCardoso1983","html_url":"https://github.com/TiagoCardoso1983","followers_url":"https://api.github.com/users/TiagoCardoso1983/followers","following_url":"https://api.github.com/users/TiagoCardoso1983/following{/other_user}","gists_url":"https://api.github.com/users/TiagoCardoso1983/gists{/gist_id}","starred_url":"https://api.github.com/users/TiagoCardoso1983/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TiagoCardoso1983/subscriptions","organizations_url":"https://api.github.com/users/TiagoCardoso1983/orgs","repos_url":"https://api.github.com/users/TiagoCardoso1983/repos","events_url":"https://api.github.com/users/TiagoCardoso1983/events{/privacy}","received_events_url":"https://api.github.com/users/TiagoCardoso1983/received_events","type":"User","site_admin":false},"created_at":"2015-06-10T15:47:09Z","updated_at":"2015-06-10T15:47:09Z","body":"API changes proposal:\r\n\r\nconfig allows one to set the serializer (the following already assumes opting for one and only one serializer per warden middleware):\r\n\r\n```ruby\r\n  ...\r\n  # advantage: allows explicitness in choosing the session serialization as default strategy\r\n  # optional first argument: scope\r\n  config.serializer :session, :serialize => -> (user) { user.id  },\r\n                                           :deserialize => -> (id) { User.get(id) }\r\n  ...\r\n```\r\n\r\nThese callbacks would then be added to the SessionSerializer (which has already default serialize/deserialize methods). \r\n\r\nOne could then build different strategies:\r\n\r\n```ruby\r\nmodule Warden\r\n  class JWTSerializer\r\n    def serialize(user)\r\n       JWT.encode({user_id: user}, VERIFY_KEY, \"RS256\", exp: Time.now.to_i + 3000)\r\n    end\r\n\r\n    def deserialize(key)\r\n      payload, header = JWT.decode(key, VERIFY_KEY, true)\r\n      # ... do necessary verifications, token expire, yadayada\r\n      payload[\"user_id\"]\r\n    end\r\n\r\n    def store(user, scope)\r\n      return unless user\r\n      method_name = \"#{scope}_serialize\"\r\n      specialized = respond_to?(method_name)\r\n      token = specialized ? send(method_name, user) : serialize(user)\r\n      @env[\"HTTP_AUTHORIZATION\"] = \"#{scope || 'Basic'}: #{token}\"\r\n    end\r\n\r\n    def fetch(scope)\r\n      lookup = scope ? scope.to_s : \"Basic\"\r\n      key = @env[\"HTTP_AUTHORIZATION\"][%r/#{lookup}: (.+)/, 1] if @env[\"HTTP_AUTHORIZATION\"] \r\nsession[key_for(scope)]\r\n\r\n      return nil unless key\r\n\r\n      method_name = \"#{scope}_deserialize\"\r\n      user = respond_to?(method_name) ? send(method_name, key) : deserialize(key)\r\n      @env.delete(\"HTTP_AUTHORIZATION\") unless user\r\n      user\r\n    end\r\n  end\r\nend\r\n```\r\n\r\n\r\n"}}