discourse_api 0.2.8 → 0.2.9
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 +8 -8
- data/lib/discourse_api.rb +1 -0
- data/lib/discourse_api/api/sso.rb +1 -3
- data/lib/discourse_api/single_sign_on.rb +102 -0
- data/lib/discourse_api/version.rb +1 -1
- metadata +4 -3
- data/lib/single_sign_on.rb +0 -98
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODA2NDFjN2M1NWFhODkxZGM2Yjg3MTlhYWM2MWUzNzhiOGNiZTM0MA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MTVhODU2YmE5MDM3ODdiZGUwMTQxY2U4ZGNiM2MyZjAxNmM1ODBhZg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODAyY2M0MzU2OTk5ODVmNDJhNjIxNjgzODI4ZGRlODUyMjdlNzIyZDI1MjVj
|
10
|
+
ZjFiMzg2MjA2ZWQ0MjM3MDhhYWIwODEzNjhjNDQ4ZmQ3YmQ1OWYzNTk0MjQz
|
11
|
+
MWFlMWI2ZjcyZWUxOWJiOGYzNTM5YzE1NDA3YjQ3OTEzMTczY2I=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
N2Q3YmYzMzZkZjIxMzRjYWMxNzEzY2VhNjU2NmFmMWYzYWVmOTY2MjNiNWM2
|
14
|
+
NTgzYjRiYTA1MmVjMTU4NzdiMzBiMTJlZmUzYmFlM2Q5YWVlYmJhYmY4NjEw
|
15
|
+
YmE0ZDBkY2IyODk3ZTBjYzk4Mjc4MTZhNDRjYWYyMTVkMGM1ODc=
|
data/lib/discourse_api.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
require 'single_sign_on'
|
2
|
-
|
3
1
|
module DiscourseApi
|
4
2
|
module API
|
5
3
|
module SSO
|
6
4
|
def sync_sso(params={})
|
7
|
-
sso = SingleSignOn.new
|
5
|
+
sso = DiscourseApi::SingleSignOn.new
|
8
6
|
sso.sso_secret = params[:sso_secret]
|
9
7
|
sso.name = params[:name]
|
10
8
|
sso.username = params[:username]
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'rack'
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
module DiscourseApi
|
6
|
+
class SingleSignOn
|
7
|
+
ACCESSORS = [:nonce, :name, :username, :email, :avatar_url, :avatar_force_update,
|
8
|
+
:about_me, :external_id, :return_sso_url, :admin, :moderator]
|
9
|
+
FIXNUMS = []
|
10
|
+
BOOLS = [:avatar_force_update, :admin, :moderator]
|
11
|
+
|
12
|
+
attr_accessor(*ACCESSORS)
|
13
|
+
attr_accessor :sso_secret, :sso_url
|
14
|
+
|
15
|
+
def self.sso_secret
|
16
|
+
raise RuntimeError, "sso_secret not implemented on class, be sure to set it on instance"
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.sso_url
|
20
|
+
raise RuntimeError, "sso_url not implemented on class, be sure to set it on instance"
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.parse(payload, sso_secret = nil)
|
24
|
+
sso = new
|
25
|
+
sso.sso_secret = sso_secret if sso_secret
|
26
|
+
|
27
|
+
parsed = Rack::Utils.parse_query(payload)
|
28
|
+
if sso.sign(parsed["sso"]) != parsed["sig"]
|
29
|
+
raise RuntimeError, "Bad signature for payload"
|
30
|
+
end
|
31
|
+
|
32
|
+
decoded = Base64.decode64(parsed["sso"])
|
33
|
+
decoded_hash = Rack::Utils.parse_query(decoded)
|
34
|
+
|
35
|
+
ACCESSORS.each do |k|
|
36
|
+
val = decoded_hash[k.to_s]
|
37
|
+
val = val.to_i if FIXNUMS.include? k
|
38
|
+
if BOOLS.include? k
|
39
|
+
val = ["true", "false"].include?(val) ? val == "true" : nil
|
40
|
+
end
|
41
|
+
sso.send("#{k}=", val)
|
42
|
+
end
|
43
|
+
|
44
|
+
decoded_hash.each do |k,v|
|
45
|
+
# 1234567
|
46
|
+
# custom.
|
47
|
+
#
|
48
|
+
if k[0..6] == "custom."
|
49
|
+
field = k[7..-1]
|
50
|
+
sso.custom_fields[field] = v
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
sso
|
55
|
+
end
|
56
|
+
|
57
|
+
def sso_secret
|
58
|
+
@sso_secret || self.class.sso_secret
|
59
|
+
end
|
60
|
+
|
61
|
+
def sso_url
|
62
|
+
@sso_url || self.class.sso_url
|
63
|
+
end
|
64
|
+
|
65
|
+
def custom_fields
|
66
|
+
@custom_fields ||= {}
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def sign(payload)
|
71
|
+
OpenSSL::HMAC.hexdigest("sha256", sso_secret, payload)
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def to_url(base_url=nil)
|
76
|
+
base = "#{base_url || sso_url}"
|
77
|
+
"#{base}#{base.include?('?') ? '&' : '?'}#{payload}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def payload
|
81
|
+
payload = Base64.encode64(unsigned_payload)
|
82
|
+
"sso=#{CGI::escape(payload)}&sig=#{sign(payload)}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def unsigned_payload
|
86
|
+
payload = {}
|
87
|
+
ACCESSORS.each do |k|
|
88
|
+
next if (val = send k) == nil
|
89
|
+
|
90
|
+
payload[k] = val
|
91
|
+
end
|
92
|
+
|
93
|
+
if @custom_fields
|
94
|
+
@custom_fields.each do |k,v|
|
95
|
+
payload["custom.#{k}"] = v.to_s
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
Rack::Utils.build_query(payload)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: discourse_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-11-
|
13
|
+
date: 2014-11-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: faraday
|
@@ -220,8 +220,8 @@ files:
|
|
220
220
|
- lib/discourse_api/api/users.rb
|
221
221
|
- lib/discourse_api/client.rb
|
222
222
|
- lib/discourse_api/error.rb
|
223
|
+
- lib/discourse_api/single_sign_on.rb
|
223
224
|
- lib/discourse_api/version.rb
|
224
|
-
- lib/single_sign_on.rb
|
225
225
|
- routes.txt
|
226
226
|
- spec/discourse_api/api/categories_spec.rb
|
227
227
|
- spec/discourse_api/api/groups_spec.rb
|
@@ -298,3 +298,4 @@ test_files:
|
|
298
298
|
- spec/fixtures/user_update_user.json
|
299
299
|
- spec/fixtures/user_update_username.json
|
300
300
|
- spec/spec_helper.rb
|
301
|
+
has_rdoc:
|
data/lib/single_sign_on.rb
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'rack'
|
3
|
-
require 'openssl'
|
4
|
-
|
5
|
-
class SingleSignOn
|
6
|
-
ACCESSORS = [:nonce, :name, :username, :email, :avatar_url, :avatar_force_update,
|
7
|
-
:about_me, :external_id]
|
8
|
-
FIXNUMS = []
|
9
|
-
NONCE_EXPIRY_TIME = 600 # 10 minutes
|
10
|
-
|
11
|
-
attr_accessor(*ACCESSORS)
|
12
|
-
attr_accessor :sso_secret, :sso_url
|
13
|
-
|
14
|
-
def self.sso_secret
|
15
|
-
raise RuntimeError, "sso_secret not implemented on class, be sure to set it on instance"
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.sso_url
|
19
|
-
raise RuntimeError, "sso_url not implemented on class, be sure to set it on instance"
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.parse(payload, sso_secret = nil)
|
23
|
-
sso = new
|
24
|
-
sso.sso_secret = sso_secret if sso_secret
|
25
|
-
|
26
|
-
parsed = Rack::Utils.parse_query(payload)
|
27
|
-
if sso.sign(parsed["sso"]) != parsed["sig"]
|
28
|
-
raise RuntimeError, "Bad signature for payload"
|
29
|
-
end
|
30
|
-
|
31
|
-
decoded = Base64.decode64(parsed["sso"])
|
32
|
-
decoded_hash = Rack::Utils.parse_query(decoded)
|
33
|
-
|
34
|
-
ACCESSORS.each do |k|
|
35
|
-
val = decoded_hash[k.to_s]
|
36
|
-
val = val.to_i if FIXNUMS.include? k
|
37
|
-
sso.send("#{k}=", val)
|
38
|
-
end
|
39
|
-
|
40
|
-
decoded_hash.each do |k,v|
|
41
|
-
# 1234567
|
42
|
-
# custom.
|
43
|
-
#
|
44
|
-
if k[0..6] == "custom."
|
45
|
-
field = k[7..-1]
|
46
|
-
sso.custom_fields[field] = v
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
sso
|
51
|
-
end
|
52
|
-
|
53
|
-
def sso_secret
|
54
|
-
@sso_secret || self.class.sso_secret
|
55
|
-
end
|
56
|
-
|
57
|
-
def sso_url
|
58
|
-
@sso_url || self.class.sso_url
|
59
|
-
end
|
60
|
-
|
61
|
-
def custom_fields
|
62
|
-
@custom_fields ||= {}
|
63
|
-
end
|
64
|
-
|
65
|
-
|
66
|
-
def sign(payload)
|
67
|
-
OpenSSL::HMAC.hexdigest("sha256", sso_secret, payload)
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
def to_url(base_url=nil)
|
72
|
-
base = "#{base_url || sso_url}"
|
73
|
-
"#{base}#{base.include?('?') ? '&' : '?'}#{payload}"
|
74
|
-
end
|
75
|
-
|
76
|
-
def payload
|
77
|
-
payload = Base64.encode64(unsigned_payload)
|
78
|
-
"sso=#{CGI::escape(payload)}&sig=#{sign(payload)}"
|
79
|
-
end
|
80
|
-
|
81
|
-
def unsigned_payload
|
82
|
-
payload = {}
|
83
|
-
ACCESSORS.each do |k|
|
84
|
-
next unless (val = send k)
|
85
|
-
|
86
|
-
payload[k] = val
|
87
|
-
end
|
88
|
-
|
89
|
-
if @custom_fields
|
90
|
-
@custom_fields.each do |k,v|
|
91
|
-
payload["custom.#{k}"] = v.to_s
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
Rack::Utils.build_query(payload)
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|