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 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