Commit 08259dd

mo <mo@mokhan.ca>
2017-11-24 19:06:20
work towards allowing login to mulitiple IDPS.
1 parent c19947a
airport/app/controllers/sessions_controller.rb
@@ -1,19 +1,19 @@
 class SessionsController < ApplicationController
-  skip_before_action :authenticate!, only: [:new]
+  skip_before_action :authenticate!, only: [:new, :create]
 
   def new
-    # HTTP Redirect
-    # * URI
-    # * SigAlg
-    # * Signature
-    # * RelayState
-    redirect_binding = idp.single_sign_on_service_for(binding: :http_redirect)
-    @redirect_uri, _ = redirect_binding.serialize(builder_for(:login), relay_state: relay_state)
-    # HTTP POST
-    # * URI
-    # * SAMLRequest/SAMLResponse
-    post_binding = idp.single_sign_on_service_for(binding: :http_post)
-    @post_uri, @saml_params = post_binding.serialize(builder_for(:login), relay_state: relay_state)
+    @metadatum = Metadatum.all
+  end
+
+  def create
+    if :http_redirect == params[:binding].to_sym
+      redirect_binding = idp.single_sign_on_service_for(binding: :http_redirect)
+      @redirect_uri, _ = redirect_binding.serialize(builder_for(:login), relay_state: relay_state)
+    else
+      post_binding = idp.single_sign_on_service_for(binding: :http_post)
+      @post_uri, @saml_params = post_binding.serialize(builder_for(:login), relay_state: relay_state)
+    end
+    render layout: "spinner"
   end
 
   def destroy
@@ -24,8 +24,8 @@ class SessionsController < ApplicationController
 
   private
 
-  def idp
-    Rails.configuration.x.idp_metadata
+  def idp(entity_id = params[:entity_id])
+    Saml::Kit.configuration.registry.metadata_for(params[:entity_id])
   end
 
   def relay_state
airport/app/models/metadata_registry.rb
@@ -1,20 +0,0 @@
-class MetadataRegistry
-  def register_url(url, verify_ssl: true)
-    content = Saml::Kit::DefaultRegistry::HttpApi.new(url, verify_ssl: verify_ssl).get
-    register(Saml::Kit::Metadata.from(content))
-  end
-
-  def register(metadata)
-    record = Metadatum.find_or_create_by!(issuer: metadata.entity_id)
-    record.metadata = metadata.to_xml
-    record.save!
-    metadata
-  end
-
-  def metadata_for(entity_id)
-    Metadatum.find_by!(issuer: entity_id).to_saml
-  rescue ActiveRecord::RecordNotFound => error
-    Rails.logger.error(error)
-    nil
-  end
-end
airport/app/models/metadatum.rb
@@ -6,4 +6,25 @@ class Metadatum < ApplicationRecord
   def to_saml
     Saml::Kit::Metadata.from(metadata)
   end
+
+  class << self
+    def register_url(url, verify_ssl: true)
+      content = Saml::Kit::DefaultRegistry::HttpApi.new(url, verify_ssl: verify_ssl).get
+      register(Saml::Kit::Metadata.from(content))
+    end
+
+    def register(metadata)
+      record = Metadatum.find_or_create_by!(entity_id: metadata.entity_id)
+      record.metadata = metadata.to_xml
+      record.save!
+      metadata
+    end
+
+    def metadata_for(entity_id)
+      Metadatum.find_by!(entity_id: entity_id).to_saml
+    rescue ActiveRecord::RecordNotFound => error
+      Rails.logger.error(error)
+      nil
+    end
+  end
 end
airport/app/views/registrations/index.html.erb
@@ -6,7 +6,7 @@
         <tbody>
         <% @metadatum.each do |metadata| %>
           <tr>
-            <td><%= link_to metadata.issuer, registration_path(metadata) %></td>
+            <td><%= link_to metadata.entity_id, registration_path(metadata) %></td>
           </tr>
         <% end %>
         </tbody>
