require 'active_support/core_ext/hash' require 'msgpack' require 'openneo-auth-signatory' require 'utf8' module Openneo module Auth class Session REMOTE_MSG_KEYS = %w(session_id source user) TMP_STORAGE_DIR = Rails.root.join('tmp', 'openneo-auth-sessions') attr_writer :id def save! content = +MessagePack.pack(@message) FileUtils.mkdir_p TMP_STORAGE_DIR File.open(tmp_storage_path, 'w') do |file| file.write content end end def destroy! File.delete(tmp_storage_path) end def load_message! raise NotFound, "Session #{id} not found" unless File.exists?(tmp_storage_path) @message = File.open(tmp_storage_path, 'r') do |file| MessagePack.unpack file.read end end def params=(params) unless Auth.config.secret raise "Must set config.secret to the remote auth server's secret" end given_signature = params['signature'] secret = +Auth.config.secret signatory = Auth::Signatory.new(secret) REMOTE_MSG_KEYS.each do |key| unless params.include?(key) raise MissingParam, "Missing required param #{key.inspect}" end end @message = params.slice(*REMOTE_MSG_KEYS) correct_signature = signatory.sign(@message) unless given_signature == correct_signature raise InvalidSignature, "Signature (#{given_signature}) " + "did not match message #{@message.inspect} (#{correct_signature})" end end def user Auth.config.find_user_with_remote_auth(@message['user']) end def self.from_params(params) session = new session.params = params session end def self.find(id) session = new session.id = id session.load_message! session end private def id @id ||= @message[:session_id] end def tmp_storage_path name = "#{id}.mpac" File.join TMP_STORAGE_DIR, name end class InvalidSession < ArgumentError;end class InvalidSignature < InvalidSession;end class MissingParam < InvalidSession;end class NotFound < StandardError;end end end end