Commit 7b1abe4

mo <mo.khan@gmail.com>
2017-11-20 01:53:29
try to handle invalid credentials entry.
1 parent 42730b8
Changed files (2)
app
controllers
views
app/controllers/sessions_controller.rb
@@ -1,37 +1,39 @@
 class SessionsController < ApplicationController
   skip_before_action :verify_authenticity_token, only: [:new, :destroy]
-  before_action :load_saml_request, only: [:new, :create, :destroy]
+  before_action :saml_request, only: [:new, :create, :destroy]
   rescue_from ActiveRecord::RecordInvalid do |error|
     render_error(:forbidden, model: error.record)
   end
 
   def new
-    session[:SAMLRequest] ||= params[:SAMLRequest]
-    session[:RelayState] ||= params[:RelayState]
+    @raw_params = raw_params
+    session[:request_binding] = request.post? ? :post : :http_redirect
   end
 
   def create
     if user = User.login(user_params[:email], user_params[:password])
       reset_session
       session[:user_id] = user.id
-      response_binding = @saml_request.provider.assertion_consumer_service_for(binding: :post)
-      @url, @saml_params = response_binding.serialize(@saml_request.response_for(user), relay_state: session[:RelayState])
+      response_binding = saml_request.provider.assertion_consumer_service_for(binding: :post)
+      saml_response = saml_request.response_for(user)
+      @url, @saml_params = response_binding.serialize(saml_response, relay_state: saml_params[:RelayState])
       render layout: "spinner"
     else
-      redirect_to new_session_path, error: "Invalid Credentials"
+      @raw_params = raw_params
+      flash[:error] = "Invalid Credentials"
+      render :new
     end
   end
 
   def destroy
-    if params['SAMLRequest'].present?
-      saml_request = load_saml_request
+    if saml_params[:SAMLRequest].present?
       user = User.find_by(uuid: saml_request.name_id)
       response_binding = saml_request.provider.single_logout_service_for(binding: :post)
       saml_response = saml_request.response_for(user)
-      @url, @saml_params = response_binding.serialize(saml_response, relay_state: params[:RelayState])
+      @url, @saml_params = response_binding.serialize(saml_response, relay_state: saml_params[:RelayState])
       reset_session
       render layout: "spinner"
-    elsif params['SAMLResponse'].present?
+    elsif saml_params[:SAMLResponse].present?
     else
     end
   end
@@ -42,24 +44,31 @@ class SessionsController < ApplicationController
     params.require(:user).permit(:email, :password)
   end
 
-  def load_saml_request
-    @saml_request = request_binding_for(request).deserialize(raw_params_for(request))
-    raise ActiveRecord::RecordInvalid.new(@saml_request) if @saml_request.invalid?
-    @saml_request
+  def saml_params
+    params.permit(:SAMLRequest, :SAMLResponse, :SAMLEncoding, :SigAlg, :Signature)
+  end
+
+  def saml_request
+    @saml_request ||= request_binding.deserialize(raw_params).tap do |saml_request|
+      if saml_request.invalid?
+        raise ActiveRecord::RecordInvalid.new(saml_request)
+      end
+    end
   end
 
   def idp
     Idp.default(request)
   end
 
-  def request_binding_for(request)
-    target_binding = request.post? ? :post : :http_redirect
+  def request_binding
+    target_binding = session[:request_binding]
+    target_binding = target_binding || (request.post? ? :post : :http_redirect)
     idp.single_sign_on_service_for(binding: target_binding)
   end
 
-  def raw_params_for(request)
+  def raw_params
     if request.post?
-      request.params
+      saml_params
     else
       Hash[request.query_string.split("&").map { |x| x.split("=", 2) }]
     end
app/views/sessions/new.html.erb
@@ -9,8 +9,9 @@
         <div class="form-group">
           <%= form.password_field :password, class: 'form-control', placeholder: User.human_attribute_name(:password), required: :required %>
         </div>
-        <%= hidden_field_tag :SAMLRequest, params[:SAMLRequest] %>
-        <%= hidden_field_tag :RelayState, params[:RelayState] %>
+        <% @raw_params.each_pair do |key, value| %>
+          <%= hidden_field_tag key, value %>
+        <% end %>
         <%= form.button t('.login'), type: 'submit', class: 'btn btn-primary', data: { disable_with: t('.loading') } %>
       <% end %>
     </div>