airport/app/views/sessions/create.html.erb
@@ -0,0 +1,17 @@
+<% if :http_redirect == params[:binding].to_sym %>
+  <%= javascript_tag do %>
+    window.location.href = '<%= @redirect_uri %>';
+  <% end  %>
+<% else %>
+  <%= form_tag(@post_uri, style: "position: absolute; left: -10000px; top: -10000px;") do %>
+    <%= @saml_params.each do |(key, value)| %>
+      <%= hidden_field_tag key, value %>
+    <% end %>
+  <% end %>
+
+  <%= javascript_tag do %>
+    window.onload = function() {
+      document.forms[0].submit();
+    };
+  <% end %>
+<% end %>
airport/app/views/sessions/new.html.erb
@@ -1,13 +1,10 @@
 <div class="container">
   <div class="row">
     <div class="col">
-      <%= link_to "Log in to IDP via redirect", @redirect_uri %>
-
-      <%= form_tag @post_uri.to_s, method: :post do %>
-        <% @saml_params.each do |(key, value)| %>
-          <%= hidden_field_tag key, value %>
-        <% end %>
-        <%= submit_tag "Log In to IDP via POST" %>
+      <%= form_with url: session_path, data: { remote: false } do |form| %>
+        <%= form.select "entity_id", @metadatum.pluck(:entity_id, :entity_id) %>
+        <%= form.select "binding", [["HTTP Post", :http_post], ["HTTP Redirect", :http_redirect]] %>
+        <%= form.submit "Log In to IDP" %>
       <% end %>
     </div>
   </div>
airport/config/initializers/saml_kit.rb
@@ -1,5 +1,4 @@
 Saml::Kit.configure do |configuration|
   configuration.issuer = ENV['ISSUER']
-  configuration.registry = MetadataRegistry.new
-  Rails.configuration.x.idp_metadata = configuration.registry.register_url("#{ENV['IDP_METADATA_URL']}", verify_ssl: Rails.env.production?)
+  configuration.registry = Metadatum
 end
airport/config/routes.rb
@@ -1,6 +1,6 @@
 Rails.application.routes.draw do
   get "dashboard", to: "dashboard#show", as: :dashboard
-  resource :session, only: [:new, :destroy]
+  resource :session, only: [:new, :create, :destroy]
   resource :assertion, only: [:create, :destroy]
   post "/assertions/consume" => "assertions#create", as: :consume
   post "/assertions/logout" => "assertions#destroy", as: :logout
airport/db/migrate/20171123220807_create_metadata.rb
@@ -1,11 +1,11 @@
 class CreateMetadata < ActiveRecord::Migration[5.1]
   def change
     create_table :metadata do |t|
-      t.string :issuer
+      t.string :entity_id
       t.text :metadata
 
       t.timestamps
     end
-    add_index :metadata, [:issuer], unique: true
+    add_index :metadata, [:entity_id], unique: true
   end
 end
airport/db/schema.rb
@@ -13,11 +13,11 @@
 ActiveRecord::Schema.define(version: 20171123220807) do
 
   create_table "metadata", force: :cascade do |t|
-    t.string "issuer"
+    t.string "entity_id"
     t.text "metadata"
     t.datetime "created_at", null: false
     t.datetime "updated_at", null: false
-    t.index ["issuer"], name: "index_metadata_on_issuer", unique: true
+    t.index ["entity_id"], name: "index_metadata_on_entity_id", unique: true
   end
 
 end
saml-kit/lib/saml/kit/metadata.rb
@@ -50,7 +50,7 @@ module Saml
         document.find_all("/md:EntityDescriptor/md:#{name}/md:#{type}").map do |item|
           binding = item.attribute("Binding").value
           location = item.attribute("Location").value
-          binding_for(binding, location)
+          Saml::Kit::Bindings.create_for(binding, location)
         end
       end
 
@@ -141,10 +141,6 @@ module Saml
         end
         result
       end
-
-      def binding_for(binding, location)
-        Bindings.create_for(binding, location)
-      end
     end
   end
 end