sezame-sdk 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f6d57334987a3e68df5d3616469bec1077d1ceaf
4
+ data.tar.gz: aab37915e30af2a759b4dfba942bd5419c20b1bf
5
+ SHA512:
6
+ metadata.gz: 728dd84fe737b122e96a38f183cefaaeb46cc8f1d047a17b355117bf20404552935748a47252734ac08c4a0ceac15816922e33e86e40a6ecf0bfcc3afa08c64b
7
+ data.tar.gz: ebeba0e1e1a63edda11a5103fbec4ec8e88abf1e2cafda52ecb7acee80ad798d31a6161ebb84206c5be7ca58edff53e938f3271beed12f1e39c975491c105ad0
data/lib/sezame-sdk.rb ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'sezame-sdk/client'
@@ -0,0 +1,153 @@
1
+ require 'openssl'
2
+ require_relative 'sezamejsonclient'
3
+ require_relative 'response'
4
+
5
+
6
+ module Sezame
7
+
8
+ ##
9
+ # base class for client requests.
10
+ class Client
11
+ attr_reader :http
12
+
13
+ # Expects a certificate string in pem format, the
14
+ # corresponding private key and an optional keypassword
15
+ def initialize(cert = nil, key = nil, keypassword = nil)
16
+ @http = SezameJSONClient.new
17
+ @http.connect_timeout = 10
18
+
19
+ @endpoint = 'https://hqfrontend-finprin.finprin.com/'
20
+
21
+ if cert != nil && key != nil
22
+ @http.ssl_config.client_cert = OpenSSL::X509::Certificate.new(cert)
23
+ @http.ssl_config.client_key = OpenSSL::PKey.read(key, keypassword)
24
+ end
25
+ end
26
+
27
+ # start the self-registration process by specifying
28
+ # a recovery e-mail entered during app installation
29
+ # and a name for your application
30
+ def register(email, name)
31
+ endpoint = @endpoint + 'client/register'
32
+ response = @http.post endpoint, {
33
+ :email => email,
34
+ :name => name
35
+ }
36
+ Sezame::Response::Register.new(response)
37
+ end
38
+
39
+ # helper function for building a csr
40
+ # pass the client code, obtained by the registration call
41
+ # add an e-mail address and additional x509 options
42
+ def makecsr(clientcode, email, x509 = {}, keylen = 2048)
43
+ options = {
44
+ :country => 'AT',
45
+ :state => 'Vienna',
46
+ :city => 'Vienna',
47
+ :organization => '-',
48
+ :department => '-',
49
+ :common_name => clientcode,
50
+ :email => email
51
+ }
52
+ options.merge!(x509)
53
+
54
+ key = OpenSSL::PKey::RSA.new(keylen)
55
+ csr = OpenSSL::X509::Request.new
56
+ csr.version = 0
57
+ csr.subject = OpenSSL::X509::Name.new([
58
+ ['C', options[:country], OpenSSL::ASN1::PRINTABLESTRING],
59
+ ['ST', options[:state], OpenSSL::ASN1::PRINTABLESTRING],
60
+ ['L', options[:city], OpenSSL::ASN1::PRINTABLESTRING],
61
+ ['O', options[:organization], OpenSSL::ASN1::UTF8STRING],
62
+ ['OU', options[:department], OpenSSL::ASN1::UTF8STRING],
63
+ ['CN', options[:common_name], OpenSSL::ASN1::UTF8STRING],
64
+ ['emailAddress', options[:email], OpenSSL::ASN1::UTF8STRING]
65
+ ])
66
+ csr.public_key = key.public_key
67
+ csr.sign(key, OpenSSL::Digest::SHA256.new)
68
+
69
+ {
70
+ :csr => csr.to_pem,
71
+ :key => key.to_pem
72
+ }
73
+ end
74
+
75
+ # let the csr signed by the hq server, pass the
76
+ # shared secret as optained by the register call
77
+ def sign(csr, sharedsecret)
78
+ endpoint = @endpoint + 'client/sign'
79
+ response = @http.post endpoint, {
80
+ :csr => csr,
81
+ :sharedsecret => sharedsecret
82
+ }
83
+ Sezame::Response::Sign.new(response)
84
+ end
85
+
86
+ # check the pairing status for the given username
87
+ def link_status(username)
88
+ endpoint = @endpoint + 'client/link/status'
89
+ response = @http.post endpoint, {
90
+ :username => username
91
+ }
92
+ response.content
93
+ end
94
+
95
+ # pair the given username with your application
96
+ def link(username)
97
+ endpoint = @endpoint + 'client/link'
98
+ response = @http.post endpoint, {
99
+ :username => username
100
+ }
101
+ ret = Sezame::Response::Link.new(response)
102
+ ret.username = username
103
+ ret
104
+ end
105
+
106
+ # remove the pairing for the given username
107
+ def link_delete(username)
108
+ endpoint = @endpoint + 'client/link'
109
+ response = @http.delete endpoint, {
110
+ :username => username
111
+ }
112
+ Sezame::Response::LinkDelete.new(response)
113
+ end
114
+
115
+ # submit an authentication request for the given username
116
+ # the message is displayed on the mobile app
117
+ # the timeout parameter defined the amount of seconds the requests is valid
118
+ # the type of request (auth or fraud)
119
+ # a callback url, results are posted to this url
120
+ # extra_params to be returned with the callback post
121
+ def authorize(username, message = nil, timeout = nil, type = 'auth', callback = nil, extra_params = nil)
122
+ endpoint = @endpoint + 'auth/login'
123
+ params = {
124
+ :username => username
125
+ }
126
+
127
+ params[:type] = type if type
128
+ params[:message] = message if message
129
+ params[:timeout] = timeout if timeout
130
+ params[:callback] = callback if callback
131
+ params[:params] = extra_params if extra_params
132
+
133
+ Sezame::Response::Auth.new(@http.post endpoint, params)
134
+ end
135
+
136
+ # inform the user about fraud attempts, like plaintext password logins
137
+ def fraud(username, message = nil, timeout = nil, callback = nil, extra_params = nil)
138
+ authorize(username, message, timeout, 'fraud', callback, extra_params)
139
+ end
140
+
141
+ # fetch the status of an authentication request
142
+ def status(auth_id)
143
+ endpoint = @endpoint + 'auth/status/' + auth_id
144
+ Sezame::Response::Status.new(@http.get endpoint)
145
+ end
146
+ end
147
+
148
+ # cancel the service
149
+ def cancel
150
+ endpoint = @endpoint + 'client/cancel'
151
+ Sezame::Response::Cancel.new(@http.get endpoint)
152
+ end
153
+ end
@@ -0,0 +1,151 @@
1
+ require 'rqrcode'
2
+
3
+ module Sezame
4
+
5
+ # defines a set of response classes
6
+ # to get easily response values
7
+ module Response
8
+
9
+ # generic response, expects the response as returned by the httpclient
10
+ class Generic
11
+ attr_reader :response
12
+ attr_reader :data
13
+
14
+ def initialize(response)
15
+ @response = response
16
+ @data = response.content
17
+ end
18
+
19
+ def is_empty
20
+ [201, 204, 304].include? @response.status
21
+ end
22
+
23
+ def is_ok
24
+ @response.status == 200
25
+ end
26
+
27
+ def is_notfound
28
+ @response.status == 404
29
+ end
30
+
31
+ def get_status
32
+ unless @data.has_key?('status')
33
+ return nil
34
+ end
35
+
36
+ @data['status']
37
+ end
38
+
39
+ # get the error message return by hq if any
40
+ def get_message
41
+ unless @data.has_key?('message')
42
+ return nil
43
+ end
44
+
45
+ @data['message']
46
+ end
47
+
48
+ # return an array of error messages
49
+ def get_errors
50
+ unless @data.has_key?('errors')
51
+ return []
52
+ end
53
+
54
+ @data['errors']
55
+ end
56
+ end
57
+
58
+ # represents the registration response
59
+ # returns the clientcode and the shared secret
60
+ class Register < Generic
61
+ def is_ok
62
+ super && @data.has_key?('clientcode')
63
+ end
64
+
65
+ def get_clientcode
66
+ @data['clientcode']
67
+ end
68
+
69
+ def get_sharedsecret
70
+ @data['sharedsecret']
71
+ end
72
+ end
73
+
74
+ # represents the sign response
75
+ # returns the certificate
76
+ class Sign < Generic
77
+ def is_ok
78
+ super && @data.has_key?('cert')
79
+ end
80
+
81
+ def get_cert
82
+ @data['cert']
83
+ end
84
+ end
85
+
86
+ # represents an authentication response
87
+ # returns the authentication id
88
+ class Auth < Generic
89
+ def is_ok
90
+ get_status == 'initiated'
91
+ end
92
+
93
+ def get_id
94
+ @data['id']
95
+ end
96
+ end
97
+
98
+ # auth status response
99
+ # returns the status of the authentication request
100
+ class Status < Generic
101
+ def is_authorized
102
+ get_status == 'authorized'
103
+ end
104
+
105
+ def is_denied
106
+ get_status == 'denied'
107
+ end
108
+
109
+ def is_pending
110
+ get_status == 'initiated'
111
+ end
112
+ end
113
+
114
+ # represents the pairing response
115
+ # returns a qrcode
116
+ class Link < Generic
117
+ attr_accessor :username
118
+
119
+ def is_ok
120
+ super && @data.has_key?('id')
121
+ end
122
+
123
+ def qrcode
124
+ linkdata = @data
125
+ linkdata[:username] = username
126
+ RQRCode::QRCode.new(linkdata.to_json)
127
+ end
128
+
129
+ def is_duplicate
130
+ @response.status == 409
131
+ end
132
+ end
133
+
134
+ # remove pairing response
135
+ class LinkDelete < Generic
136
+
137
+ def is_ok
138
+ super || @response.status == 204
139
+ end
140
+ end
141
+
142
+ # cancel service response
143
+ class Cancel < Generic
144
+
145
+ def is_ok
146
+ super || @response.status == 204
147
+ end
148
+ end
149
+
150
+ end
151
+ end
@@ -0,0 +1,18 @@
1
+ require 'jsonclient'
2
+
3
+ # parse json in quirks mode, so that JSON fragments (true, false, simple strings) can be handled
4
+ class SezameJSONClient < JSONClient
5
+
6
+ def delete(uri, *args, &block)
7
+ request(:delete, uri, argument_to_hash_for_json(args), &block)
8
+ end
9
+
10
+ private
11
+
12
+ def wrap_json_response(original)
13
+ res = ::HTTP::Message.new_response(JSON.parse(original.content, :quirks_mode => true))
14
+ res.http_header = original.http_header
15
+ res.previous = original
16
+ res
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module SezameSDK
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sezame-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Finpin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rqrcode
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httpclient
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.7'
41
+ description: |
42
+ Passwordless multi-factor authentication.
43
+
44
+ Unlike password-based solutions that require you to remember just another PIN or password,
45
+ sezame is a secure and simple multi-factor authentication solution.
46
+ You only need the username and your fingerprint on your smartphone to log into any sezame-enabled site.
47
+ email:
48
+ - office@finpintech.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - lib/sezame-sdk.rb
54
+ - lib/sezame-sdk/client.rb
55
+ - lib/sezame-sdk/response.rb
56
+ - lib/sezame-sdk/sezamejsonclient.rb
57
+ - lib/sezame-sdk/version.rb
58
+ homepage: https://www.seza.me/
59
+ licenses:
60
+ - BSD
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.2.2
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Sezame ruby SDK
82
+ test_files: []