omniauth-threefold-connect 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e538dfc9a2f928f9cf65ba4494b88680344f637c5c61d4f3353abb830651b079
4
+ data.tar.gz: c8a5acfa6214a117c4c59733b0b2f722764f63024a50946dae3126851d9cebbb
5
+ SHA512:
6
+ metadata.gz: eb68b5a40f20f555b4ba67ea1207c9a4920ed36e4ac8c24086dbd8ee6bc2051067435192ae396509cc066dd994733fe54e73a1f2b379488fec94d941be9ad435
7
+ data.tar.gz: cd4a6c80c5a002032fdf195fdb5baa7da9f5dd59d345dc87c495bb91f3782cc62837d967a4ec9fe14e9a612da3514f3c7ce16a27bf7b0561bf025996a281b8f1
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in omniauth-threefold-connect.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Omniauth::Threefold::Connect
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/omniauth/threefold/connect`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Install the gem and add to the application's Gemfile by executing:
10
+
11
+ $ bundle add omniauth-threefold-connect
12
+
13
+ If bundler is not being used to manage dependencies, install the gem by executing:
14
+
15
+ $ gem install omniauth-threefold-connect
16
+
17
+ ## Usage
18
+
19
+ TODO: Write usage instructions here
20
+
21
+ ## Development
22
+
23
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
24
+
25
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
26
+
27
+ ## Contributing
28
+
29
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/omniauth-threefold-connect.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omniauth
4
+ module Threefold
5
+ module Connect
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "connect/version"
4
+ require "base64"
5
+
6
+ module OmniAuth
7
+ module Strategies
8
+ class Threefold
9
+ include OmniAuth::Strategy
10
+
11
+ args [:key, :scope, :callback_url, :server_url, :kyc_url]
12
+
13
+ option :key, nil
14
+ option :scope, [:user, :email]
15
+
16
+ option :callback_url, nil
17
+ option :server_url, "https://login.threefold.me"
18
+ option :kyc_url, "https://openkyc.live/verification/verify-sei"
19
+
20
+ attr_accessor :data
21
+
22
+ def signing_key
23
+ RbNaCl::SigningKey.new(Base64.decode64(options[:key]))
24
+ end
25
+
26
+ def get_user_public_key(double_name)
27
+ resp = Net::HTTP.get_response(URI("#{options[:server_url]}/api/users/#{double_name}"))
28
+ if resp.kind_of?(Net::HTTPOK)
29
+ return JSON.parse(resp.body)["publicKey"]
30
+ end
31
+
32
+ raise resp.body
33
+ end
34
+
35
+ def verify_email(sei)
36
+ resp = Net::HTTP.post(URI(options[:kyc_url]), { "signedEmailIdentifier": sei }.to_json, { "Content-Type" => "application/json" })
37
+ unless resp.kind_of?(Net::HTTPOK)
38
+ raise "email is not verified"
39
+ end
40
+ end
41
+
42
+ def validate_fields(data, fields)
43
+ fields.each do |field|
44
+ unless data.key?(field)
45
+ raise "missing '#{field}'"
46
+ end
47
+ end
48
+ end
49
+
50
+ # decrypt verified data
51
+ # @param verify_key [VerifyKey] used to verify this data
52
+ # @param data [Hash] e.g. {data => {"nonce" => "...", "ciphertext" => "..."}}
53
+ #
54
+ # @return [Hash] containing scope fields e.g. email and username
55
+ def decrypt_verified_data(verify_key, data)
56
+ nonce = Base64.strict_decode64(data["data"]["nonce"])
57
+ ciphertext = Base64.strict_decode64(data["data"]["ciphertext"])
58
+
59
+ private_key = signing_key.to_curve25519_private_key
60
+ public_key = verify_key.to_curve25519_public_key
61
+ box = RbNaCl::Box.new(public_key, private_key)
62
+ decrypted = box.decrypt(nonce, ciphertext)
63
+ JSON.parse(decrypted)
64
+ end
65
+
66
+ # verify login attempt
67
+ # @param attempt [Hash] must containing `doubleName` and `signedAttempt`
68
+ #
69
+ # @raise in case verifying the login attempt failed
70
+ #
71
+ # @return [Hash] containing user info as `email` and `username`
72
+ def verify(attempt)
73
+ validate_fields(attempt, ["signedAttempt", "doubleName"])
74
+
75
+ signed_data = Base64.strict_decode64(attempt["signedAttempt"])
76
+ double_name = attempt["doubleName"]
77
+ public_key = get_user_public_key(double_name)
78
+ verify_key = RbNaCl::VerifyKey.new(Base64.strict_decode64(public_key))
79
+
80
+ # signed_data have the signature attached, so, split them
81
+ signature, signed_data = signed_data[0...verify_key.signature_bytes], signed_data[verify_key.signature_bytes..-1]
82
+ # will raise an error if verification failed
83
+ verify_key.verify(signature, signed_data)
84
+ verified_data = JSON.parse(signed_data)
85
+ validate_fields(verified_data, ["data", "signedState", "doubleName"])
86
+
87
+ state = verified_data["signedState"]
88
+ if state != session[:auth_state]
89
+ raise "state has been changed"
90
+ end
91
+
92
+ decrypted = decrypt_verified_data(verify_key, verified_data)
93
+ validate_fields(decrypted, ["email"])
94
+ verify_email(decrypted["email"]["sei"])
95
+ { email: decrypted["email"]["email"], user: double_name }
96
+ end
97
+
98
+ def callback_url
99
+ options[:callback_url] || callback_path
100
+ end
101
+
102
+ def request_phase
103
+ state = SecureRandom.uuid.gsub("-", "")
104
+ scope = options[:scope].to_h { |field| [field, true] }
105
+ params = {
106
+ :appid => request.host_with_port,
107
+ :scope => JSON.generate(scope),
108
+ :publickey => Base64.strict_encode64(signing_key.verify_key.to_curve25519_public_key.to_s),
109
+ :redirecturl => callback_url,
110
+ :state => state,
111
+ }
112
+
113
+ session[:auth_state] = params[:state]
114
+ redirect "#{options[:server_url]}?#{params.to_query}"
115
+ end
116
+
117
+ def callback_phase
118
+ begin
119
+ attempt = JSON.parse(request.params["signedAttempt"])
120
+ @data = verify(attempt)
121
+ rescue => err
122
+ fail!(:error, err)
123
+ end
124
+
125
+ super
126
+ end
127
+
128
+ def username
129
+ data[:user].chomp(".3bot")
130
+ end
131
+
132
+ def email
133
+ data[:email]
134
+ end
135
+
136
+ uid do
137
+ username
138
+ end
139
+
140
+ info do
141
+ {
142
+ :name => username,
143
+ :nickname => username,
144
+ :email => email,
145
+ :verified => true,
146
+ }
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,8 @@
1
+ module Omniauth
2
+ module Threefold
3
+ module Connect
4
+ VERSION: String
5
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
6
+ end
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-threefold-connect
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Omar
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-12-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Omniauth strategy for ThreeFold connect auth!
14
+ email: omarabdul3ziz@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - Gemfile
20
+ - README.md
21
+ - Rakefile
22
+ - lib/omniauth/threefold/connect.rb
23
+ - lib/omniauth/threefold/connect/version.rb
24
+ - sig/omniauth/threefold/connect.rbs
25
+ homepage: https://github.com/Omarabdul3ziz/omniauth-threefold-connect
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubygems_version: 3.3.25
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Omniauth strategy for ThreeFold connect auth!
48
+ test_files: []