swt_federation 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []