swt_federation 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in swt_federation.gemspec
4
+ gemspec
@@ -0,0 +1,39 @@
1
+ = SWT Federation for Ruby
2
+
3
+ This library provides SWT-based federation for Ruby applications (ruby 1.9)
4
+
5
+ The entry point of this library is the TokenHandler class. Before using it you have to set some class instance
6
+ variables that hold configuration information.
7
+
8
+
9
+ TokenHandler.realm = 'http://0.0.0.0:8080/login/'
10
+ TokenHandler.token_type = 'http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0'
11
+ TokenHandler.issuer = 'https://southworksinc.accesscontrol.windows.net/'
12
+ TokenHandler.toke_key = 'your key here'
13
+
14
+ The lines above can be placed in the config.ru file.
15
+ Below you can find an example of how to use it with Sinatra.
16
+
17
+ before do
18
+
19
+ next if request.path_info == '/swt'
20
+ if(session['user']==nil)
21
+ redirect ("<your_identity_provider_url>")
22
+ end
23
+ end
24
+
25
+ post '/swt' do
26
+ response = TokenHandler.new(params[:wresult])
27
+ if (response.is_valid?)
28
+ session['user'] = response.claims['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress']
29
+ target_url = params[:wctx]
30
+ if (target_url != nil)
31
+ redirect(target_url)
32
+ else
33
+ redirect('/home')
34
+ end
35
+ else
36
+ status(403)
37
+ halt('access denied')
38
+ end
39
+ end
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,101 @@
1
+ # http://blog.thepete.net/2010/11/creating-and-publishing-your-first-ruby.html
2
+ require "swt_federation/version"
3
+
4
+ require 'nokogiri'
5
+ require 'time'
6
+ require 'base64'
7
+ require 'cgi'
8
+ require 'openssl'
9
+
10
+
11
+ module SwtFederation
12
+
13
+ class TokenHandler
14
+ class << self; attr_accessor :realm, :issuer, :token_key, :token_type end
15
+
16
+ attr_reader :validation_errors, :claims
17
+
18
+ def initialize(wresult)
19
+ @validation_errors = []
20
+ @claims={}
21
+ @wresult=Nokogiri::XML(wresult)
22
+
23
+ parse_response()
24
+ end
25
+
26
+ def is_valid?
27
+ @validation_errors.empty?
28
+ end
29
+
30
+ #parse through the document, performing validation & pulling out claims
31
+ def parse_response
32
+ parse_address()
33
+ parse_expires()
34
+ parse_token_type()
35
+ parse_token()
36
+ end
37
+
38
+ #does the address field have the expected address?
39
+ def parse_address
40
+ address = get_element('//t:RequestSecurityTokenResponse/wsp:AppliesTo/addr:EndpointReference/addr:Address')
41
+ @validation_errors << "Address field is empty." and return if address.nil?
42
+ @validation_errors << "Address field is incorrect." unless address == self.class.realm
43
+ end
44
+
45
+ #is the expire value valid?
46
+ def parse_expires
47
+ expires = get_element('//t:RequestSecurityTokenResponse/t:Lifetime/wsu:Expires')
48
+ @validation_errors << "Expiration field is empty." and return if expires.nil?
49
+ @validation_errors << "Invalid format for expiration field." and return unless /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?$/.match(expires)
50
+ @validation_errors << "Expiration date occurs in the past." unless Time.now.utc.iso8601 < Time.iso8601(expires).iso8601
51
+ end
52
+
53
+ #is the token type what we expected?
54
+ def parse_token_type
55
+ token_type = get_element('//t:RequestSecurityTokenResponse/t:TokenType')
56
+ @validation_errors << "TokenType field is empty." and return if token_type.nil?
57
+ @validation_errors << "Invalid token type." unless token_type == self.class.token_type
58
+ end
59
+
60
+ #parse the binary token
61
+ def parse_token
62
+ binary_token = get_element('//t:RequestSecurityTokenResponse/t:RequestedSecurityToken/wsse:BinarySecurityToken')
63
+ @validation_errors << "No binary token exists." and return if binary_token.nil?
64
+
65
+ decoded_token = Base64.decode64(binary_token)
66
+ name_values={}
67
+ decoded_token.split('&').each do |entry|
68
+ pair=entry.split('=')
69
+ name_values[CGI.unescape(pair[0]).chomp] = CGI.unescape(pair[1]).chomp
70
+ end
71
+
72
+ @validation_errors << "Response token is expired." if Time.now.to_i > name_values["ExpiresOn"].to_i
73
+ @validation_errors << "Invalid token issuer." unless name_values["Issuer"]=="#{self.class.issuer}"
74
+ @validation_errors << "Invalid audience." unless name_values["Audience"] =="#{self.class.realm}"
75
+
76
+ # is HMAC valid?
77
+ token_hmac = decoded_token.split("&HMACSHA256=")
78
+ swt=token_hmac[0]
79
+ @validation_errors << "HMAC does not match computed value." unless name_values['HMACSHA256'] == Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'),Base64.decode64(self.class.token_key),swt)).chomp
80
+
81
+ # remove non-claims from collection and make claims available
82
+
83
+ @claims = name_values.reject {|key, value| !key.include? '/claims/'}
84
+ end
85
+
86
+ #given an path, return the content of the first matching element
87
+ def get_element(xpath_statement)
88
+ begin
89
+ @wresult.xpath(xpath_statement,
90
+ 't'=>'http://schemas.xmlsoap.org/ws/2005/02/trust',
91
+ 'wsu'=>'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
92
+ 'wsp'=>'http://schemas.xmlsoap.org/ws/2004/09/policy',
93
+ 'wsse'=>'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
94
+ 'addr'=>'http://www.w3.org/2005/08/addressing')[0].content
95
+ rescue
96
+ nil
97
+ end
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,3 @@
1
+ module SwtFederation
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "swt_federation/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "swt_federation"
7
+ s.version = SwtFederation::VERSION
8
+ s.authors = ["NicoPaez"]
9
+ s.email = ["nicopaez@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{This gem provides website federation based on Simple Web Tokens (SWT)}
12
+ s.description = %q{It is inspired on this post (http://blogs.msdn.com/b/silverlining/archive/2011/10/03/ruby-web-sites-and-windows-azure-appfabric-access-control.aspx) by Larry Franks.}
13
+
14
+ s.rubyforge_project = "swt_federation"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ #s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ s.add_dependency "nokogiri"
25
+
26
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: swt_federation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - NicoPaez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-21 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &11839000 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *11839000
25
+ description: It is inspired on this post (http://blogs.msdn.com/b/silverlining/archive/2011/10/03/ruby-web-sites-and-windows-azure-appfabric-access-control.aspx)
26
+ by Larry Franks.
27
+ email:
28
+ - nicopaez@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - README.rdoc
36
+ - Rakefile
37
+ - lib/swt_federation.rb
38
+ - lib/swt_federation/version.rb
39
+ - swt_federation.gemspec
40
+ homepage: ''
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project: swt_federation
60
+ rubygems_version: 1.8.10
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: This gem provides website federation based on Simple Web Tokens (SWT)
64
+ test_files: []