omniauth-heroku 0.1.1 → 0.4.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7114a261c4657b1093fa15c002dc0c5dc501c3a147670c99b31bb82bb2173290
4
+ data.tar.gz: 409fe3bd640e82ec72fc30f92ef9a0fd383bb95260b4f1d8d7d9d070b6d325b4
5
+ SHA512:
6
+ metadata.gz: 36e9c08495d7941cf3a19b8e2b972ec2d70fd992c326f88586141892c5bc445ab4ee9ff28927062d6a5babd58351f7b16fda97fcea9e5933750bc73178f5d6fd
7
+ data.tar.gz: 6d8bcd09cd0847c01f870ad2d955a90b21ac449b56ba0aafcd275790a9fc8efbca5aae86252a80f3ec916583780d352516b4065e275a9b9450c6201d034c4703
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Pedro Belo
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,8 +1,19 @@
1
1
  # OmniAuth Heroku
2
2
 
3
- [OmniAuth](https://github.com/intridea/omniauth) strategy for authenticating to Heroku.
3
+ [![Build Status](https://github.com/heroku/omniauth-heroku/actions/workflows/ci.yml/badge.svg)](https://github.com/heroku/omniauth-heroku/actions)
4
4
 
5
- Heroku's support for OAuth is still private/experimental.
5
+ [OmniAuth](https://github.com/intridea/omniauth) strategy for authenticating
6
+ Heroku users.
7
+
8
+ Mount this with your Rack application (be it Rails or Sinatra) to simplify the
9
+ [OAuth flow with Heroku](https://devcenter.heroku.com/articles/oauth).
10
+
11
+ This is intended for apps already using OmniAuth, for apps that authenticate
12
+ against more than one service (eg: Heroku and GitHub), or apps that have
13
+ specific needs on session management. If your app doesn't fall in any of these
14
+ you should consider using [Heroku Bouncer][heroku-bouncer] instead.
15
+
16
+ [heroku-bouncer]: https://github.com/heroku/heroku-bouncer
6
17
 
7
18
 
8
19
  ## Configuration
@@ -11,20 +22,116 @@ OmniAuth works as a Rack middleware. Mount this Heroku adapter with:
11
22
 
12
23
  ```ruby
13
24
  use OmniAuth::Builder do
14
- provider :heroku, ENV['HEROKU_OAUTH_ID'], ENV['HEROKU_OAUTH_SECRET']
25
+ provider :heroku, ENV.fetch("HEROKU_OAUTH_ID"), ENV.fetch("HEROKU_OAUTH_SECRET")
15
26
  end
16
27
  ```
17
28
 
18
- Your Heroku OAuth client should be set to receive callbacks on `/auth/heroku/callback`.
29
+ Obtain a `HEROKU_OAUTH_ID` and `HEROKU_OAUTH_SECRET` by creating a client with
30
+ the [Heroku OAuth CLI plugin](https://github.com/heroku/heroku-oauth).
31
+
32
+ Your Heroku OAuth client should be set to receive callbacks on
33
+ `/auth/heroku/callback`.
19
34
 
20
35
 
21
36
  ## Usage
22
37
 
23
38
  Initiate the OAuth flow sending users to `/auth/heroku`.
24
39
 
25
- Once the authorization flow is complete and the user is bounced back to your application, check `env["omniauth.auth"]["credentials"]`. It contains both a refresh token and an access token (identified just as `"token"`) to the account.
40
+ Once the authorization flow is complete and the user is bounced back to your
41
+ application, check `env["omniauth.auth"]["credentials"]`. It contains both a
42
+ refresh token and an access token (identified just as `"token"`) to the
43
+ account.
44
+
45
+ We recommend using this access token together with
46
+ the [Heroku Platform API gem][heroku-ruby-client] to make API calls on behalf of the user.
47
+
48
+ [heroku-ruby-client]: https://github.com/heroku/platform-api
49
+
50
+ Refer to the examples below to see how these work.
51
+
52
+
53
+ ### Basic account information
54
+
55
+ If you want this middleware to fetch additional Heroku account information like
56
+ the user email address and name, use the `fetch_info` option, like:
57
+
58
+ ```ruby
59
+ use OmniAuth::Builder do
60
+ provider :heroku, ENV.fetch("HEROKU_OAUTH_ID"), ENV.fetch("HEROKU_OAUTH_SECRET"),
61
+ fetch_info: true
62
+ end
63
+ ```
64
+
65
+ This sets name and email in the [omniauth auth hash][auth-hash]. You can access
66
+ it from your app via `env["omniauth.auth"]["info"]`.
67
+
68
+ [auth-hash]: https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema
69
+
70
+ It will also add [additional Heroku account info][platform-api] to
71
+ `env["omniauth.auth"]["extra"]`.
72
+
73
+ [platform-api]: https://devcenter.heroku.com/articles/platform-api-reference#account
74
+
75
+ ### OAuth scopes
76
+
77
+ [Heroku supports different OAuth scopes][oauth-scopes]. By default this
78
+ strategy will request global access to the account, but you're encouraged to
79
+ request for less permissions when possible.
80
+
81
+ [oauth-scopes]: https://devcenter.heroku.com/articles/oauth#scopes
82
+
83
+ To do so, configure it like:
84
+
85
+ ```ruby
86
+ use OmniAuth::Builder do
87
+ provider :heroku, ENV.fetch("HEROKU_OAUTH_ID"), ENV.fetch("HEROKU_OAUTH_SECRET"),
88
+ scope: "identity"
89
+ end
90
+ ```
91
+
92
+ This will trim down the permissions associated to the access token given back
93
+ to you.
94
+
95
+ The Oauth scope can also be decided dynamically at runtime. For example, you
96
+ could use a `scope` GET parameter if it exists, and revert to a default `scope`
97
+ if it does not:
98
+
99
+ ```ruby
100
+ use OmniAuth::Builder do
101
+ provider :heroku, ENV.fetch("HEROKU_OAUTH_ID"), ENV.fetch("HEROKU_OAUTH_SECRET"),
102
+ scope: ->(request) { request.params["scope"] || "identity" }
103
+ end
104
+ ```
105
+
106
+
107
+ ## Example - Sinatra
108
+
109
+ ```ruby
110
+ class Myapp < Sinatra::Application
111
+ use Rack::Session::Cookie, secret: ENV.fetch("SESSION_SECRET")
112
+
113
+ use OmniAuth::Builder do
114
+ provider :heroku, ENV.fetch("HEROKU_OAUTH_ID"), ENV.fetch("HEROKU_OAUTH_SECRET")
115
+ end
116
+
117
+ get "/" do
118
+ redirect "/auth/heroku"
119
+ end
26
120
 
27
- We recommend using this access token together with [Heroku.rb](https://github.com/heroku/heroku.rb) to make API calls on behalf of the user.
121
+ get "/auth/heroku/callback" do
122
+ access_token = env["omniauth.auth"]["credentials"]["token"]
123
+ # DO NOT store this token in an unencrypted cookie session
124
+ # Please read "A note on security" below!
125
+ heroku = PlatformAPI.connect_oauth(access_token)
126
+ "You have #{heroku.app.list.count} apps"
127
+ end
128
+ end
129
+ ```
130
+
131
+ Note that we're explicitly calling `Rack::Session::Cookie` with a secret. Using
132
+ `enable :sessions` is not recommended because the secret is generated randomly,
133
+ and not reused across processes – so your users can lose their session whenever
134
+ your app restarts.
28
135
 
29
136
 
30
137
  ## Example - Rails
@@ -33,7 +140,7 @@ Under `config/initializers/omniauth.rb`:
33
140
 
34
141
  ```ruby
35
142
  Rails.application.config.middleware.use OmniAuth::Builder do
36
- provider :heroku, ENV['HEROKU_OAUTH_ID'], ENV['HEROKU_OAUTH_SECRET']
143
+ provider :heroku, ENV.fetch("HEROKU_OAUTH_ID"), ENV.fetch("HEROKU_OAUTH_SECRET")
37
144
  end
38
145
  ```
39
146
 
@@ -56,8 +163,10 @@ class SessionsController < ApplicationController
56
163
 
57
164
  def create
58
165
  access_token = request.env['omniauth.auth']['credentials']['token']
59
- heroku_api = Heroku::API.new(:api_key => access_token)
60
- @apps = api.get_apps.body
166
+ # DO NOT store this token in an unencrypted cookie session
167
+ # Please read "A note on security" below!
168
+ heroku = PlatformAPI.connect_oauth(access_token)
169
+ @apps = heroku.app.list
61
170
  end
62
171
  end
63
172
  ```
@@ -74,6 +183,20 @@ And view:
74
183
  </ul>
75
184
  ```
76
185
 
186
+ ## A note on security
187
+
188
+ **Make sure your cookie session is encrypted before storing sensitive
189
+ information on it, like access tokens**. [encrypted_cookie][encrypted-cookie]
190
+ is a popular gem to do that in Ruby.
191
+
192
+ [encrypted-cookie]: https://github.com/cvonkleist/encrypted_cookie
193
+
194
+ Both Rails and Sinatra take a cookie secret, but that is only used to protect
195
+ against tampering; any information stored on standard cookie sessions can
196
+ easily be read from the client side, which can be further exploited to leak
197
+ credentials off your app.
198
+
199
+
77
200
  ## Meta
78
201
 
79
202
  Released under the MIT license.
@@ -3,13 +3,88 @@ require 'omniauth-oauth2'
3
3
  module OmniAuth
4
4
  module Strategies
5
5
  class Heroku < OmniAuth::Strategies::OAuth2
6
- BaseAuthUrl = ENV["HEROKU_AUTH_URL"] || "https://id.heroku.com"
6
+ AuthUrl = ENV["HEROKU_AUTH_URL"] || "https://id.heroku.com"
7
+ ApiUrl = ENV["HEROKU_API_URL"] || "https://api.heroku.com"
7
8
 
8
9
  option :client_options, {
9
- :site => BaseAuthUrl,
10
- :authorize_url => "#{BaseAuthUrl}/oauth/authorize",
11
- :token_url => "#{BaseAuthUrl}/oauth/token"
10
+ site: AuthUrl,
11
+ authorize_url: "#{AuthUrl}/oauth/authorize",
12
+ token_url: "#{AuthUrl}/oauth/token"
12
13
  }
14
+
15
+ # whether we should make another API call to Heroku to fetch
16
+ # additional account info like the real user name and email
17
+ option :fetch_info
18
+
19
+ uid do
20
+ access_token.params["user_id"]
21
+ end
22
+
23
+ info do
24
+ if options.fetch_info
25
+ email_hash = Digest::MD5.hexdigest(account_info['email'].to_s)
26
+ default_image_url = "https://dashboard.heroku.com/ninja-avatar-48x48.png"
27
+ image_url = "https://secure.gravatar.com/avatar/#{email_hash}.png?d=#{default_image_url}"
28
+
29
+ {
30
+ name: account_info["name"],
31
+ email: account_info["email"],
32
+ image: image_url,
33
+ }
34
+ else
35
+ { name: "Heroku user" } # only mandatory field
36
+ end
37
+ end
38
+
39
+ extra do
40
+ if options.fetch_info
41
+ account_info
42
+ else
43
+ {}
44
+ end
45
+ end
46
+
47
+ # override method in OmniAuth::Strategies::OAuth2 to error
48
+ # when we don't have a client_id or secret:
49
+ def request_phase
50
+ if missing_client_id?
51
+ fail!(:missing_client_id)
52
+ elsif missing_client_secret?
53
+ fail!(:missing_client_secret)
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ def authorize_params
60
+ super.tap do |params|
61
+ # Allow the scope to be determined dynamically based on the request.
62
+ if params.scope.respond_to?(:call)
63
+ params.scope = params.scope.call(request)
64
+ end
65
+ end
66
+ end
67
+
68
+ def account_info
69
+ @account_info ||= MultiJson.decode(heroku_api.get("/account").body)
70
+ end
71
+
72
+ def heroku_api
73
+ @heroku_api ||= Faraday.new(
74
+ url: ApiUrl,
75
+ headers: {
76
+ "Accept" => "application/vnd.heroku+json; version=3",
77
+ "Authorization" => "Bearer #{access_token.token}",
78
+ })
79
+ end
80
+
81
+ def missing_client_id?
82
+ [nil, ""].include?(options.client_id)
83
+ end
84
+
85
+ def missing_client_secret?
86
+ [nil, ""].include?(options.client_secret)
87
+ end
13
88
  end
14
89
  end
15
90
  end
metadata CHANGED
@@ -1,48 +1,43 @@
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.4.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Pedro Belo
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-03-12 00:00:00.000000000 Z
11
+ date: 2021-07-09 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: omniauth
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
- version: '1.0'
19
+ version: 1.9.0
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
- version: '1.0'
26
+ version: 1.9.0
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: omniauth-oauth2
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
- version: '1.0'
33
+ version: 1.6.0
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
- version: '1.0'
40
+ version: 1.6.0
46
41
  description: OmniAuth strategy for Heroku.
47
42
  email:
48
43
  - pedro@heroku.com
@@ -50,35 +45,31 @@ executables: []
50
45
  extensions: []
51
46
  extra_rdoc_files: []
52
47
  files:
53
- - .gitignore
54
- - .rspec
48
+ - LICENSE
55
49
  - README.md
56
- - Rakefile
57
50
  - lib/omniauth-heroku.rb
58
51
  - lib/omniauth/strategies/heroku.rb
59
- - omniauth-heroku.gemspec
60
52
  homepage: https://github.com/heroku/omniauth-heroku
61
- licenses: []
62
- post_install_message:
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
63
57
  rdoc_options: []
64
58
  require_paths:
65
59
  - lib
66
60
  required_ruby_version: !ruby/object:Gem::Requirement
67
- none: false
68
61
  requirements:
69
- - - ! '>='
62
+ - - ">="
70
63
  - !ruby/object:Gem::Version
71
64
  version: '0'
72
65
  required_rubygems_version: !ruby/object:Gem::Requirement
73
- none: false
74
66
  requirements:
75
- - - ! '>='
67
+ - - ">="
76
68
  - !ruby/object:Gem::Version
77
69
  version: '0'
78
70
  requirements: []
79
- rubyforge_project:
80
- rubygems_version: 1.8.24
81
- signing_key:
82
- specification_version: 3
71
+ rubygems_version: 3.2.14
72
+ signing_key:
73
+ specification_version: 4
83
74
  summary: OmniAuth strategy for Heroku.
84
75
  test_files: []
data/.gitignore DELETED
@@ -1,17 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- /pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --colour
data/Rakefile DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
@@ -1,16 +0,0 @@
1
- Gem::Specification.new do |gem|
2
- gem.authors = ["Pedro Belo"]
3
- gem.email = ["pedro@heroku.com"]
4
- gem.description = %q{OmniAuth strategy for Heroku.}
5
- gem.summary = %q{OmniAuth strategy for Heroku.}
6
- gem.homepage = "https://github.com/heroku/omniauth-heroku"
7
-
8
- gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
9
- gem.files = `git ls-files`.split("\n")
10
- gem.name = "omniauth-heroku"
11
- gem.require_paths = ["lib"]
12
- gem.version = "0.1.1"
13
-
14
- gem.add_dependency 'omniauth', '~> 1.0'
15
- gem.add_dependency 'omniauth-oauth2', '~> 1.0'
16
- end