Commit 2b0491d

mo <mo.khan@gmail.com>
2017-12-24 05:57:39
reduce coupling from idp metadata.
1 parent 913910d
Changed files (3)
app/controllers/concerns/saml_respondable.rb
@@ -1,6 +1,14 @@
 module SamlRespondable
   extend ActiveSupport::Concern
 
+  def binding_for(binding, location)
+    if binding == :http_post
+      Saml::Kit::Bindings::HttpPost.new(location: location)
+    else
+      Saml::Kit::Bindings::HttpRedirect.new(location: location)
+    end
+  end
+
   def saml_params(allowed_params = [:SAMLRequest, :SAMLResponse, :SAMLEncoding, :SigAlg, :Signature, :RelayState])
     @saml_params ||=
       if request.post?
app/controllers/sessions_controller.rb
@@ -2,32 +2,32 @@ class SessionsController < ApplicationController
   skip_before_action :verify_authenticity_token, only: [:new, :destroy]
 
   def new
-    target_binding = request.post? ? :http_post : :http_redirect
-    binding = idp.single_sign_on_service_for(binding: target_binding)
+    binding = binding_for(request.post? ? :http_post : :http_redirect, new_session_url)
     @saml_request = binding.deserialize(saml_params)
     if @saml_request.valid?
-      session[:saml] = { params: saml_params.to_h, binding: target_binding }
+      session[:saml] = { params: saml_params.to_h, xml: @saml_request.to_xml }
       return post_back(@saml_request, current_user) if current_user?
     else
-      logger.error(@saml_request.errors.full_messages)
-      return render_error(:forbidden, model: @saml_request)
+      render_error(:forbidden, model: @saml_request)
     end
   rescue => error
     logger.error(error)
   end
 
   def create
+    user_params = params.require(:user).permit(:email, :password)
     if user = User.login(user_params[:email], user_params[:password])
       unless session[:saml].present?
         login(user)
         return redirect_to(dashboard_path)
       end
 
-      binding = idp.single_sign_on_service_for(binding: session[:saml][:binding])
-      saml_request = binding.deserialize(session[:saml][:params])
-      return render_error(:forbidden, model: saml_request) if saml_request.invalid?
-
-      post_back(saml_request, user)
+      saml_request = Saml::Kit::AuthenticationRequest.new(session[:saml][:xml])
+      if saml_request.invalid?
+        render_error(:forbidden, model: saml_request)
+      else
+        post_back(saml_request, user)
+      end
     else
       flash[:error] = "Invalid Credentials"
       render :new
@@ -36,7 +36,7 @@ class SessionsController < ApplicationController
 
   def destroy
     if saml_params[:SAMLRequest].present?
-      binding = Saml::Kit::Bindings::HttpPost.new(location: session_url)
+      binding = binding_for(:http_post, session_url)
       saml_request = binding.deserialize(saml_params).tap do |saml|
         raise ActiveRecord::RecordInvalid.new(saml) if saml.invalid?
       end
@@ -53,14 +53,6 @@ class SessionsController < ApplicationController
 
   private
 
-  def user_params
-    params.require(:user).permit(:email, :password)
-  end
-
-  def idp
-    Idp.default(request)
-  end
-
   def post_back(saml_request, user)
     relay_state = session[:saml][:params][:RelayState]
     @url, @saml_params = saml_request.response_for(user, binding: :http_post, relay_state: relay_state) do |builder|
spec/requests/sessions_controller_spec.rb
@@ -35,7 +35,8 @@ describe SessionsController do
 
         expect(response).to have_http_status(:ok)
         expect(session[:saml]).to be_present
-        expect(session[:saml][:binding]).to eql(:http_post)
+        expect(session[:saml][:params]).to be_present
+        expect(session[:saml][:xml]).to be_present
       end
 
       it 'generates a response for the user when they are already logged in' do
@@ -50,7 +51,7 @@ describe SessionsController do
         expect(response.body).to include("Sending Response to Service Provider")
       end
 
-      it 'renders a login page when their is no SAML Request' do
+      it 'renders a login page when there is no SAML Request' do
         post '/session/new'
         expect(response).to have_http_status(:ok)
         expect(response.body).to include("Login")