omniauth-latvija 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Edgars Beigarts
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # OmniAuth Latvija.lv
2
+
3
+ > **Autentifikācijas serviss.** Ar autentifikācijas servisa palīdzību iestādes var ērti savos pakalpojumu portālos vai reģistros autentificēt pakalpojuma lietotāju atbilstoši visiem drošības standartiem. Iestādei vairs nav nepieciešams veidot jaunus autentifikācijas mehānismus un juridiski slēgt vienošanos ar katru no autentifikācijas iespējas nodrošinātājiem. Šobrīd pieejamos autentifikācijas līdzekļus var apskatīties portālā [www.latvija.lv](http://www.latvija.lv/) sadaļā „E-pakalpojumi”.
4
+ >
5
+ > -- [VRAA E-pakalpojumi](http://www.vraa.gov.lv/lv/epakalpojumi/viss/)
6
+
7
+ Provides the following authentication types:
8
+
9
+ * E-paraksts
10
+ * Swedbank
11
+ * SEB banka
12
+ * Online bank
13
+ * Citadele
14
+ * Norvik banka
15
+ * Lattelecom Mobile ID
16
+
17
+ ## Installation
18
+
19
+ ```ruby
20
+ gem 'omniauth-latvija', :git => 'http://github.com/ebeigarts/omniauth-latvija.git'
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ `OmniAuth::Strategies::Latvija` is simply a Rack middleware. Read the OmniAuth 1.x docs for detailed instructions: https://github.com/intridea/omniauth.
26
+
27
+ Here's a quick example, adding the middleware to a Rails app in `config/initializers/omniauth.rb`:
28
+
29
+ ```ruby
30
+ Rails.application.config.middleware.use OmniAuth::Builder do
31
+ provider :latvija, {
32
+ :endpoint => "https://epaktv.vraa.gov.lv/IVIS.LVP.STS/Default.aspx",
33
+ :certificate => File.read("/path/to/cert"),
34
+ :realm => "urn:federation:example.com"
35
+ }
36
+ end
37
+ ```
38
+
39
+ ## References
40
+
41
+ * http://docs.oasis-open.org/wsfed/federation/v1.2/os/ws-federation-1.2-spec-os.html
42
+ * http://msdn.microsoft.com/en-us/library/bb498017.aspx
43
+ * http://msdn.microsoft.com/en-us/library/bb608217.aspx
44
+ * https://github.com/onelogin/ruby-saml
@@ -0,0 +1,48 @@
1
+ module OmniAuth
2
+ module Strategies
3
+ class Latvija
4
+ class Response
5
+ ASSERTION = "urn:oasis:names:tc:SAML:1.0:assertion"
6
+
7
+ attr_accessor :options, :response, :document
8
+
9
+ def initialize(response, options = {})
10
+ raise ArgumentError.new("Response cannot be nil") if response.nil?
11
+ self.options = options
12
+ self.response = response
13
+ self.document = OmniAuth::Strategies::Latvija::SignedDocument.new(response)
14
+ end
15
+
16
+ def validate!
17
+ document.validate!(fingerprint)
18
+ end
19
+
20
+ # A hash of alle the attributes with the response. Assuming there is only one value for each key
21
+ def attributes
22
+ @attributes ||= begin
23
+ result = {}
24
+
25
+ stmt_element = REXML::XPath.first(document, "//a:Assertion/a:AttributeStatement", { "a" => ASSERTION })
26
+ return {} if stmt_element.nil?
27
+
28
+ stmt_element.elements.each do |attr_element|
29
+ name = attr_element.attributes["AttributeName"]
30
+ value = attr_element.elements.first.text
31
+
32
+ result[name] = value
33
+ end
34
+
35
+ result
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def fingerprint
42
+ cert = OpenSSL::X509::Certificate.new(options[:certificate])
43
+ Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,95 @@
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
+ module OmniAuth
26
+ module Strategies
27
+ class Latvija
28
+ class SignedDocument < REXML::Document
29
+ DSIG = "http://www.w3.org/2000/09/xmldsig#"
30
+
31
+ attr_accessor :signed_element_id
32
+
33
+ def initialize(response)
34
+ super(response)
35
+ extract_signed_element_id
36
+ end
37
+
38
+ def validate!(idp_cert_fingerprint)
39
+ # get cert from response
40
+ base64_cert = self.elements["//ds:X509Certificate"].text
41
+ cert_text = Base64.decode64(base64_cert)
42
+ cert = OpenSSL::X509::Certificate.new(cert_text)
43
+
44
+ # check cert matches registered idp cert
45
+ fingerprint = Digest::SHA1.hexdigest(cert.to_der)
46
+
47
+ if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase
48
+ raise ValidationError.new("Fingerprint mismatch")
49
+ end
50
+
51
+ # remove signature node
52
+ sig_element = REXML::XPath.first(self, "//ds:Signature", { "ds" => DSIG })
53
+ sig_element.remove
54
+
55
+ # check digests
56
+ REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}) do |ref|
57
+ uri = ref.attributes.get_attribute("URI").value
58
+ hashed_element = REXML::XPath.first(self, "//[@AssertionID='#{uri[1,uri.size]}']")
59
+ canoner = XML::Util::XmlCanonicalizer.new(false, true)
60
+ canon_hashed_element = canoner.canonicalize(hashed_element)
61
+ hash = Base64.encode64(Digest::SHA1.digest(canon_hashed_element)).chomp
62
+ digest_value = REXML::XPath.first(ref, "//ds:DigestValue", { "ds" => DSIG }).text
63
+
64
+ if hash != digest_value
65
+ raise ValidationError.new("Digest mismatch")
66
+ end
67
+ end
68
+
69
+ # verify signature
70
+ canoner = XML::Util::XmlCanonicalizer.new(false, true)
71
+ signed_info_element = REXML::XPath.first(sig_element, "//ds:SignedInfo", { "ds" => DSIG })
72
+ canon_string = canoner.canonicalize(signed_info_element)
73
+
74
+ base64_signature = REXML::XPath.first(sig_element, "//ds:SignatureValue", { "ds" => DSIG }).text
75
+ signature = Base64.decode64(base64_signature)
76
+
77
+ # get certificate object
78
+ cert_text = Base64.decode64(base64_cert)
79
+ cert = OpenSSL::X509::Certificate.new(cert_text)
80
+
81
+ if !cert.public_key.verify(OpenSSL::Digest::SHA1.new, signature, canon_string)
82
+ raise ValidationError.new("Key validation error")
83
+ end
84
+
85
+ true
86
+ end
87
+
88
+ def extract_signed_element_id
89
+ reference_element = REXML::XPath.first(self, "//ds:Signature/ds:SignedInfo/ds:Reference", { "ds" => DSIG })
90
+ self.signed_element_id = reference_element.attribute("URI").value unless reference_element.nil?
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,74 @@
1
+ require "time"
2
+ require "rexml/document"
3
+ require "rexml/xpath"
4
+ require "openssl"
5
+ require "xmlcanonicalizer"
6
+ require "digest/sha1"
7
+
8
+ require "omniauth/strategies/latvija/response"
9
+ require "omniauth/strategies/latvija/signed_document"
10
+
11
+ module OmniAuth
12
+ module Strategies
13
+ #
14
+ # Authenticate with Latvija.lv.
15
+ #
16
+ # @example Basic Rails Usage
17
+ #
18
+ # Add this to config/initializers/omniauth.rb
19
+ #
20
+ # Rails.application.config.middleware.use OmniAuth::Builder do
21
+ # provider :latvija, {
22
+ # :endpoint => "https://epaktv.vraa.gov.lv/IVIS.LVP.STS/Default.aspx",
23
+ # :certificate => File.read("/path/to/cert"),
24
+ # :realm => "urn:federation:example.com"
25
+ # }
26
+ # end
27
+ #
28
+ class Latvija
29
+ include OmniAuth::Strategy
30
+
31
+ class ValidationError < StandardError; end
32
+
33
+ def request_phase
34
+ params = {
35
+ :wa => 'wsignin1.0',
36
+ :wct => Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ'),
37
+ :wtrealm => @options[:realm],
38
+ :wreply => callback_url,
39
+ :wctx => callback_url,
40
+ :wreq => '<trust:RequestSecurityToken xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512"><trust:Claims xmlns:i="http://schemas.xmlsoap.org/ws/2005/05/identity" Dialect="http://schemas.xmlsoap.org/ws/2005/05/identity"><i:ClaimType Uri="http://docs.oasis-open.org/wsfed/authorization/200706/claims/action" Optional="false" /></trust:Claims><trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType></trust:RequestSecurityToken>'
41
+ }
42
+ query_string = params.collect{ |key, value| "#{key}=#{Rack::Utils.escape(value)}" }.join('&')
43
+ redirect "#{options[:endpoint]}?#{query_string}"
44
+ end
45
+
46
+ def callback_phase
47
+ if request.params['wresult']
48
+ @response = OmniAuth::Strategies::Latvija::Response.new(request.params['wresult'], {
49
+ :certificate => options[:certificate]
50
+ })
51
+ @response.validate!
52
+ super
53
+ else
54
+ fail!(:invalid_response)
55
+ end
56
+ rescue Exception => e
57
+ fail!(:invalid_response, e)
58
+ end
59
+
60
+ def auth_hash
61
+ OmniAuth::Utils.deep_merge(super, {
62
+ 'uid' => "#{@response.attributes['givenname']} #{@response.attributes['surname']}, #{@response.attributes["privatepersonalidentifier"]}",
63
+ 'user_info' => {
64
+ 'name' => "#{@response.attributes['givenname']} #{@response.attributes['surname']}",
65
+ 'first_name' => @response.attributes['givenname'],
66
+ 'last_name' => @response.attributes['surname'],
67
+ 'private_personal_identifier' => @response.attributes['privatepersonalidentifier']
68
+ },
69
+ 'extra' => @response.attributes
70
+ })
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module Latvija
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ require 'omniauth-latvija/version'
2
+ require 'omniauth/strategies/latvija'
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-latvija
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Edgars Beigarts
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: omniauth
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: canonix
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '2.10'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '2.10'
78
+ - !ruby/object:Gem::Dependency
79
+ name: simplecov
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rack-test
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: Latvija.lv authentication strategy for OmniAuth
111
+ email:
112
+ - edgars.beigarts@makit.lv
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - lib/omniauth/strategies/latvija/response.rb
118
+ - lib/omniauth/strategies/latvija/signed_document.rb
119
+ - lib/omniauth/strategies/latvija.rb
120
+ - lib/omniauth-latvija/version.rb
121
+ - lib/omniauth-latvija.rb
122
+ - README.md
123
+ - LICENSE
124
+ homepage:
125
+ licenses: []
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ! '>='
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 1.8.24
145
+ signing_key:
146
+ specification_version: 3
147
+ summary: Latvija.lv authentication strategy for OmniAuth
148
+ test_files: []