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 +7 -0
- data/LICENSE +22 -0
- data/README.md +132 -9
- data/lib/omniauth/strategies/heroku.rb +79 -4
- metadata +21 -30
- data/.gitignore +0 -17
- data/.rspec +0 -1
- data/Rakefile +0 -2
- data/omniauth-heroku.gemspec +0 -16
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
|
-
[
|
3
|
+
[](https://github.com/heroku/omniauth-heroku/actions)
|
4
4
|
|
5
|
-
|
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
|
25
|
+
provider :heroku, ENV.fetch("HEROKU_OAUTH_ID"), ENV.fetch("HEROKU_OAUTH_SECRET")
|
15
26
|
end
|
16
27
|
```
|
17
28
|
|
18
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
60
|
-
|
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
|
-
|
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
|
-
:
|
10
|
-
:
|
11
|
-
:
|
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.
|
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:
|
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:
|
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:
|
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:
|
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:
|
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
|
-
-
|
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
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
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
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--colour
|
data/Rakefile
DELETED
data/omniauth-heroku.gemspec
DELETED
@@ -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
|