saml2ruby 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +19 -0
- data/Rakefile +111 -0
- data/TODO +3 -0
- data/examples/rails/SimpleSAMLRP/app/controllers/account_controller.rb +74 -0
- data/examples/rails/SimpleSAMLRP/app/controllers/application.rb +7 -0
- data/examples/rails/SimpleSAMLRP/app/helpers/account_helper.rb +2 -0
- data/examples/rails/SimpleSAMLRP/app/helpers/application_helper.rb +3 -0
- data/examples/rails/SimpleSAMLRP/config/boot.rb +45 -0
- data/examples/rails/SimpleSAMLRP/config/environment.rb +56 -0
- data/examples/rails/SimpleSAMLRP/config/environments/development.rb +21 -0
- data/examples/rails/SimpleSAMLRP/config/environments/production.rb +18 -0
- data/examples/rails/SimpleSAMLRP/config/environments/test.rb +19 -0
- data/examples/rails/SimpleSAMLRP/config/routes.rb +23 -0
- data/examples/rails/SimpleSAMLRP/public/dispatch.rb +10 -0
- data/examples/rails/SimpleSAMLRP/test/functional/account_controller_test.rb +18 -0
- data/examples/rails/SimpleSAMLRP/test/test_helper.rb +28 -0
- data/lib/saml2ruby.rb +1 -0
- data/lib/saml_2_ruby.rb +5 -0
- data/lib/saml_2_ruby/relying_party.rb +170 -0
- data/lib/saml_2_ruby/version.rb +9 -0
- data/lib/saml_2_ruby/xml_sec.rb +111 -0
- data/test/xml_sec_test.rb +62 -0
- metadata +86 -0
data/README
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
=Ruby SAML2
|
2
|
+
|
3
|
+
Grabbed from https://opensso.dev.java.net/source/browse/opensso/extensions/saml2ruby/source/
|
4
|
+
|
5
|
+
A Ruby library for SAML 2.0
|
6
|
+
|
7
|
+
==Features
|
8
|
+
* Easy to use API for acting as a SAML 2.0 relying party.
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/packagetask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
|
7
|
+
require File.join(File.dirname(__FILE__), '/lib/saml_2_ruby/version')
|
8
|
+
|
9
|
+
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
10
|
+
PKG_NAME = 'saml2ruby'
|
11
|
+
PKG_VERSION = SAML::VERSION::STRING + PKG_BUILD
|
12
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
13
|
+
PKG_DESTINATION = ENV["PKG_DESTINATION"] || "../#{PKG_NAME}"
|
14
|
+
|
15
|
+
RELEASE_NAME = "REL #{PKG_VERSION}"
|
16
|
+
|
17
|
+
PKG_FILES = FileList[
|
18
|
+
#'CHANGELOG',
|
19
|
+
#'LICENSE',
|
20
|
+
'README',
|
21
|
+
#'TODO',
|
22
|
+
'Rakefile',
|
23
|
+
'bin/**/*',
|
24
|
+
'doc/**/*',
|
25
|
+
'lib/**/*',
|
26
|
+
] - [ 'test' ]
|
27
|
+
|
28
|
+
require 'rubygems'
|
29
|
+
begin
|
30
|
+
require 'jeweler'
|
31
|
+
Jeweler::Tasks.new do |gemspec|
|
32
|
+
gemspec.name = "saml2ruby"
|
33
|
+
gemspec.summary = "Ruby implementation of the SAML 2.0 Specification"
|
34
|
+
gemspec.description = %Q{Part of the OpenSSO extension set. Writting by the wonderful guys over at Sun. Moved it over to a github repo and turned it into a rubygem.}
|
35
|
+
gemspec.email = ["scashin133@gmail.com"]
|
36
|
+
gemspec.homepage = "http://github.com/scashin133/saml2ruby"
|
37
|
+
gemspec.authors = ["Sean Cashin"]
|
38
|
+
gemspec.add_dependency('XMLCanonicalizer', '>=1.0.1')
|
39
|
+
gemspec.version = PKG_VERSION
|
40
|
+
gemspec.files = PKG_FILES.to_a
|
41
|
+
end
|
42
|
+
Jeweler::GemcutterTasks.new
|
43
|
+
rescue LoadError
|
44
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
desc 'Default: run unit tests.'
|
49
|
+
task :default => :test
|
50
|
+
|
51
|
+
desc 'Test the library.'
|
52
|
+
Rake::TestTask.new(:test) do |t|
|
53
|
+
t.libs << 'lib'
|
54
|
+
test_files = FileList['test/**/*_test.rb']
|
55
|
+
t.test_files = test_files
|
56
|
+
t.verbose = true
|
57
|
+
end
|
58
|
+
|
59
|
+
desc 'Generate documentation for the library.'
|
60
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
61
|
+
rdoc.rdoc_dir = 'rdoc'
|
62
|
+
rdoc.title = 'RSAML'
|
63
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
64
|
+
rdoc.rdoc_files.include('README')
|
65
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
66
|
+
end
|
67
|
+
|
68
|
+
namespace :rcov do
|
69
|
+
desc 'Measures test coverage'
|
70
|
+
task :test do
|
71
|
+
rm_f 'coverage.data'
|
72
|
+
mkdir 'coverage' unless File.exist?('coverage')
|
73
|
+
rcov = "rcov --aggregate coverage.data --text-summary -Ilib"
|
74
|
+
system("#{rcov} test/*_test.rb")
|
75
|
+
#system("open coverage/index.html") if PLATFORM['darwin']
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "Generate code statistics"
|
80
|
+
task :lines do
|
81
|
+
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
|
82
|
+
|
83
|
+
for file_name in FileList["lib/**/*.rb"]
|
84
|
+
next if file_name =~ /vendor/
|
85
|
+
f = File.open(file_name)
|
86
|
+
|
87
|
+
while line = f.gets
|
88
|
+
lines += 1
|
89
|
+
next if line =~ /^\s*$/
|
90
|
+
next if line =~ /^\s*#/
|
91
|
+
codelines += 1
|
92
|
+
end
|
93
|
+
puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
|
94
|
+
|
95
|
+
total_lines += lines
|
96
|
+
total_codelines += codelines
|
97
|
+
|
98
|
+
lines, codelines = 0, 0
|
99
|
+
end
|
100
|
+
|
101
|
+
puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
|
102
|
+
end
|
103
|
+
|
104
|
+
desc "Reinstall the gem from a local package copy"
|
105
|
+
task :reinstall => [:package] do
|
106
|
+
windows = RUBY_PLATFORM =~ /mswin/
|
107
|
+
sudo = windows ? '' : 'sudo'
|
108
|
+
gem = windows ? 'gem.bat' : 'gem'
|
109
|
+
`#{sudo} #{gem} uninstall -x -i #{PKG_NAME}`
|
110
|
+
`#{sudo} #{gem} install pkg/#{PKG_NAME}-#{PKG_VERSION}`
|
111
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# The contents of this file are subject to the terms
|
2
|
+
# of the Common Development and Distribution License
|
3
|
+
# (the License). You may not use this file except in
|
4
|
+
# compliance with the License.
|
5
|
+
#
|
6
|
+
# You can obtain a copy of the License at
|
7
|
+
# https://opensso.dev.java.net/public/CDDLv1.0.html or
|
8
|
+
# opensso/legal/CDDLv1.0.txt
|
9
|
+
# See the License for the specific language governing
|
10
|
+
# permission and limitations under the License.
|
11
|
+
#
|
12
|
+
# When distributing Covered Code, include this CDDL
|
13
|
+
# Header Notice in each file and include the License file
|
14
|
+
# at opensso/legal/CDDLv1.0.txt.
|
15
|
+
# If applicable, add the following below the CDDL Header,
|
16
|
+
# with the fields enclosed by brackets [] replaced by
|
17
|
+
# your own identifying information:
|
18
|
+
# "Portions Copyrighted [year] [name of copyright owner]"
|
19
|
+
#
|
20
|
+
# $Id: account_controller.rb,v 1.1 2007/03/20 05:26:56 todddd Exp $
|
21
|
+
#
|
22
|
+
# Copyright 2007 Sun Microsystems Inc. All Rights Reserved
|
23
|
+
# Portions Copyrighted 2007 Todd W Saxton.
|
24
|
+
|
25
|
+
require "pathname"
|
26
|
+
require "cgi"
|
27
|
+
require "saml2ruby"
|
28
|
+
|
29
|
+
|
30
|
+
class AccountController < ApplicationController
|
31
|
+
|
32
|
+
def login
|
33
|
+
relying_party = SAML::RelyingParty.new(
|
34
|
+
:assertion_consumer_service_URL => "http://localhost:3008/account/complete",
|
35
|
+
:issuer => "localhost_ruby",
|
36
|
+
:sp_name_qualifier => "localhost_ruby",
|
37
|
+
:idp_sso_target_url => "http://localhost:8080/openfm-samples-ip/SSORedirect/metaAlias/ip_meta_alias",
|
38
|
+
:idp_slo_target_url => "http://localhost:8080/openfm-samples-ip/IDPSloRedirect/metaAlias/ip_meta_alias",
|
39
|
+
:idp_cert_fingerprint => "93:bd:43:a4:60:65:a4:05:95:98:a9:d8:f4:8b:4c:c8:5f:31:87:e9"
|
40
|
+
)
|
41
|
+
relying_party.logger = logger
|
42
|
+
session[:relying_party] = relying_party
|
43
|
+
request = relying_party.create_auth_request
|
44
|
+
redirect_to(request)
|
45
|
+
end
|
46
|
+
|
47
|
+
def complete
|
48
|
+
|
49
|
+
if params[:SAMLResponse].empty?
|
50
|
+
flash[:notice] = 'Unknown response from SAML server.'
|
51
|
+
redirect_to :action => 'index'
|
52
|
+
end
|
53
|
+
|
54
|
+
valid_flag = session[:relying_party].process_auth_response(params[:SAMLResponse])
|
55
|
+
|
56
|
+
if valid_flag
|
57
|
+
redirect_to :action => "welcome"
|
58
|
+
else
|
59
|
+
flash[:notice] = 'invalid SAML Response.'
|
60
|
+
redirect_to :action => "index"
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def logout
|
66
|
+
|
67
|
+
request = session[:relying_party].create_logout_request
|
68
|
+
session[:relying_party] = nil
|
69
|
+
|
70
|
+
redirect_to(request)
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Filters added to this controller apply to all controllers in the application.
|
2
|
+
# Likewise, all the methods added will be available for all controllers.
|
3
|
+
|
4
|
+
class ApplicationController < ActionController::Base
|
5
|
+
# Pick a unique cookie name to distinguish our session data from others'
|
6
|
+
session :session_key => '_SimpleSAMLRP_session_id'
|
7
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb
|
2
|
+
|
3
|
+
unless defined?(RAILS_ROOT)
|
4
|
+
root_path = File.join(File.dirname(__FILE__), '..')
|
5
|
+
|
6
|
+
unless RUBY_PLATFORM =~ /mswin32/
|
7
|
+
require 'pathname'
|
8
|
+
root_path = Pathname.new(root_path).cleanpath(true).to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
RAILS_ROOT = root_path
|
12
|
+
end
|
13
|
+
|
14
|
+
unless defined?(Rails::Initializer)
|
15
|
+
if File.directory?("#{RAILS_ROOT}/vendor/rails")
|
16
|
+
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
|
17
|
+
else
|
18
|
+
require 'rubygems'
|
19
|
+
|
20
|
+
environment_without_comments = IO.readlines(File.dirname(__FILE__) + '/environment.rb').reject { |l| l =~ /^#/ }.join
|
21
|
+
environment_without_comments =~ /[^#]RAILS_GEM_VERSION = '([\d.]+)'/
|
22
|
+
rails_gem_version = $1
|
23
|
+
|
24
|
+
if version = defined?(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : rails_gem_version
|
25
|
+
# Asking for 1.1.6 will give you 1.1.6.5206, if available -- makes it easier to use beta gems
|
26
|
+
rails_gem = Gem.cache.search('rails', "~>#{version}.0").sort_by { |g| g.version.version }.last
|
27
|
+
|
28
|
+
if rails_gem
|
29
|
+
require_gem "rails", "=#{rails_gem.version.version}"
|
30
|
+
require rails_gem.full_gem_path + '/lib/initializer'
|
31
|
+
else
|
32
|
+
STDERR.puts %(Cannot find gem for Rails ~>#{version}.0:
|
33
|
+
Install the missing gem with 'gem install -v=#{version} rails', or
|
34
|
+
change environment.rb to define RAILS_GEM_VERSION with your desired version.
|
35
|
+
)
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
else
|
39
|
+
require_gem "rails"
|
40
|
+
require 'initializer'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Rails::Initializer.run(:set_load_path)
|
45
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Be sure to restart your web server when you modify this file.
|
2
|
+
|
3
|
+
# Uncomment below to force Rails into production mode when
|
4
|
+
# you don't control web/app server and can't set it the proper way
|
5
|
+
# ENV['RAILS_ENV'] ||= 'production'
|
6
|
+
|
7
|
+
# Specifies gem version of Rails to use when vendor/rails is not present
|
8
|
+
RAILS_GEM_VERSION = '1.1.6' unless defined? RAILS_GEM_VERSION
|
9
|
+
|
10
|
+
# Bootstrap the Rails environment, frameworks, and default configuration
|
11
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
12
|
+
|
13
|
+
Rails::Initializer.run do |config|
|
14
|
+
# Settings in config/environments/* take precedence over those specified here
|
15
|
+
|
16
|
+
# Skip frameworks you're not going to use (only works if using vendor/rails)
|
17
|
+
# config.frameworks -= [ :action_web_service, :action_mailer ]
|
18
|
+
|
19
|
+
# Only load the plugins named here, by default all plugins in vendor/plugins are loaded
|
20
|
+
# config.plugins = %W( exception_notification ssl_requirement )
|
21
|
+
|
22
|
+
# Add additional load paths for your own custom dirs
|
23
|
+
# config.load_paths += %W( #{RAILS_ROOT}/extras )
|
24
|
+
|
25
|
+
# Force all environments to use the same logger level
|
26
|
+
# (by default production uses :info, the others :debug)
|
27
|
+
# config.log_level = :debug
|
28
|
+
|
29
|
+
# Use the database for sessions instead of the file system
|
30
|
+
# (create the session table with 'rake db:sessions:create')
|
31
|
+
# config.action_controller.session_store = :active_record_store
|
32
|
+
|
33
|
+
# Use SQL instead of Active Record's schema dumper when creating the test database.
|
34
|
+
# This is necessary if your schema can't be completely dumped by the schema dumper,
|
35
|
+
# like if you have constraints or database-specific column types
|
36
|
+
# config.active_record.schema_format = :sql
|
37
|
+
|
38
|
+
# Activate observers that should always be running
|
39
|
+
# config.active_record.observers = :cacher, :garbage_collector
|
40
|
+
|
41
|
+
# Make Active Record use UTC-base instead of local time
|
42
|
+
# config.active_record.default_timezone = :utc
|
43
|
+
|
44
|
+
# See Rails::Configuration for more options
|
45
|
+
end
|
46
|
+
|
47
|
+
# Add new inflection rules using the following format
|
48
|
+
# (all these examples are active by default):
|
49
|
+
# Inflector.inflections do |inflect|
|
50
|
+
# inflect.plural /^(ox)$/i, '\1en'
|
51
|
+
# inflect.singular /^(ox)en/i, '\1'
|
52
|
+
# inflect.irregular 'person', 'people'
|
53
|
+
# inflect.uncountable %w( fish sheep )
|
54
|
+
# end
|
55
|
+
|
56
|
+
# Include your application configuration below
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Settings specified here will take precedence over those in config/environment.rb
|
2
|
+
|
3
|
+
# In the development environment your application's code is reloaded on
|
4
|
+
# every request. This slows down response time but is perfect for development
|
5
|
+
# since you don't have to restart the webserver when you make code changes.
|
6
|
+
config.cache_classes = false
|
7
|
+
|
8
|
+
# Log error messages when you accidentally call methods on nil.
|
9
|
+
config.whiny_nils = true
|
10
|
+
|
11
|
+
# Enable the breakpoint server that script/breakpointer connects to
|
12
|
+
config.breakpoint_server = true
|
13
|
+
|
14
|
+
# Show full error reports and disable caching
|
15
|
+
config.action_controller.consider_all_requests_local = true
|
16
|
+
config.action_controller.perform_caching = false
|
17
|
+
config.action_view.cache_template_extensions = false
|
18
|
+
config.action_view.debug_rjs = true
|
19
|
+
|
20
|
+
# Don't care if the mailer can't send
|
21
|
+
config.action_mailer.raise_delivery_errors = false
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Settings specified here will take precedence over those in config/environment.rb
|
2
|
+
|
3
|
+
# The production environment is meant for finished, "live" apps.
|
4
|
+
# Code is not reloaded between requests
|
5
|
+
config.cache_classes = true
|
6
|
+
|
7
|
+
# Use a different logger for distributed setups
|
8
|
+
# config.logger = SyslogLogger.new
|
9
|
+
|
10
|
+
# Full error reports are disabled and caching is turned on
|
11
|
+
config.action_controller.consider_all_requests_local = false
|
12
|
+
config.action_controller.perform_caching = true
|
13
|
+
|
14
|
+
# Enable serving of images, stylesheets, and javascripts from an asset server
|
15
|
+
# config.action_controller.asset_host = "http://assets.example.com"
|
16
|
+
|
17
|
+
# Disable delivery errors, bad email addresses will be ignored
|
18
|
+
# config.action_mailer.raise_delivery_errors = false
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Settings specified here will take precedence over those in config/environment.rb
|
2
|
+
|
3
|
+
# The test environment is used exclusively to run your application's
|
4
|
+
# test suite. You never need to work with it otherwise. Remember that
|
5
|
+
# your test database is "scratch space" for the test suite and is wiped
|
6
|
+
# and recreated between test runs. Don't rely on the data there!
|
7
|
+
config.cache_classes = true
|
8
|
+
|
9
|
+
# Log error messages when you accidentally call methods on nil.
|
10
|
+
config.whiny_nils = true
|
11
|
+
|
12
|
+
# Show full error reports and disable caching
|
13
|
+
config.action_controller.consider_all_requests_local = true
|
14
|
+
config.action_controller.perform_caching = false
|
15
|
+
|
16
|
+
# Tell ActionMailer not to deliver emails to the real world.
|
17
|
+
# The :test delivery method accumulates sent emails in the
|
18
|
+
# ActionMailer::Base.deliveries array.
|
19
|
+
config.action_mailer.delivery_method = :test
|
@@ -0,0 +1,23 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
# The priority is based upon order of creation: first created -> highest priority.
|
3
|
+
|
4
|
+
# Sample of regular route:
|
5
|
+
# map.connect 'products/:id', :controller => 'catalog', :action => 'view'
|
6
|
+
# Keep in mind you can assign values other than :controller and :action
|
7
|
+
|
8
|
+
# Sample of named route:
|
9
|
+
# map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
|
10
|
+
# This route can be invoked with purchase_url(:id => product.id)
|
11
|
+
|
12
|
+
# You can have the root of your site routed by hooking up ''
|
13
|
+
# -- just remember to delete public/index.html.
|
14
|
+
# map.connect '', :controller => "welcome"
|
15
|
+
|
16
|
+
# Allow downloading Web Service WSDL as a file with an extension
|
17
|
+
# instead of a file named 'wsdl'
|
18
|
+
map.connect ':controller/service.wsdl', :action => 'wsdl'
|
19
|
+
|
20
|
+
# Install the default route as the lowest priority.
|
21
|
+
map.connect ':controller/:action/:id.:format'
|
22
|
+
map.connect ':controller/:action/:id'
|
23
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!c:/ruby/bin/ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
|
4
|
+
|
5
|
+
# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
|
6
|
+
# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
|
7
|
+
require "dispatcher"
|
8
|
+
|
9
|
+
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
|
10
|
+
Dispatcher.dispatch
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'account_controller'
|
3
|
+
|
4
|
+
# Re-raise errors caught by the controller.
|
5
|
+
class AccountController; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
class AccountControllerTest < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
@controller = AccountController.new
|
10
|
+
@request = ActionController::TestRequest.new
|
11
|
+
@response = ActionController::TestResponse.new
|
12
|
+
end
|
13
|
+
|
14
|
+
# Replace this with your real tests.
|
15
|
+
def test_truth
|
16
|
+
assert true
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
|
3
|
+
require 'test_help'
|
4
|
+
|
5
|
+
class Test::Unit::TestCase
|
6
|
+
# Transactional fixtures accelerate your tests by wrapping each test method
|
7
|
+
# in a transaction that's rolled back on completion. This ensures that the
|
8
|
+
# test database remains unchanged so your fixtures don't have to be reloaded
|
9
|
+
# between every test method. Fewer database queries means faster tests.
|
10
|
+
#
|
11
|
+
# Read Mike Clark's excellent walkthrough at
|
12
|
+
# http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
|
13
|
+
#
|
14
|
+
# Every Active Record database supports transactions except MyISAM tables
|
15
|
+
# in MySQL. Turn off transactional fixtures in this case; however, if you
|
16
|
+
# don't care one way or the other, switching from MyISAM to InnoDB tables
|
17
|
+
# is recommended.
|
18
|
+
self.use_transactional_fixtures = true
|
19
|
+
|
20
|
+
# Instantiated fixtures are slow, but give you @david where otherwise you
|
21
|
+
# would need people(:david). If you don't want to migrate your existing
|
22
|
+
# test cases which use the @david style and don't mind the speed hit (each
|
23
|
+
# instantiated fixtures translates to a database query per test method),
|
24
|
+
# then set this back to true.
|
25
|
+
self.use_instantiated_fixtures = false
|
26
|
+
|
27
|
+
# Add more helper methods to be used by all tests here...
|
28
|
+
end
|
data/lib/saml2ruby.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'saml_2_ruby'
|
data/lib/saml_2_ruby.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
# The contents of this file are subject to the terms
|
2
|
+
# of the Common Development and Distribution License
|
3
|
+
# (the License). You may not use this file except in
|
4
|
+
# compliance with the License.
|
5
|
+
#
|
6
|
+
# You can obtain a copy of the License at
|
7
|
+
# https://opensso.dev.java.net/public/CDDLv1.0.html or
|
8
|
+
# opensso/legal/CDDLv1.0.txt
|
9
|
+
# See the License for the specific language governing
|
10
|
+
# permission and limitations under the License.
|
11
|
+
#
|
12
|
+
# When distributing Covered Code, include this CDDL
|
13
|
+
# Header Notice in each file and include the License file
|
14
|
+
# at opensso/legal/CDDLv1.0.txt.
|
15
|
+
# If applicable, add the following below the CDDL Header,
|
16
|
+
# with the fields enclosed by brackets [] replaced by
|
17
|
+
# your own identifying information:
|
18
|
+
# "Portions Copyrighted [year] [name of copyright owner]"
|
19
|
+
#
|
20
|
+
# $Id: relying_party.rb,v 1.1 2007/03/19 22:45:54 todddd Exp $
|
21
|
+
#
|
22
|
+
# Copyright 2007 Sun Microsystems Inc. All Rights Reserved
|
23
|
+
# Portions Copyrighted 2007 Todd W Saxton.
|
24
|
+
|
25
|
+
|
26
|
+
require "base64"
|
27
|
+
require "rexml/document"
|
28
|
+
|
29
|
+
module SAML
|
30
|
+
|
31
|
+
class RelyingParty
|
32
|
+
|
33
|
+
cattr_accessor :logger
|
34
|
+
attr_accessor :name_id
|
35
|
+
|
36
|
+
def initialize(metadata)
|
37
|
+
@assertion_consumer_service_URL = metadata[:assertion_consumer_service_URL]
|
38
|
+
@issuer = metadata[:issuer]
|
39
|
+
@sp_name_qualifier = metadata[:sp_name_qualifier]
|
40
|
+
@idp_sso_target_url = metadata[:idp_sso_target_url]
|
41
|
+
@idp_slo_target_url = metadata[:idp_slo_target_url]
|
42
|
+
@idp_cert_fingerprint = metadata[:idp_cert_fingerprint]
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_auth_request
|
46
|
+
|
47
|
+
id = generateUniqueHexCode(42)
|
48
|
+
issue_instant = Time.new().strftime("%Y-%m-%dT%H:%M:%SZ")
|
49
|
+
|
50
|
+
auth_request = "<samlp:AuthnRequest " +
|
51
|
+
"xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"\n" +
|
52
|
+
"ID=\"" + id + "\" " +
|
53
|
+
"Version=\"2.0\" " +
|
54
|
+
"IssueInstant=\"" + issue_instant + "\" " +
|
55
|
+
"ForceAuthn=\"false\" " +
|
56
|
+
"isPassive=\"false\" " +
|
57
|
+
"ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" " +
|
58
|
+
"AssertionConsumerServiceURL=\"" + @assertion_consumer_service_URL + "\">\n" +
|
59
|
+
"<saml:Issuer " +
|
60
|
+
"xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" +
|
61
|
+
@issuer +
|
62
|
+
"</saml:Issuer>\n" +
|
63
|
+
"<samlp:NameIDPolicy " +
|
64
|
+
"xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" " +
|
65
|
+
"Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\" " +
|
66
|
+
"SPNameQualifier=\"" + @sp_name_qualifier + "\" " +
|
67
|
+
"AllowCreate=\"true\">\n" +
|
68
|
+
"</samlp:NameIDPolicy>\n" +
|
69
|
+
"<samlp:RequestedAuthnContext " +
|
70
|
+
"xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" " +
|
71
|
+
"Comparison=\"exact\">" +
|
72
|
+
"<saml:AuthnContextClassRef " +
|
73
|
+
"xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" +
|
74
|
+
"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" +
|
75
|
+
"</saml:AuthnContextClassRef>" +
|
76
|
+
"</samlp:RequestedAuthnContext>\n" +
|
77
|
+
"</samlp:AuthnRequest>"
|
78
|
+
|
79
|
+
logger.info(auth_request) if !logger.nil?
|
80
|
+
|
81
|
+
deflated_auth_request = Zlib::Deflate.deflate(auth_request, 9)[2..-5]
|
82
|
+
base64_auth_request = Base64.encode64(deflated_auth_request)
|
83
|
+
encoded_auth_request = CGI.escape(base64_auth_request)
|
84
|
+
|
85
|
+
|
86
|
+
redirect_url = @idp_sso_target_url + "?SAMLRequest=" + encoded_auth_request
|
87
|
+
|
88
|
+
return redirect_url
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
def process_auth_response(raw_response)
|
93
|
+
|
94
|
+
logger.info("Raw Response: " + raw_response ) if !logger.nil?
|
95
|
+
|
96
|
+
# raw_response is all ready URL decoded...
|
97
|
+
@saml_response = Base64.decode64( raw_response )
|
98
|
+
logger.info("Authn response = " + @saml_response) if !logger.nil?
|
99
|
+
|
100
|
+
saml_response_doc = XMLSecurity::SignedDocument.new @saml_response
|
101
|
+
|
102
|
+
if valid_flag = saml_response_doc.validate(@idp_cert_fingerprint, logger)
|
103
|
+
self.name_id = saml_response_doc.elements["/samlp:Response/saml:Assertion/saml:Subject/saml:NameID"].text
|
104
|
+
else
|
105
|
+
# error
|
106
|
+
logger.error("Invalid SAML response")
|
107
|
+
end
|
108
|
+
|
109
|
+
return valid_flag
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
def create_logout_request
|
115
|
+
|
116
|
+
saml_response_doc = REXML::Document.new @saml_response
|
117
|
+
id = generateUniqueHexCode(42)
|
118
|
+
issue_instant = Time.new().strftime("%Y-%m-%dT%H:%M:%SZ")
|
119
|
+
name_id = saml_response_doc.elements["/samlp:Response/saml:Assertion/saml:Subject/saml:NameID"].text
|
120
|
+
name_qualifier = saml_response_doc.elements["/samlp:Response/saml:Assertion/saml:Subject/saml:NameID"].attributes["NameQualifier"]
|
121
|
+
session_index = saml_response_doc.elements["/samlp:Response/saml:Assertion/saml:AuthnStatement"].attributes["SessionIndex"]
|
122
|
+
|
123
|
+
logout_request = "<samlp:LogoutRequest " +
|
124
|
+
"xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" " +
|
125
|
+
"ID=\"" + id + "\" " +
|
126
|
+
"Version=\"2.0\" " +
|
127
|
+
"IssueInstant=\"" + issue_instant + "\"> " +
|
128
|
+
"<saml:Issuer " +
|
129
|
+
"xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" +
|
130
|
+
@issuer +
|
131
|
+
"</saml:Issuer>" +
|
132
|
+
"<saml:NameID " +
|
133
|
+
"xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" " +
|
134
|
+
"NameQualifier=\"" + name_qualifier + "\" " +
|
135
|
+
"SPNameQualifier=\"" + @sp_name_qualifier + "\" " +
|
136
|
+
"Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">" +
|
137
|
+
name_id +
|
138
|
+
"</saml:NameID>" +
|
139
|
+
"<samlp:SessionIndex " +
|
140
|
+
"xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">" +
|
141
|
+
session_index +
|
142
|
+
"</samlp:SessionIndex>" +
|
143
|
+
"</samlp:LogoutRequest>";
|
144
|
+
|
145
|
+
logger.info("Logout request = " + logout_request) if !logger.nil?
|
146
|
+
|
147
|
+
deflated_logout_request = Zlib::Deflate.deflate(logout_request, 9)[2..-5]
|
148
|
+
base64_logout_request = Base64.encode64(deflated_logout_request)
|
149
|
+
encoded_logout_request = CGI.escape(base64_logout_request)
|
150
|
+
|
151
|
+
redirect_url = @idp_slo_target_url + "?SAMLRequest=" + encoded_logout_request
|
152
|
+
|
153
|
+
return redirect_url
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def generateUniqueHexCode( codeLength )
|
160
|
+
validChars = ("A".."F").to_a + ("0".."9").to_a
|
161
|
+
length = validChars.size
|
162
|
+
|
163
|
+
hexCode = ""
|
164
|
+
1.upto(codeLength) { |i| hexCode << validChars[rand(length-1)] }
|
165
|
+
|
166
|
+
hexCode
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# The contents of this file are subject to the terms
|
2
|
+
# of the Common Development and Distribution License
|
3
|
+
# (the License). You may not use this file except in
|
4
|
+
# compliance with the License.
|
5
|
+
#
|
6
|
+
# You can obtain a copy of the License at
|
7
|
+
# https://opensso.dev.java.net/public/CDDLv1.0.html or
|
8
|
+
# opensso/legal/CDDLv1.0.txt
|
9
|
+
# See the License for the specific language governing
|
10
|
+
# permission and limitations under the License.
|
11
|
+
#
|
12
|
+
# When distributing Covered Code, include this CDDL
|
13
|
+
# Header Notice in each file and include the License file
|
14
|
+
# at opensso/legal/CDDLv1.0.txt.
|
15
|
+
# If applicable, add the following below the CDDL Header,
|
16
|
+
# with the fields enclosed by brackets [] replaced by
|
17
|
+
# your own identifying information:
|
18
|
+
# "Portions Copyrighted [year] [name of copyright owner]"
|
19
|
+
#
|
20
|
+
# $Id: xml_sec.rb,v 1.6 2007/10/24 00:28:41 todddd Exp $
|
21
|
+
#
|
22
|
+
# Copyright 2007 Sun Microsystems Inc. All Rights Reserved
|
23
|
+
# Portions Copyrighted 2007 Todd W Saxton.
|
24
|
+
|
25
|
+
require "rexml/document"
|
26
|
+
require "rexml/xpath"
|
27
|
+
require "openssl"
|
28
|
+
require "xmlcanonicalizer"
|
29
|
+
require "digest/sha1"
|
30
|
+
|
31
|
+
#
|
32
|
+
# WARNING, WARNING: VERY rudimentary
|
33
|
+
#
|
34
|
+
#
|
35
|
+
module XMLSecurity
|
36
|
+
|
37
|
+
class SignedDocument < REXML::Document
|
38
|
+
|
39
|
+
def validate (idp_cert_fingerprint, logger)
|
40
|
+
|
41
|
+
# get cert from response
|
42
|
+
base64_cert = self.elements["//X509Certificate"].text
|
43
|
+
cert_text = Base64.decode64(base64_cert)
|
44
|
+
cert = OpenSSL::X509::Certificate.new(cert_text)
|
45
|
+
|
46
|
+
# check cert matches registered idp cert
|
47
|
+
fingerprint = Digest::SHA1.hexdigest(cert.to_der)
|
48
|
+
logger.info("fingerprint = " + fingerprint) if !logger.nil?
|
49
|
+
valid_flag = fingerprint == idp_cert_fingerprint.gsub(":", "").downcase
|
50
|
+
|
51
|
+
return valid_flag if !valid_flag
|
52
|
+
|
53
|
+
validate_doc(base64_cert, logger)
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_doc(base64_cert, logger)
|
57
|
+
|
58
|
+
#
|
59
|
+
#validate references
|
60
|
+
#
|
61
|
+
|
62
|
+
# remove signature node
|
63
|
+
sig_element = XPath.first(self, "//ds:Signature", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"})
|
64
|
+
sig_element.remove
|
65
|
+
|
66
|
+
#check digests
|
67
|
+
logger.info("checking digests") if !logger.nil?
|
68
|
+
XPath.each(sig_element, "//ds:Reference", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}) do | ref |
|
69
|
+
uri = ref.attributes.get_attribute("URI").value
|
70
|
+
logger.info("URI = " + uri[1,uri.size]) if !logger.nil?
|
71
|
+
hashed_element = XPath.first(self, "//[@ID='#{uri[1,uri.size]}']")
|
72
|
+
logger.info("hashed element = " + hashed_element.to_s) if !logger.nil?
|
73
|
+
canoner = XML::Util::XmlCanonicalizer.new(false, true)
|
74
|
+
canon_hashed_element = canoner.canonicalize_element(hashed_element)
|
75
|
+
logger.info("canon hashed element = " + canon_hashed_element) if !logger.nil?
|
76
|
+
hash = Base64.encode64(Digest::SHA1.digest(canon_hashed_element)).chomp
|
77
|
+
digest_value = XPath.first(ref, "//ds:DigestValue", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}).text
|
78
|
+
logger.info("hashed_element_hash = " + hash) if !logger.nil?
|
79
|
+
logger.info("digest_value_element = " + digest_value) if !logger.nil?
|
80
|
+
|
81
|
+
valid_flag = hash == digest_value
|
82
|
+
return valid_flag if !valid_flag
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# verify dig sig
|
87
|
+
#
|
88
|
+
logger.info("checking dig sig") if !logger.nil?
|
89
|
+
|
90
|
+
# signed_info_element.add_namespace("http://www.w3.org/2000/09/xmldsig#") if signed_info_element.namespace.nil? || signed_info_element.namespace.empty?
|
91
|
+
canoner = XML::Util::XmlCanonicalizer.new(false, true)
|
92
|
+
signed_info_element = XPath.first(sig_element, "//ds:SignedInfo", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"})
|
93
|
+
canon_string = canoner.canonicalize_element(signed_info_element)
|
94
|
+
logger.info("canon INFO = " + canon_string) if !logger.nil?
|
95
|
+
|
96
|
+
base64_signature = XPath.first(sig_element, "//ds:SignatureValue", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}).text
|
97
|
+
logger.info("base 64 SIG = " + base64_signature) if !logger.nil?
|
98
|
+
signature = Base64.decode64(base64_signature)
|
99
|
+
logger.info("SIG = " + signature) if !logger.nil?
|
100
|
+
|
101
|
+
# get cert object
|
102
|
+
cert_text = Base64.decode64(base64_cert)
|
103
|
+
cert = OpenSSL::X509::Certificate.new(cert_text)
|
104
|
+
|
105
|
+
valid_flag = cert.public_key.verify(OpenSSL::Digest::SHA1.new, signature, canon_string)
|
106
|
+
|
107
|
+
return valid_flag
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
$LOAD_PATH.insert(0, File.expand_path(File.dirname(__FILE__)) + "/../lib")
|
2
|
+
load "xml_sec.rb"
|
3
|
+
require "logger"
|
4
|
+
require "test/unit"
|
5
|
+
|
6
|
+
class XMLSecurityTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@log = Logger.new("test_output.log")
|
11
|
+
@log.level = Logger::DEBUG
|
12
|
+
@log.info "starting"
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_open_fed_response
|
16
|
+
puts "Processing OpenFederation file"
|
17
|
+
@log.info "Processing OpenFederation file"
|
18
|
+
File.open("test/authNResponseOpenFed.xml", aModeString="r") {|file|
|
19
|
+
|
20
|
+
saml_response_doc = XMLSecurity::SignedDocument.new(file)
|
21
|
+
|
22
|
+
base64_cert = saml_response_doc.elements["//X509Certificate"].text
|
23
|
+
assert saml_response_doc.validate_doc(base64_cert, @log)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_rsa_fim_response
|
28
|
+
puts "Processing RSA file"
|
29
|
+
@log.info "Processing RSA file"
|
30
|
+
File.open("test/authNResponseRSAFIM.xml", aModeString="r") {|file|
|
31
|
+
|
32
|
+
saml_response_doc = XMLSecurity::SignedDocument.new(file)
|
33
|
+
|
34
|
+
base64_cert = "MIICODCCAaECBEatbN8wDQYJKoZIhvcNAQEEBQAwYzELMAkGA1UEBhMCTloxEDAOBgNVBAgTB1Vua25vd24xEzARBgNVBAcTCldlbGxpbmd0b24xDDAKBgNVBAoTA1NTQzEMMAoGA1UECxMDU1NDMREwDwYDVQQDEwhHTFMgU0FNTDAeFw0wNzA3MzAwNDQ1MTlaFw0xMjA3MjgwNDQ1MTlaMGMxCzAJBgNVBAYTAk5aMRAwDgYDVQQIEwdVbmtub3duMRMwEQYDVQQHEwpXZWxsaW5ndG9uMQwwCgYDVQQKEwNTU0MxDDAKBgNVBAsTA1NTQzERMA8GA1UEAxMIR0xTIFNBTUwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOy62p6wMNRRVCSs7/4fnPrHqFehVBaYeg9yayD1I/yqYXvmOgbYX/OnuIE+RylVDwkzmKHgNsLpw8jfw1Ee2f0qmZY1rs6x+jmE4yDLDR1eKNGCkB4hSep2cVknWCBBzvmrk1nKet8Aw460FU2+C5H67Iwj5sVqshi5noLXSckTAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAL2ebLISFR6F0RzeEpLOjv4kSfDhsELSzEi4vVqlmCm+YcRWH0ASik3Ynl1B/K05cosqD5RMJG71t6ZWNf/s5F4NX0blU0ZAWewQXIUS4CUZPcQT3K/WXbpWBjRDIY0Cj6Dim/yBdmYSxZV51sDAIfOq4FXb5bEPSCopKK1YQRLE="
|
35
|
+
assert saml_response_doc.validate_doc(base64_cert, @log)
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_rsa_fim_response_after_enc
|
40
|
+
puts "Processing RSA file after encryption"
|
41
|
+
@log.info "Processing RSA file after encryption"
|
42
|
+
File.open("test/authNResponseRSAFIMAfterEncryption.xml", aModeString="r") {|file|
|
43
|
+
|
44
|
+
saml_response_doc = XMLSecurity::SignedDocument.new(file)
|
45
|
+
|
46
|
+
base64_cert = "MIICODCCAaECBEatbN8wDQYJKoZIhvcNAQEEBQAwYzELMAkGA1UEBhMCTloxEDAOBgNVBAgTB1Vua25vd24xEzARBgNVBAcTCldlbGxpbmd0b24xDDAKBgNVBAoTA1NTQzEMMAoGA1UECxMDU1NDMREwDwYDVQQDEwhHTFMgU0FNTDAeFw0wNzA3MzAwNDQ1MTlaFw0xMjA3MjgwNDQ1MTlaMGMxCzAJBgNVBAYTAk5aMRAwDgYDVQQIEwdVbmtub3duMRMwEQYDVQQHEwpXZWxsaW5ndG9uMQwwCgYDVQQKEwNTU0MxDDAKBgNVBAsTA1NTQzERMA8GA1UEAxMIR0xTIFNBTUwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOy62p6wMNRRVCSs7/4fnPrHqFehVBaYeg9yayD1I/yqYXvmOgbYX/OnuIE+RylVDwkzmKHgNsLpw8jfw1Ee2f0qmZY1rs6x+jmE4yDLDR1eKNGCkB4hSep2cVknWCBBzvmrk1nKet8Aw460FU2+C5H67Iwj5sVqshi5noLXSckTAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAL2ebLISFR6F0RzeEpLOjv4kSfDhsELSzEi4vVqlmCm+YcRWH0ASik3Ynl1B/K05cosqD5RMJG71t6ZWNf/s5F4NX0blU0ZAWewQXIUS4CUZPcQT3K/WXbpWBjRDIY0Cj6Dim/yBdmYSxZV51sDAIfOq4FXb5bEPSCopKK1YQRLE="
|
47
|
+
assert saml_response_doc.validate_doc(base64_cert, @log)
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_ak_assertion
|
52
|
+
puts "Processing AK file"
|
53
|
+
@log.info "Processing AK file"
|
54
|
+
File.open("test/assertion_from_AK.xml", aModeString="r") {|file|
|
55
|
+
|
56
|
+
saml_response_doc = XMLSecurity::SignedDocument.new(file)
|
57
|
+
|
58
|
+
base64_cert = saml_response_doc.elements["//X509Certificate"].text
|
59
|
+
assert saml_response_doc.validate_doc(base64_cert, @log)
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: saml2ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Cashin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-16 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: XMLCanonicalizer
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.0.1
|
24
|
+
version:
|
25
|
+
description: Part of the OpenSSO extension set. Writting by the wonderful guys over at Sun. Moved it over to a github repo and turned it into a rubygem.
|
26
|
+
email:
|
27
|
+
- scashin133@gmail.com
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- README
|
34
|
+
- TODO
|
35
|
+
files:
|
36
|
+
- README
|
37
|
+
- Rakefile
|
38
|
+
- lib/saml2ruby.rb
|
39
|
+
- lib/saml_2_ruby.rb
|
40
|
+
- lib/saml_2_ruby/relying_party.rb
|
41
|
+
- lib/saml_2_ruby/version.rb
|
42
|
+
- lib/saml_2_ruby/xml_sec.rb
|
43
|
+
- TODO
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://github.com/scashin133/saml2ruby
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options:
|
50
|
+
- --charset=UTF-8
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.3.5
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Ruby implementation of the SAML 2.0 Specification
|
72
|
+
test_files:
|
73
|
+
- test/xml_sec_test.rb
|
74
|
+
- examples/rails/SimpleSAMLRP/app/controllers/account_controller.rb
|
75
|
+
- examples/rails/SimpleSAMLRP/app/controllers/application.rb
|
76
|
+
- examples/rails/SimpleSAMLRP/app/helpers/account_helper.rb
|
77
|
+
- examples/rails/SimpleSAMLRP/app/helpers/application_helper.rb
|
78
|
+
- examples/rails/SimpleSAMLRP/config/boot.rb
|
79
|
+
- examples/rails/SimpleSAMLRP/config/environment.rb
|
80
|
+
- examples/rails/SimpleSAMLRP/config/environments/development.rb
|
81
|
+
- examples/rails/SimpleSAMLRP/config/environments/production.rb
|
82
|
+
- examples/rails/SimpleSAMLRP/config/environments/test.rb
|
83
|
+
- examples/rails/SimpleSAMLRP/config/routes.rb
|
84
|
+
- examples/rails/SimpleSAMLRP/public/dispatch.rb
|
85
|
+
- examples/rails/SimpleSAMLRP/test/functional/account_controller_test.rb
|
86
|
+
- examples/rails/SimpleSAMLRP/test/test_helper.rb
|