diff --git a/Gemfile b/Gemfile
index 9f336726..8ed611c9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -8,5 +8,5 @@ group :ldap do
 end
 
 group :active_resource do
-  gem "activeresource", ">= 2.3.12", "< 4.0"
+  gem "activeresource", ">= 2.3.12", "< 5.2"
 end
diff --git a/config/config.example.yml b/config/config.example.yml
index f49c5211..772ec4ec 100644
--- a/config/config.example.yml
+++ b/config/config.example.yml
@@ -534,10 +534,14 @@ log:
 #downcase_username: true
 
 # If you'd like to limit the service hosts that can use CAS for authentication,
-# add the individual IPs and IP ranges in CIDR notation below. Leaving this
-# setting blank will allow any server to authenticate users via the CAS server
+# you can either limit specific service URIs (validating the service parameter),
+# or add the individual IPs and IP ranges in CIDR notation below. Leaving these
+# settings blank will allow any server to authenticate users via the CAS server
 # and potentially harvest sensitive user information.
 
+#allowed_service_uris:
+#  - https://myservice.com/login/cas
+
 #allowed_service_ips:
 #  - 127.0.0.1
 #  - 192.168.0.0/24
diff --git a/db/migrate/001_create_initial_structure.rb b/db/migrate/001_create_initial_structure.rb
index e381acf3..efffc022 100644
--- a/db/migrate/001_create_initial_structure.rb
+++ b/db/migrate/001_create_initial_structure.rb
@@ -1,4 +1,4 @@
-class CreateInitialStructure < ActiveRecord::Migration
+class CreateInitialStructure < ActiveRecord::Migration[4.2]
   def self.up
     # Oracle table names cannot exceed 30 chars...
     # See http://code.google.com/p/rubycas-server/issues/detail?id=15
diff --git a/db/migrate/002_add_indexes_for_performance.rb b/db/migrate/002_add_indexes_for_performance.rb
index 680ecf77..454aface 100644
--- a/db/migrate/002_add_indexes_for_performance.rb
+++ b/db/migrate/002_add_indexes_for_performance.rb
@@ -1,4 +1,4 @@
-class AddIndexesForPerformance < ActiveRecord::Migration
+class AddIndexesForPerformance < ActiveRecord::Migration[4.2]
   def self.up
     add_index :casserver_lt,  :ticket
     add_index :casserver_st,  :ticket
diff --git a/lib/casserver/model/consumable.rb b/lib/casserver/model/consumable.rb
index eeb6b62e..6b224b44 100644
--- a/lib/casserver/model/consumable.rb
+++ b/lib/casserver/model/consumable.rb
@@ -18,12 +18,12 @@ def cleanup(max_lifetime, max_unconsumed_lifetime)
                           Time.now - max_lifetime,
                           Time.now - max_unconsumed_lifetime]
                         
-          expired_tickets_count = count(:conditions => conditions)
+          expired_tickets_count = where(conditions).count
 
           $LOG.debug("Destroying #{expired_tickets_count} expired #{self.name.demodulize}"+
             "#{'s' if expired_tickets_count > 1}.") if expired_tickets_count > 0
 
-          destroy_all(conditions)
+          where(conditions).destroy_all
         end
       end
     end
diff --git a/lib/casserver/server.rb b/lib/casserver/server.rb
index 36c9c363..c03f0d98 100644
--- a/lib/casserver/server.rb
+++ b/lib/casserver/server.rb
@@ -322,7 +322,11 @@ def self.init_database!
 
       begin
         if @service
-          if @renew
+          if !service_allowed?(@service)
+            $LOG.warn("Disallowed service '#{@service}'.")
+            @message = {:type => 'mistake',
+                        :message => t.error.disallowed_service}
+          elsif @renew
             $LOG.info("Authentication renew explicitly requested. Proceeding with CAS login for service #{@service.inspect}.")
           elsif tgt && !tgt_error
             $LOG.debug("Valid ticket granting ticket detected.")
@@ -409,6 +413,13 @@ def self.init_database!
         @username.downcase!
       end
 
+      if !@service.blank? && !service_allowed?(@service)
+        @message = {:type => 'mistake',
+                    :message => t.error.disallowed_service}
+        status 400
+        return render @template_engine, :login
+      end
+
       if error = validate_login_ticket(@lt)
         @message = {:type => 'mistake', :message => error}
         # generate another login ticket to allow for re-submitting the form
@@ -532,9 +543,8 @@ def self.init_database!
             st.destroy
           end
 
-          pgts = CASServer::Model::ProxyGrantingTicket.find(:all,
-            :conditions => [CASServer::Model::ServiceTicket.quoted_table_name+".username = ?", tgt.username],
-            :include => :service_ticket)
+          pgts = CASServer::Model::ProxyGrantingTicket.where(casserver_st: { username: tgt.username }).
+              joins(:service_ticket)
           pgts.each do |pgt|
             $LOG.debug("Deleting Proxy-Granting Ticket '#{pgt}' for user '#{pgt.service_ticket.username}'")
             pgt.destroy
@@ -766,6 +776,12 @@ def compile_template(engine, data, options, views)
       super engine, data, options, views
     end
 
+    def service_allowed?(service)
+      allowed_uris = Array(settings.config[:allowed_service_uris])
+
+      allowed_uris.empty? || allowed_uris.include?(service)
+    end
+
     def ip_allowed?(ip)
       require 'ipaddr'
 
