omniauth-desk 0.1.7 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 78ae51cd756cb4ce1389d03aadad0ff24920bdbc
4
- data.tar.gz: b5299b0606bbf76e9e888952da4732d751a1a24c
3
+ metadata.gz: 613f20bbbfc3140cd48a42ff218cb7c3cdf50e26
4
+ data.tar.gz: 7c420f92b70dd824d03e17d9c787a62e692f3f5b
5
5
  SHA512:
6
- metadata.gz: 737efb1f76b076c0b84d997105b8eff2e55008be070d3972fcfaae73545d108844d8bf391afbb07199b63e5e20c989bef56b1266fa2da84a236285dd194d8abd
7
- data.tar.gz: cca26acc58fa1cd48a543d2726657c5570e4ca05afa708f44ed7c46b0a1cb38f8612ac0e5906848477cd057a01a90cbebea49e125330f72e436fcb45fcb8ed02
6
+ metadata.gz: 20a44bfddbb942944e4c1bc4a60523a4ab1ac09d74663f053eef626864f05f2878a1a9d3d58f126be99203c5cf1574a96224de0a3b7b75129a214a34ad9265a6
7
+ data.tar.gz: e212d3b6c938b031f9c9da1d681cea0c30008b55728a03e59c1056fa6a2eeb6c7d039dd2a4c43f673a9cb14d9fad5cb02dc60cb7d511a72ca4161d498b42b9df
data/Gemfile CHANGED
@@ -5,4 +5,5 @@ gemspec
5
5
 
6
6
  group :development, :test do
7
7
  gem 'rake'
8
- end
8
+ gem 'pry'
9
+ end
data/Rakefile CHANGED
@@ -5,4 +5,5 @@ desc "Run specs"
5
5
  RSpec::Core::RakeTask.new
6
6
 
7
7
  desc 'Default: run specs.'
8
- task :default => :spec
8
+ task :default => :spec
9
+ task :test => :spec
@@ -1,2 +1,3 @@
1
1
  require 'omniauth-desk/version'
2
- require 'omniauth/strategies/desk'
2
+ require 'omniauth/desk/signed_request'
3
+ require 'omniauth/strategies/desk'
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module Desk
3
- VERSION = "0.1.7"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -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, 'desk_site'
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
- @raw_info ||= MultiJson.decode(access_token.get('/api/v2/users/me').body) if access_token
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
- options.client_options.site = session[:site] if session[:site]
84
- super
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
@@ -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
- strat = OmniAuth::Strategies::Desk
6
- Rack::Builder.new {
7
- use Rack::Session::Cookie, :secret => "MY_SECRET"
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[^>]*desk_site/)
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', desk_site: 'devel'
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', desk_site: 'https://devel.desk.com'
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', desk_site: 'https://devel.desk.com'
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', desk_site: 'https://thisdoesnotexist.desk.com'
126
+ post '/auth/desk', site: 'https://thisdoesnotexist.desk.com'
98
127
  end
99
128
 
100
129
  it 'should be redirected to failure' do
@@ -8,6 +8,8 @@ require 'webmock/rspec'
8
8
  require 'omniauth'
9
9
  require 'omniauth-desk'
10
10
 
11
+ OmniAuth.config.logger = Logger.new('/dev/null')
12
+
11
13
  RSpec.configure do |config|
12
14
  config.include WebMock::API
13
15
  config.include Rack::Test::Methods
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.1.7
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-07-13 00:00:00.000000000 Z
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