omniauth-desk 0.1.7 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/Rakefile +2 -1
- data/lib/omniauth-desk.rb +2 -1
- data/lib/omniauth-desk/version.rb +1 -1
- data/lib/omniauth/desk/signed_request.rb +56 -0
- data/lib/omniauth/strategies/desk.rb +38 -5
- data/omniauth-desk.gemspec +0 -1
- data/spec/omniauth/desk/signed_request_spec.rb +37 -0
- data/spec/omniauth/strategies/desk_spec.rb +38 -9
- data/spec/spec_helper.rb +2 -0
- metadata +5 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 613f20bbbfc3140cd48a42ff218cb7c3cdf50e26
|
4
|
+
data.tar.gz: 7c420f92b70dd824d03e17d9c787a62e692f3f5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20a44bfddbb942944e4c1bc4a60523a4ab1ac09d74663f053eef626864f05f2878a1a9d3d58f126be99203c5cf1574a96224de0a3b7b75129a214a34ad9265a6
|
7
|
+
data.tar.gz: e212d3b6c938b031f9c9da1d681cea0c30008b55728a03e59c1056fa6a2eeb6c7d039dd2a4c43f673a9cb14d9fad5cb02dc60cb7d511a72ca4161d498b42b9df
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/lib/omniauth-desk.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
module OmniAuth
|
2
|
+
module Desk
|
3
|
+
module SignedRequest
|
4
|
+
ALGORITHM = 'HMACSHA256'.freeze
|
5
|
+
class Error < ArgumentError; end
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def decode(str, options = {})
|
9
|
+
shared_secret = options[:shared_secret] || ENV['DESK_SHARED_SECRET']
|
10
|
+
signature, envelope = str.split('.', 2)
|
11
|
+
hash = JSON.parse(base64_decode(envelope))
|
12
|
+
|
13
|
+
if hash['algorithm'] != ALGORITHM
|
14
|
+
raise Error.new("Invalid algorithm, use `#{ALGORITHM}`.")
|
15
|
+
end
|
16
|
+
|
17
|
+
if compare_time(hash['expiresAt'])
|
18
|
+
raise Error.new("Expired request.")
|
19
|
+
end
|
20
|
+
|
21
|
+
if base64_decode(signature) != hex(shared_secret, envelope).split.pack('H*')
|
22
|
+
raise Error.new("Invalid signature.")
|
23
|
+
end
|
24
|
+
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
|
28
|
+
def encode(hash, options = {})
|
29
|
+
shared_secret = options[:shared_secret] || ENV['DESK_SHARED_SECRET']
|
30
|
+
envelope = base64_encode(JSON.generate(hash))
|
31
|
+
signature = base64_encode(hex(shared_secret, envelope).split.pack('H*'))
|
32
|
+
signature + '.' + envelope
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def compare_time(str)
|
38
|
+
Time.parse(str).to_i < Time.now.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
def hex(secret, data)
|
42
|
+
OpenSSL::HMAC.hexdigest('sha256', secret, data)
|
43
|
+
end
|
44
|
+
|
45
|
+
def base64_decode(str)
|
46
|
+
str += '=' * (4 - str.length.modulo(4))
|
47
|
+
Base64.decode64(str.tr('-_', '+/'))
|
48
|
+
end
|
49
|
+
|
50
|
+
def base64_encode(str)
|
51
|
+
Base64.strict_encode64(str).tr('+/', '-_').tr('=', '')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'omniauth-oauth'
|
2
|
-
require 'multi_json'
|
3
2
|
require 'uri'
|
4
3
|
|
5
4
|
module OmniAuth
|
@@ -8,7 +7,8 @@ module OmniAuth
|
|
8
7
|
class Desk < OmniAuth::Strategies::OAuth
|
9
8
|
option :name, 'desk'
|
10
9
|
option :site, nil
|
11
|
-
option :site_param, '
|
10
|
+
option :site_param, 'site'
|
11
|
+
option :shared_secret, nil
|
12
12
|
option :client_options, {
|
13
13
|
:authorize_path => '/oauth/authorize',
|
14
14
|
:request_token_path => '/oauth/request_token',
|
@@ -38,7 +38,11 @@ module OmniAuth
|
|
38
38
|
|
39
39
|
# Return info gathered from the verify_credentials API call
|
40
40
|
def raw_info
|
41
|
-
|
41
|
+
if access_token
|
42
|
+
@raw_info ||= JSON.parse(access_token.get('/api/v2/users/me').body)
|
43
|
+
elsif signed_request
|
44
|
+
@raw_info ||= decode(signed_request)
|
45
|
+
end
|
42
46
|
rescue ::Errno::ETIMEDOUT
|
43
47
|
raise ::Timeout::Error
|
44
48
|
end
|
@@ -48,6 +52,25 @@ module OmniAuth
|
|
48
52
|
@user_info ||= raw_info.nil? ? {} : raw_info
|
49
53
|
end
|
50
54
|
|
55
|
+
def decode(signed_request)
|
56
|
+
hash = OmniAuth::Desk::SignedRequest.decode(
|
57
|
+
signed_request, shared_secret: options.shared_secret
|
58
|
+
)['context']['user']
|
59
|
+
|
60
|
+
{
|
61
|
+
'id' => hash['userId'],
|
62
|
+
'name' => hash['fullName'],
|
63
|
+
'public_name' => hash['fullName'],
|
64
|
+
'email' => hash['email'],
|
65
|
+
'avatar' => hash['profileThumbnailUrl'],
|
66
|
+
'level' => hash['userType']
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def signed_request
|
71
|
+
@signed_request ||= request.params['signed_request']
|
72
|
+
end
|
73
|
+
|
51
74
|
def identifier
|
52
75
|
session[:site] = options.client_options.site = options.site || validate_site(request.params[options.site_param.to_s])
|
53
76
|
session[:site] = options.client_options.site = nil if options.client_options.site == ''
|
@@ -80,8 +103,18 @@ module OmniAuth
|
|
80
103
|
end
|
81
104
|
|
82
105
|
def callback_phase
|
83
|
-
|
84
|
-
|
106
|
+
if signed_request.nil?
|
107
|
+
options.client_options.site = session[:site] if session[:site]
|
108
|
+
super
|
109
|
+
else
|
110
|
+
env['omniauth.auth'] = AuthHash.new({
|
111
|
+
provider: name,
|
112
|
+
uid: uid,
|
113
|
+
info: info,
|
114
|
+
extra: extra
|
115
|
+
})
|
116
|
+
call_app!
|
117
|
+
end
|
85
118
|
end
|
86
119
|
end
|
87
120
|
end
|
data/omniauth-desk.gemspec
CHANGED
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.add_runtime_dependency 'omniauth', '>= 1.0'
|
22
22
|
s.add_runtime_dependency 'omniauth-oauth', '>= 1.0'
|
23
|
-
s.add_runtime_dependency 'multi_json', '>= 1.3.6'
|
24
23
|
|
25
24
|
s.add_development_dependency 'rspec', '~> 3.5'
|
26
25
|
s.add_development_dependency 'rack-test'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'omniauth/desk/signed_request'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
describe OmniAuth::Desk::SignedRequest do
|
6
|
+
let(:shared_secret) { SecureRandom.uuid.gsub('-', '') }
|
7
|
+
let(:working) { { "expiresAt" => (Time.now + 10*60).iso8601, "algorithm" => "HMACSHA256" } }
|
8
|
+
let(:unsupported) { working.merge({ "algorithm" => "HMACSHA512" }) }
|
9
|
+
let(:too_old) { working.merge({ "expiresAt" => (Time.now - 1).iso8601 }) }
|
10
|
+
|
11
|
+
it 'encodes a valid request' do
|
12
|
+
encoded = OmniAuth::Desk::SignedRequest.encode(working, shared_secret: shared_secret)
|
13
|
+
decoded = OmniAuth::Desk::SignedRequest.decode(encoded, shared_secret: shared_secret)
|
14
|
+
expect(decoded).to eq(working)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'throws an unsupported algorithm error' do
|
18
|
+
expect do
|
19
|
+
encoded = OmniAuth::Desk::SignedRequest.encode(unsupported, shared_secret: shared_secret)
|
20
|
+
OmniAuth::Desk::SignedRequest.decode(encoded, shared_secret: shared_secret)
|
21
|
+
end.to raise_error(OmniAuth::Desk::SignedRequest::Error)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'throws a too old error' do
|
25
|
+
expect do
|
26
|
+
encoded = OmniAuth::Desk::SignedRequest.encode(too_old, shared_secret: shared_secret)
|
27
|
+
OmniAuth::Desk::SignedRequest.decode(encoded, shared_secret: shared_secret)
|
28
|
+
end.to raise_error(OmniAuth::Desk::SignedRequest::Error)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'throws an invalid signature error' do
|
32
|
+
expect do
|
33
|
+
encoded = OmniAuth::Desk::SignedRequest.encode(working, shared_secret: shared_secret)
|
34
|
+
OmniAuth::Desk::SignedRequest.decode(encoded, shared_secret: SecureRandom.uuid.gsub('-', ''))
|
35
|
+
end.to raise_error(OmniAuth::Desk::SignedRequest::Error)
|
36
|
+
end
|
37
|
+
end
|
@@ -2,10 +2,9 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe OmniAuth::Strategies::Desk, :type => :strategy do
|
4
4
|
def app
|
5
|
-
|
6
|
-
|
7
|
-
use
|
8
|
-
use strat
|
5
|
+
@app ||= Rack::Builder.new {
|
6
|
+
use Rack::Session::Cookie, secret: "MY_SECRET"
|
7
|
+
use OmniAuth::Strategies::Desk, shared_secret: SecureRandom.uuid.gsub('-', '')
|
9
8
|
run lambda {|env| [404, {'Content-Type' => 'text/plain'}, [nil || env.key?('omniauth.auth').to_s]] }
|
10
9
|
}.to_app
|
11
10
|
end
|
@@ -24,7 +23,7 @@ describe OmniAuth::Strategies::Desk, :type => :strategy do
|
|
24
23
|
end
|
25
24
|
|
26
25
|
it 'should render an identifier URL input' do
|
27
|
-
expect(last_response.body).to match(/<input[^>]*
|
26
|
+
expect(last_response.body).to match(/<input[^>]*site/)
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
@@ -32,7 +31,7 @@ describe OmniAuth::Strategies::Desk, :type => :strategy do
|
|
32
31
|
before do
|
33
32
|
@stub_devel = stub_request(:post, "https://devel.desk.com/oauth/request_token")
|
34
33
|
.to_return(status: 200, body: 'oauth_token=&oauth_token_secret=')
|
35
|
-
post '/auth/desk',
|
34
|
+
post '/auth/desk', site: 'devel'
|
36
35
|
end
|
37
36
|
|
38
37
|
it 'should have been requested' do
|
@@ -44,7 +43,7 @@ describe OmniAuth::Strategies::Desk, :type => :strategy do
|
|
44
43
|
before do
|
45
44
|
@stub_devel = stub_request(:post, "https://devel.desk.com/oauth/request_token")
|
46
45
|
.to_return(status: 200, body: 'oauth_token=&oauth_token_secret=')
|
47
|
-
post '/auth/desk',
|
46
|
+
post '/auth/desk', site: 'https://devel.desk.com'
|
48
47
|
end
|
49
48
|
|
50
49
|
it 'should have been requested' do
|
@@ -58,7 +57,7 @@ describe OmniAuth::Strategies::Desk, :type => :strategy do
|
|
58
57
|
stub_request(:post, "https://devel.desk.com/oauth/request_token")
|
59
58
|
.to_return(status: 200, body: 'oauth_token=&oauth_token_secret=')
|
60
59
|
|
61
|
-
post '/auth/desk',
|
60
|
+
post '/auth/desk', site: 'https://devel.desk.com'
|
62
61
|
|
63
62
|
@access_token = stub_request(:post, "https://devel.desk.com/oauth/access_token")
|
64
63
|
.to_return(status: 200, body: "oauth_token=6253282-eWudHldSbIaelX7swmsiHImEL4KinwaGloHANdrY&oauth_token_secret=2EEfA6BG3ly3sR3RjE0IBSnlQu4ZrUzPiYKmrkVU&user_id=6253282&screen_name=twitterapi")
|
@@ -78,6 +77,36 @@ describe OmniAuth::Strategies::Desk, :type => :strategy do
|
|
78
77
|
end
|
79
78
|
end
|
80
79
|
|
80
|
+
context 'signed request' do
|
81
|
+
before do
|
82
|
+
signed_request = OmniAuth::Desk::SignedRequest.encode({
|
83
|
+
"currentTime": Time.now.iso8601,
|
84
|
+
"expiresAt": (Time.now+3600).iso8601,
|
85
|
+
"algorithm": "HMACSHA256",
|
86
|
+
"userId": "1",
|
87
|
+
"context": {
|
88
|
+
"user": {
|
89
|
+
"userId": "1",
|
90
|
+
"userName": "agent@desk.com",
|
91
|
+
"email": "agent@desk.com",
|
92
|
+
"fullName": "Joe Agent",
|
93
|
+
"locale": "en_us",
|
94
|
+
"language": "en_us",
|
95
|
+
"timeZone": "Pacific Time (US & Canada)",
|
96
|
+
"roleId": 60,
|
97
|
+
"userType": "agent",
|
98
|
+
"profileThumbnailUrl": "http://www.gravatar.com/avatar/8a4e3154a0f99458dd1f382e72174198?default=mm&rating=PG&size=50"
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}, shared_secret: app.instance_variable_get(:@app).options.shared_secret)
|
102
|
+
post '/auth/desk/callback', signed_request: signed_request
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should set omniauth.auth' do
|
106
|
+
expect(last_request.env['omniauth.auth']).not_to be_nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
81
110
|
context 'unsuccessful' do
|
82
111
|
before do
|
83
112
|
get '/auth/desk/callback'
|
@@ -94,7 +123,7 @@ describe OmniAuth::Strategies::Desk, :type => :strategy do
|
|
94
123
|
before do
|
95
124
|
stub_request(:post, "https://thisdoesnotexist.desk.com/oauth/request_token")
|
96
125
|
.to_return(status: 403, body: 'oauth_token=&oauth_token_secret=')
|
97
|
-
post '/auth/desk',
|
126
|
+
post '/auth/desk', site: 'https://thisdoesnotexist.desk.com'
|
98
127
|
end
|
99
128
|
|
100
129
|
it 'should be redirected to failure' do
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omniauth-desk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Stachl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: omniauth
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: multi_json
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 1.3.6
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 1.3.6
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: rspec
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -124,8 +110,10 @@ files:
|
|
124
110
|
- Rakefile
|
125
111
|
- lib/omniauth-desk.rb
|
126
112
|
- lib/omniauth-desk/version.rb
|
113
|
+
- lib/omniauth/desk/signed_request.rb
|
127
114
|
- lib/omniauth/strategies/desk.rb
|
128
115
|
- omniauth-desk.gemspec
|
116
|
+
- spec/omniauth/desk/signed_request_spec.rb
|
129
117
|
- spec/omniauth/strategies/desk_spec.rb
|
130
118
|
- spec/spec_helper.rb
|
131
119
|
homepage: https://github.com/tstachl/omniauth-desk
|
@@ -152,5 +140,6 @@ signing_key:
|
|
152
140
|
specification_version: 4
|
153
141
|
summary: OmniAuth strategy for Desk.com
|
154
142
|
test_files:
|
143
|
+
- spec/omniauth/desk/signed_request_spec.rb
|
155
144
|
- spec/omniauth/strategies/desk_spec.rb
|
156
145
|
- spec/spec_helper.rb
|