omniauth-heroku 0.1.1 → 0.1.2.pre

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  [OmniAuth](https://github.com/intridea/omniauth) strategy for authenticating to Heroku.
4
4
 
5
- Heroku's support for OAuth is still private/experimental.
6
-
7
5
 
8
6
  ## Configuration
9
7
 
@@ -74,6 +72,15 @@ And view:
74
72
  </ul>
75
73
  ```
76
74
 
75
+ ## A note on security
76
+
77
+ Be careful if you intend to store access tokens in cookie-based sessions.
78
+
79
+ Many web frameworks offer protection against session tampering, but still store sessions with no encryption. This allows attackers with some access to the user session to obtain valuable information from cookies.
80
+
81
+ Rails, Sinatra and others can be configured to encrypt cookies, but don't do it by default. So make sure to encrypt cookie-based sessions before storing confidential data on it!
82
+
83
+
77
84
  ## Meta
78
85
 
79
86
  Released under the MIT license.
@@ -1,8 +1,6 @@
1
- require 'omniauth-oauth2'
2
-
3
1
  module OmniAuth
4
2
  module Strategies
5
- class Heroku < OmniAuth::Strategies::OAuth2
3
+ class Heroku < OmniAuth::Strategies::HerokuOAuth2
6
4
  BaseAuthUrl = ENV["HEROKU_AUTH_URL"] || "https://id.heroku.com"
7
5
 
8
6
  option :client_options, {
@@ -0,0 +1,124 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+ require 'oauth2'
4
+ require 'omniauth'
5
+ require 'timeout'
6
+ require 'securerandom'
7
+
8
+ module OmniAuth
9
+ module Strategies
10
+ # Vendored in from `omniauth-oauth2`, but with slight modifications to
11
+ # allow request IDs to be passed through during the token phase so that the
12
+ # OAuth 2 dance can be more easily debugged.
13
+ class HerokuOAuth2
14
+ include OmniAuth::Strategy
15
+
16
+ args [:client_id, :client_secret]
17
+
18
+ option :client_id, nil
19
+ option :client_secret, nil
20
+ option :client_options, {}
21
+ option :authorize_params, {}
22
+ option :authorize_options, [:scope]
23
+ option :token_params, {}
24
+ option :token_options, []
25
+ option :provider_ignores_state, false
26
+ option :request_id, lambda { |env| nil }
27
+
28
+ attr_accessor :access_token
29
+
30
+ def client
31
+ ::OAuth2::Client.new(options.client_id, options.client_secret, deep_symbolize(options.client_options))
32
+ end
33
+
34
+ def callback_url
35
+ full_host + script_name + callback_path
36
+ end
37
+
38
+ credentials do
39
+ hash = {'token' => access_token.token}
40
+ hash.merge!('refresh_token' => access_token.refresh_token) if access_token.expires? && access_token.refresh_token
41
+ hash.merge!('expires_at' => access_token.expires_at) if access_token.expires?
42
+ hash.merge!('expires' => access_token.expires?)
43
+ hash
44
+ end
45
+
46
+ def request_phase
47
+ redirect client.auth_code.authorize_url({:redirect_uri => callback_url}.merge(authorize_params))
48
+ end
49
+
50
+ def authorize_params
51
+ options.authorize_params[:state] = SecureRandom.hex(24)
52
+ params = options.authorize_params.merge(options.authorize_options.inject({}){|h,k| h[k.to_sym] = options[k] if options[k]; h})
53
+ if OmniAuth.config.test_mode
54
+ @env ||= {}
55
+ @env['rack.session'] ||= {}
56
+ end
57
+ session['omniauth.state'] = params[:state]
58
+ params
59
+ end
60
+
61
+ def token_params
62
+ options.token_params.merge(options.token_options.inject({}){|h,k| h[k.to_sym] = options[k] if options[k]; h})
63
+ end
64
+
65
+ def callback_phase
66
+ if request.params['error'] || request.params['error_reason']
67
+ raise CallbackError.new(request.params['error'], request.params['error_description'] || request.params['error_reason'], request.params['error_uri'])
68
+ end
69
+ # if !options.provider_ignores_state && (request.params['state'].to_s.empty? || request.params['state'] != session.delete('omniauth.state'))
70
+ # raise CallbackError.new(nil, :csrf_detected)
71
+ # end
72
+
73
+ self.access_token = build_access_token
74
+ params = {}
75
+ if request_id = options.request_id.call(@env)
76
+ params.merge!(:headers => { "Request-Id" => request_id })
77
+ end
78
+ self.access_token = access_token.refresh!(params) if access_token.expired?
79
+
80
+ super
81
+ rescue ::OAuth2::Error, CallbackError => e
82
+ fail!(:invalid_credentials, e)
83
+ rescue ::MultiJson::DecodeError => e
84
+ fail!(:invalid_response, e)
85
+ rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
86
+ fail!(:timeout, e)
87
+ rescue ::SocketError => e
88
+ fail!(:failed_to_connect, e)
89
+ end
90
+
91
+ protected
92
+
93
+ def deep_symbolize(hash)
94
+ hash.inject({}) do |h, (k,v)|
95
+ h[k.to_sym] = v.is_a?(Hash) ? deep_symbolize(v) : v
96
+ h
97
+ end
98
+ end
99
+
100
+ def build_access_token
101
+ verifier = request.params['code']
102
+ params = {:redirect_uri => callback_url}.
103
+ merge(token_params.to_hash(:symbolize_keys => true))
104
+ # inject a request ID if one is available
105
+ if request_id = options.request_id.call(@env)
106
+ params.merge!(:headers => { "Request-Id" => request_id })
107
+ end
108
+ client.auth_code.get_token(verifier, params)
109
+ end
110
+
111
+ # An error that is indicated in the OAuth 2.0 callback.
112
+ # This could be a `redirect_uri_mismatch` or other
113
+ class CallbackError < StandardError
114
+ attr_accessor :error, :error_reason, :error_uri
115
+
116
+ def initialize(error, error_reason=nil, error_uri=nil)
117
+ self.error = error
118
+ self.error_reason = error_reason
119
+ self.error_uri = error_uri
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -1 +1,2 @@
1
+ require 'omniauth/strategies/heroku_oauth2'
1
2
  require 'omniauth/strategies/heroku'
@@ -9,8 +9,8 @@ Gem::Specification.new do |gem|
9
9
  gem.files = `git ls-files`.split("\n")
10
10
  gem.name = "omniauth-heroku"
11
11
  gem.require_paths = ["lib"]
12
- gem.version = "0.1.1"
12
+ gem.version = "0.1.2.pre"
13
13
 
14
+ gem.add_dependency 'oauth2', '~> 0.8.0'
14
15
  gem.add_dependency 'omniauth', '~> 1.0'
15
- gem.add_dependency 'omniauth-oauth2', '~> 1.0'
16
16
  end
metadata CHANGED
@@ -1,24 +1,24 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-heroku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
5
- prerelease:
4
+ version: 0.1.2.pre
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Pedro Belo
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-12 00:00:00.000000000 Z
12
+ date: 2013-08-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: omniauth
15
+ name: oauth2
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '1.0'
21
+ version: 0.8.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,9 +26,9 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: '1.0'
29
+ version: 0.8.0
30
30
  - !ruby/object:Gem::Dependency
31
- name: omniauth-oauth2
31
+ name: omniauth
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
@@ -56,6 +56,7 @@ files:
56
56
  - Rakefile
57
57
  - lib/omniauth-heroku.rb
58
58
  - lib/omniauth/strategies/heroku.rb
59
+ - lib/omniauth/strategies/heroku_oauth2.rb
59
60
  - omniauth-heroku.gemspec
60
61
  homepage: https://github.com/heroku/omniauth-heroku
61
62
  licenses: []
@@ -72,9 +73,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
72
73
  required_rubygems_version: !ruby/object:Gem::Requirement
73
74
  none: false
74
75
  requirements:
75
- - - ! '>='
76
+ - - ! '>'
76
77
  - !ruby/object:Gem::Version
77
- version: '0'
78
+ version: 1.3.1
78
79
  requirements: []
79
80
  rubyforge_project:
80
81
  rubygems_version: 1.8.24