diff --git a/locales/en.yml b/locales/en.yml
index 99eb6094..889d07f1 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -9,6 +9,7 @@ error:
   invalid_target_service: "The target service your browser supplied appears to be invalid. Please contact your system administrator for help."
   unable_to_authenticate: "The client and server are unable to negotiate authentication. Please try logging in again later."
   no_service_parameter_given: "The server cannot fulfill this gateway request because no service parameter was given."
+  disallowed_service: "The target service is not allowed to authenticate against this CAS server. Please contact your system administrator for help."
 
 notice:
   logged_in_as: "You are currently logged in as '%1'. If this is not you, please log in below."
diff --git a/rubycas-server.gemspec b/rubycas-server.gemspec
index 2076d106..3d7486a5 100644
--- a/rubycas-server.gemspec
+++ b/rubycas-server.gemspec
@@ -26,17 +26,17 @@ $gemspec = Gem::Specification.new do |s|
   s.has_rdoc = true
   s.post_install_message = "For more information on RubyCAS-Server, see http://rubycas.github.com"
 
-  s.add_dependency("activerecord", ">= 2.3.12", "< 4.0")
-  s.add_dependency("activesupport", ">= 2.3.12", "< 4.0")
+  s.add_dependency("activerecord", ">= 3.0", "< 5.2")
+  s.add_dependency("activesupport", ">= 3.0", "< 5.2")
   s.add_dependency("sinatra", "~> 1.0")
-  s.add_dependency("sinatra-r18n", '~> 1.1.0')
+  s.add_dependency("sinatra-r18n", '~> 2.1.7')
   s.add_dependency("crypt-isaac", "~> 0.9.1")
 
   s.add_development_dependency("rack-test")
   s.add_development_dependency("capybara", '1.1.2')
   s.add_development_dependency("rspec")
   s.add_development_dependency("rspec-core")
-  s.add_development_dependency("rake", "0.8.7")
+  s.add_development_dependency("rake", "~> 11.0")
   s.add_development_dependency("sqlite3", "~> 1.3.1")
   s.add_development_dependency("appraisal", "~> 0.4.1")
   s.add_development_dependency("guard", "~> 1.4.0")
diff --git a/spec/casserver/utils_spec.rb b/spec/casserver/utils_spec.rb
index 33525379..8cafdf5e 100644
--- a/spec/casserver/utils_spec.rb
+++ b/spec/casserver/utils_spec.rb
@@ -11,13 +11,15 @@ module CASServer
   let(:params_with_password_filtered) { { 'password' => '******' } }
 
   it 'should log the controller action' do
-    $LOG.should_receive(:debug).with 'Processing application::instance_eval {}'
+    $LOG.should_receive(:<<).with "\n"
+    $LOG.should_receive(:debug).with 'Processing application::instance_exec {}'
 
     subject.log_controller_action('application', params)
   end
 
   it 'should filter password parameters in the log' do
-    $LOG.should_receive(:debug).with "Processing application::instance_eval #{params_with_password_filtered.inspect}"
+    $LOG.should_receive(:<<).with "\n"
+    $LOG.should_receive(:debug).with "Processing application::instance_exec #{params_with_password_filtered.inspect}"
 
     subject.log_controller_action('application', params_with_password)
   end
diff --git a/spec/casserver_spec.rb b/spec/casserver_spec.rb
index b49c1a03..ba81a740 100644
--- a/spec/casserver_spec.rb
+++ b/spec/casserver_spec.rb
@@ -36,6 +36,18 @@
       page.should have_content("You have successfully logged in")
     end
 
+    it "auto-forwards when you're already logged in" do
+      visit "/login"
+
+      fill_in 'username', :with => VALID_USERNAME
+      fill_in 'password', :with => VALID_PASSWORD
+      click_button 'login-submit'
+
+      visit "/login?service="+CGI.escape(@target_service)
+
+      page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
+    end
+
     it "fails to log in with invalid password" do
       visit "/login"
       fill_in 'username', :with => VALID_USERNAME
@@ -92,6 +104,38 @@
       #page.should have_xpath("<script>alert(32)</script>")
     end
 
+    describe 'service_uri validation' do
+      let(:service) { 'http://imposter.com/' }
+
+      it "doesn't redirect back to untrusted services" do
+        visit "/login?service="+CGI.escape(service)
+
+        page.should have_content("The target service is not allowed")
+
+        fill_in 'username', :with => VALID_USERNAME
+        fill_in 'password', :with => VALID_PASSWORD
+
+        click_button 'login-submit'
+
+        page.should have_content("The target service is not allowed")
+      end
+
+      it "doesn't redirect back when already logged in" do
+        visit "/login"
+
+        fill_in 'username', :with => VALID_USERNAME
+        fill_in 'password', :with => VALID_PASSWORD
+
+        click_button 'login-submit'
+
+        visit "/login?service="+CGI.escape(service)
+
+        page.should have_content("The target service is not allowed")
+      end
+
+    end
+
+
   end # describe '/login'
 
 
diff --git a/spec/config/default_config.yml b/spec/config/default_config.yml
index 90a83914..aa7180ca 100644
--- a/spec/config/default_config.yml
+++ b/spec/config/default_config.yml
@@ -50,4 +50,7 @@ enable_single_sign_out: true
 #downcase_username: true
 
 allowed_service_ips:
-  - 127.0.0.0/24
\ No newline at end of file
+  - 127.0.0.0/24
+
+allowed_service_uris:
+  - http://my.app.test