From 03136747dd80e8b9ded81a61e03e72e9c4beac11 Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 27 Feb 2025 13:56:52 -0700 Subject: Move src file to bin dir --- bin/sp | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100755 bin/sp (limited to 'bin/sp') diff --git a/bin/sp b/bin/sp new file mode 100755 index 00000000..68a0e3db --- /dev/null +++ b/bin/sp @@ -0,0 +1,147 @@ +#!/usr/bin/env ruby + +# Start the server by running: +# +# $ ruby main.rb + +require "bundler/inline" +gemfile do + source "https://rubygems.org" + + gem "base64", "~> 0.1" + gem "erb", "~> 4.0" + gem "rack", "~> 3.0" + gem "rackup", "~> 2.0" + gem "saml-kit", "~> 1.0" + gem "webrick", "~> 1.0" +end + +class OnDemandRegistry < Saml::Kit::DefaultRegistry + def metadata_for(entity_id) + found = super(entity_id) + return found if found + + register_url(entity_id, verify_ssl: false) + super(entity_id) + end +end + +Saml::Kit.configure do |x| + x.entity_id = "http://localhost:8283/metadata.xml" + x.registry = OnDemandRegistry.new + x.logger = Logger.new("/dev/stderr") +end + +class ServiceProvider + def initialize + @storage = {} + end + + # Download IDP Metadata + # + # GET /metadata.xml + def metadata + xml = Saml::Kit::Metadata.build_xml do |builder| + builder.embed_signature = false + builder.contact_email = 'hi@example.com' + builder.organization_name = "Acme, Inc" + builder.organization_url = "https://example.com" + builder.build_service_provider do |x| + x.name_id_formats = [Saml::Kit::Namespaces::EMAIL_ADDRESS] + x.add_assertion_consumer_service("http://localhost:8283/assertions", binding: :http_post) + end + end + + [200, { 'Content-Type' => "application/samlmetadata+xml" }, [xml]] + end + + def call(env) + path = env['PATH_INFO'] + case env['REQUEST_METHOD'] + when 'GET' + case path + when "/metadata.xml" + return metadata + else + # TODO Generate a post to the IdP + return post_to_idp(Rack::Request.new(env)) + end + when 'POST' + case path + when "/assertions" + # TODO:: Render the SAMLResponse from the IdP + return assertions(Rack::Request.new(env)) + else + return not_found + end + end + not_found + end + + private + + def not_found + [404, {}, []] + end + + def post_to_idp(request) + idp = Saml::Kit.registry.metadata_for('http://localhost:8282/metadata.xml') + relay_state = Base64.strict_encode64(JSON.generate(redirect_to: '/dashboard')) + + @saml_builder = nil + uri, saml_params = idp.login_request_for(binding: :http_post, relay_state: relay_state) do |builder| + @saml_builder = builder + end + + template = <<~ERB + + + + +

Sending SAML Request (SP -> IdP)

+ + +
+ <%- saml_params.each do |(key, value)| -%> + + <%- end -%> + +
+ + + ERB + erb = ERB.new(template, nil, trim_mode: '-') + html = erb.result(binding) + [200, { 'Content-Type' => "text/html" }, [html]] + end + + def assertions(request) + sp = Saml::Kit.registry.metadata_for('http://localhost:8283/metadata.xml') + saml_binding = sp.assertion_consumer_service_for(binding: :http_post) + saml_response = saml_binding.deserialize(request.params) + raise saml_response.errors unless saml_response.valid? + + template = <<~ERB + + + + +

Received SAML Response

+ + + + ERB + erb = ERB.new(template, nil, trim_mode: '-') + html = erb.result(binding) + [200, { 'Content-Type' => "text/html" }, [html]] + end +end + +if __FILE__ == $0 + app = Rack::Builder.new do + use Rack::Reloader + run ServiceProvider.new + end.to_app + + Rackup::Server.start(app: app, Port: 8283) +end -- cgit v1.2.3