require 'omniauth/core' require 'openssl' module OmniAuth module Strategies class Ign include OmniAuth::Strategy IDENTIFIER_URL_PARAMETER = "" class CallbackError < StandardError attr_accessor :error, :error_reason def initialize(error, error_reason) self.error = error self.error_reason = error_reason end end def initialize(app, api_key, hostname=nil, options = {}) options[:name] ||= "ign" super(app, :ign) @api_key = api_key @hostname = hostname end protected def request_phase OmniAuth::Form.build(:title => 'IGN Authentication', :header_info=>js) do label_field('Identifying you with the IGN server', IDENTIFIER_URL_PARAMETER) end.to_response end def callback_phase signature = OpenSSL::HMAC.hexdigest('sha1', @api_key, ("#{request.params["username"]}::#{request.params["timestamp"]}")) raise CallbackError.new("Invalid Signature","The supplied and calculated signature did not match, user not approved.") if signature != request.params["signature"] super rescue CallbackError => e fail!(:invalid_response, e) end def auth_hash OmniAuth::Utils.deep_merge(super, { 'uid' => "ign-" + request.params["username"], 'credentials' => { 'token' => request.params["signature"] }, 'user_info' => user_info, 'extra' => { 'user_hash' => request.params } }) end def user_info { 'nickname' => request.params["username"], } end def js @js = <<-JS $(document).ready(function() { $.ajax({ url: "http://#{@hostname}/users/current.json?callback=z33k", type: "get", dataType:"jsonp", success: function(data) { if(typeof data.error == 'undefined'){ // There is a current My IGN user var username = data.my_ign_username; var signature = data.signature; var timestamp = data.timestamp; window.location = "/auth/ign/callback?username=" +username+"&signature="+signature+"×tamp=" + timestamp; } else{ nouser(); } } }); return false; }); function nouser() { var url = "http://my.ign.com/login?r="+window.location; top.location = url; window.location = url; } JS "\n" + "\n" + "\n" end end end end