omniauth-heroku 0.1.2.pre → 0.2.0.pre
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 +15 -0
- data/.travis.yml +14 -0
- data/Gemfile +12 -0
- data/README.md +68 -3
- data/Rakefile +8 -0
- data/lib/omniauth/strategies/heroku.rb +53 -5
- data/lib/omniauth-heroku.rb +0 -1
- data/omniauth-heroku.gemspec +3 -3
- data/spec/omniauth_heroku_spec.rb +78 -0
- data/spec/spec_helper.rb +48 -0
- metadata +15 -18
- data/lib/omniauth/strategies/heroku_oauth2.rb +0 -124
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
M2ZlY2IwZjQ5NmNhN2QyMjRhODI0MGE4MmQ5ODFkNzIxZDZiNThlYg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MDEyNDQ1MjUzMThjMzQzYjU4NDFmMjQzNjYxYzBkZDVlOTE0OGU4Mw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MDJkMTc0MTBiNTIzZGU4ZDI4Y2YwYWRkOGEwNDJkNWFlYTczNzJiNzJmODRk
|
10
|
+
YjJjNmNiZTk5NjU0MTNhNWE4ZDcyNTAyZGQwNWJjMGU5NTIzNjI0ZDIwYjVk
|
11
|
+
YmRjODNlZGZlZDY5YjU1OGQ0ZTAzYWMxMTk2NGNlMGM3Njg4MTU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDFiYjc5NzNmMzE0MWZhYWFjYTdlZWE5MDdlM2ViOGU5MDNkNGFiZThjYmQz
|
14
|
+
NTQ1NjczYzg2MDQ1MjMxNzU0OGIzNGNkMDUzMTMyZDI0ZWI0NGViOWFlNzJi
|
15
|
+
YzI2NWNiNTViMTAwYzU1ZDBmMzRiYTE3YTc2MzNlMWYyNTQ4MzE=
|
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.1.2
|
4
|
+
- 2.1.0
|
5
|
+
- 1.9.3
|
6
|
+
cache: bundler
|
7
|
+
notifications:
|
8
|
+
hipchat:
|
9
|
+
rooms:
|
10
|
+
- 5bc7785d2feb4f25901124279daede@API
|
11
|
+
template:
|
12
|
+
- '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message} (<a href="%{build_url}">Details</a> | <a href="%{compare_url}">Change view</a>)'
|
13
|
+
format: html
|
14
|
+
script: bundle exec rake
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# OmniAuth Heroku
|
2
2
|
|
3
|
-
[OmniAuth](https://github.com/intridea/omniauth) strategy for authenticating
|
3
|
+
[OmniAuth](https://github.com/intridea/omniauth) strategy for authenticating Heroku users.
|
4
|
+
|
5
|
+
[](https://travis-ci.org/heroku/omniauth-heroku)
|
6
|
+
|
7
|
+
Mount this with your Rack application (be it Rails or Sinatra) to simplify the [OAuth flow with Heroku](https://devcenter.heroku.com/articles/oauth).
|
8
|
+
|
9
|
+
This is intended for apps already using OmniAuth, for apps that authenticate against more than one service (eg: Heroku and GitHub), or apps that have specific needs on session management. If your app doesn't fall in any of these you should consider using [Heroku Bouncer](https://github.com/heroku/heroku-bouncer) instead.
|
4
10
|
|
5
11
|
|
6
12
|
## Configuration
|
@@ -13,6 +19,8 @@ use OmniAuth::Builder do
|
|
13
19
|
end
|
14
20
|
```
|
15
21
|
|
22
|
+
Obtain a `HEROKU_OAUTH_ID` and `HEROKU_OAUTH_SECRET` by creating a client with the [Heroku OAuth CLI plugin](https://github.com/heroku/heroku-oauth).
|
23
|
+
|
16
24
|
Your Heroku OAuth client should be set to receive callbacks on `/auth/heroku/callback`.
|
17
25
|
|
18
26
|
|
@@ -24,6 +32,63 @@ Once the authorization flow is complete and the user is bounced back to your app
|
|
24
32
|
|
25
33
|
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.
|
26
34
|
|
35
|
+
Refer to the examples below to see how these work.
|
36
|
+
|
37
|
+
|
38
|
+
### Basic account information
|
39
|
+
|
40
|
+
If you want this middleware to fetch additional Heroku account information like the user email address and name, use the `fetch_info` option, like:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
use OmniAuth::Builder do
|
44
|
+
provider :heroku, ENV['HEROKU_OAUTH_ID'], ENV['HEROKU_OAUTH_SECRET'],
|
45
|
+
fetch_info: true
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
This sets name and email in the [omniauth auth hash](https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema). You can access it from your app via `env["omniauth.auth"]["info"]`.
|
50
|
+
|
51
|
+
It will also add [additional Heroku account info](https://devcenter.heroku.com/articles/platform-api-reference#account) to `env["omniauth.auth"]["extra"]`.
|
52
|
+
|
53
|
+
### OAuth scopes
|
54
|
+
|
55
|
+
[Heroku supports different OAuth scopes](https://devcenter.heroku.com/articles/oauth#scopes). By default this strategy will request global access to the account, but you're encouraged to request for less permissions when possible.
|
56
|
+
|
57
|
+
To do so, configure it like:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
use OmniAuth::Builder do
|
61
|
+
provider :heroku, ENV['HEROKU_OAUTH_ID'], ENV['HEROKU_OAUTH_SECRET'],
|
62
|
+
scope: "identity"
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
This will trim down the permissions associated to the access token given back to you.
|
67
|
+
|
68
|
+
|
69
|
+
## Example - Sinatra
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
class Myapp < Sinatra::Application
|
73
|
+
configure do
|
74
|
+
enable :sessions
|
75
|
+
end
|
76
|
+
|
77
|
+
use OmniAuth::Builder do
|
78
|
+
provider :heroku, ENV["HEROKU_OAUTH_ID"], ENV["HEROKU_OAUTH_SECRET"]
|
79
|
+
end
|
80
|
+
|
81
|
+
get "/" do
|
82
|
+
redirect "/auth/heroku"
|
83
|
+
end
|
84
|
+
|
85
|
+
get "/auth/heroku/callback" do
|
86
|
+
access_token = env['omniauth.auth']['credentials']['token']
|
87
|
+
heroku_api = Heroku::API.new(api_key: access_token)
|
88
|
+
"You have #{heroku_api.get_apps.body.size} apps"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
```
|
27
92
|
|
28
93
|
## Example - Rails
|
29
94
|
|
@@ -54,8 +119,8 @@ class SessionsController < ApplicationController
|
|
54
119
|
|
55
120
|
def create
|
56
121
|
access_token = request.env['omniauth.auth']['credentials']['token']
|
57
|
-
heroku_api = Heroku::API.new(:
|
58
|
-
@apps =
|
122
|
+
heroku_api = Heroku::API.new(api_key: access_token)
|
123
|
+
@apps = heroku_api.get_apps.body
|
59
124
|
end
|
60
125
|
end
|
61
126
|
```
|
data/Rakefile
CHANGED
@@ -1,13 +1,61 @@
|
|
1
|
+
require 'omniauth-oauth2'
|
2
|
+
|
1
3
|
module OmniAuth
|
2
4
|
module Strategies
|
3
|
-
class Heroku < OmniAuth::Strategies::
|
4
|
-
|
5
|
+
class Heroku < OmniAuth::Strategies::OAuth2
|
6
|
+
AuthUrl = ENV["HEROKU_AUTH_URL"] || "https://id.heroku.com"
|
7
|
+
ApiUrl = ENV["HEROKU_API_URL"] || "https://api.heroku.com"
|
5
8
|
|
6
9
|
option :client_options, {
|
7
|
-
:
|
8
|
-
:
|
9
|
-
:
|
10
|
+
site: AuthUrl,
|
11
|
+
authorize_url: "#{AuthUrl}/oauth/authorize",
|
12
|
+
token_url: "#{AuthUrl}/oauth/token"
|
10
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
|
+
def account_info
|
48
|
+
@account_info ||= MultiJson.decode(heroku_api.get("/account").body)
|
49
|
+
end
|
50
|
+
|
51
|
+
def heroku_api
|
52
|
+
@heroku_api ||= Faraday.new(
|
53
|
+
url: ApiUrl,
|
54
|
+
headers: {
|
55
|
+
"Accept" => "application/vnd.heroku+json; version=3",
|
56
|
+
"Authorization" => "Bearer #{access_token.token}",
|
57
|
+
})
|
58
|
+
end
|
11
59
|
end
|
12
60
|
end
|
13
61
|
end
|
data/lib/omniauth-heroku.rb
CHANGED
data/omniauth-heroku.gemspec
CHANGED
@@ -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.
|
12
|
+
gem.version = "0.2.0.pre"
|
13
13
|
|
14
|
-
gem.add_dependency '
|
15
|
-
gem.add_dependency 'omniauth', '~> 1.
|
14
|
+
gem.add_dependency 'omniauth', '~> 1.2'
|
15
|
+
gem.add_dependency 'omniauth-oauth2', '~> 1.2'
|
16
16
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe OmniAuth::Strategies::Heroku do
|
4
|
+
before do
|
5
|
+
@token = "6e441b93-4c6d-4613-abed-b9976e7cff6c"
|
6
|
+
@user_id = "ddc4beff-f08f-4856-99d2-ba5ac63c3eb9"
|
7
|
+
|
8
|
+
# stub the API call made by the strategy to start the oauth dance
|
9
|
+
stub_request(:post, "https://id.heroku.com/oauth/token").
|
10
|
+
to_return(
|
11
|
+
headers: { "Content-Type" => "application/json" },
|
12
|
+
body: MultiJson.encode(
|
13
|
+
access_token: @token,
|
14
|
+
expires_in: 3600,
|
15
|
+
user_id: @user_id))
|
16
|
+
end
|
17
|
+
|
18
|
+
it "redirects to start the OAuth flow" do
|
19
|
+
get "/auth/heroku"
|
20
|
+
assert_equal 302, last_response.status
|
21
|
+
redirect = URI.parse(last_response.headers["Location"])
|
22
|
+
redirect_params = CGI::parse(redirect.query)
|
23
|
+
assert_equal "https", redirect.scheme
|
24
|
+
assert_equal "id.heroku.com", redirect.host
|
25
|
+
assert_equal [ENV["HEROKU_OAUTH_ID"]], redirect_params["client_id"]
|
26
|
+
assert_equal ["code"], redirect_params["response_type"]
|
27
|
+
assert_equal ["http://example.org/auth/heroku/callback"],
|
28
|
+
redirect_params["redirect_uri"]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "receives the callback" do
|
32
|
+
# start the callback, get the session state
|
33
|
+
get "/auth/heroku"
|
34
|
+
assert_equal 302, last_response.status
|
35
|
+
state = last_response.headers["Location"].match(/state=([\w\d]+)/)[1]
|
36
|
+
|
37
|
+
# trigger the callback setting the state as a param and in the session
|
38
|
+
get "/auth/heroku/callback", { "state" => state },
|
39
|
+
{ "rack.session" => { "omniauth.state" => state }}
|
40
|
+
assert_equal 200, last_response.status
|
41
|
+
|
42
|
+
omniauth_env = MultiJson.decode(last_response.body)
|
43
|
+
assert_equal "heroku", omniauth_env["provider"]
|
44
|
+
assert_equal @user_id, omniauth_env["uid"]
|
45
|
+
assert_equal "Heroku user", omniauth_env["info"]["name"]
|
46
|
+
end
|
47
|
+
|
48
|
+
it "fetches additional info when requested" do
|
49
|
+
# change the app being tested:
|
50
|
+
@app = make_app(fetch_info: true)
|
51
|
+
|
52
|
+
# stub the API call to heroku
|
53
|
+
account_info = {
|
54
|
+
"email" => "john@example.org",
|
55
|
+
"name" => "John"
|
56
|
+
}
|
57
|
+
stub_request(:get, "https://api.heroku.com/account").
|
58
|
+
with(headers: { "Authorization" => "Bearer #{@token}" }).
|
59
|
+
to_return(body: MultiJson.encode(account_info))
|
60
|
+
|
61
|
+
# do the oauth dance
|
62
|
+
get "/auth/heroku"
|
63
|
+
assert_equal 302, last_response.status
|
64
|
+
state = last_response.headers["Location"].match(/state=([\w\d]+)/)[1]
|
65
|
+
|
66
|
+
get "/auth/heroku/callback", { "state" => state },
|
67
|
+
{ "rack.session" => { "omniauth.state" => state }}
|
68
|
+
assert_equal 200, last_response.status
|
69
|
+
|
70
|
+
# now make sure there's additional info in the omniauth env
|
71
|
+
omniauth_env = MultiJson.decode(last_response.body)
|
72
|
+
assert_equal "heroku", omniauth_env["provider"]
|
73
|
+
assert_equal @user_id, omniauth_env["uid"]
|
74
|
+
assert_equal "john@example.org", omniauth_env["info"]["email"]
|
75
|
+
assert_equal "John", omniauth_env["info"]["name"]
|
76
|
+
assert_equal account_info, omniauth_env["extra"]
|
77
|
+
end
|
78
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
ENV["SESSION_SECRET"] = "abcdefghjij"
|
2
|
+
ENV["HEROKU_OAUTH_ID"] = "12345"
|
3
|
+
ENV["HEROKU_OAUTH_SECRET"] = "klmnopqrstu"
|
4
|
+
|
5
|
+
require "rubygems"
|
6
|
+
require "bundler"
|
7
|
+
Bundler.setup(:default, :test)
|
8
|
+
require "omniauth/strategies/heroku"
|
9
|
+
|
10
|
+
require "cgi"
|
11
|
+
require "rspec"
|
12
|
+
require "rack/test"
|
13
|
+
require "sinatra"
|
14
|
+
require "webmock/rspec"
|
15
|
+
|
16
|
+
Dir["./spec/support/*.rb"].each { |f| require f }
|
17
|
+
|
18
|
+
WebMock.disable_net_connect!
|
19
|
+
|
20
|
+
OmniAuth.config.logger = Logger.new(StringIO.new)
|
21
|
+
|
22
|
+
RSpec.configure do |config|
|
23
|
+
config.include Rack::Test::Methods
|
24
|
+
config.expect_with :minitest
|
25
|
+
|
26
|
+
def app
|
27
|
+
@app || make_app
|
28
|
+
end
|
29
|
+
|
30
|
+
def make_app(omniauth_heroku_options={})
|
31
|
+
Sinatra.new do
|
32
|
+
configure do
|
33
|
+
enable :sessions
|
34
|
+
set :show_exceptions, false
|
35
|
+
set :session_secret, ENV["SESSION_SECRET"]
|
36
|
+
end
|
37
|
+
|
38
|
+
use OmniAuth::Builder do
|
39
|
+
provider :heroku, ENV["HEROKU_OAUTH_ID"], ENV["HEROKU_OAUTH_SECRET"],
|
40
|
+
omniauth_heroku_options
|
41
|
+
end
|
42
|
+
|
43
|
+
get "/auth/heroku/callback" do
|
44
|
+
MultiJson.encode(env['omniauth.auth'])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
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: 6
|
4
|
+
version: 0.2.0.pre
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Pedro Belo
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-09-11 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
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.2'
|
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.2'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
|
-
name: omniauth
|
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.
|
33
|
+
version: '1.2'
|
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.
|
40
|
+
version: '1.2'
|
46
41
|
description: OmniAuth strategy for Heroku.
|
47
42
|
email:
|
48
43
|
- pedro@heroku.com
|
@@ -52,34 +47,36 @@ extra_rdoc_files: []
|
|
52
47
|
files:
|
53
48
|
- .gitignore
|
54
49
|
- .rspec
|
50
|
+
- .travis.yml
|
51
|
+
- Gemfile
|
55
52
|
- README.md
|
56
53
|
- Rakefile
|
57
54
|
- lib/omniauth-heroku.rb
|
58
55
|
- lib/omniauth/strategies/heroku.rb
|
59
|
-
- lib/omniauth/strategies/heroku_oauth2.rb
|
60
56
|
- omniauth-heroku.gemspec
|
57
|
+
- spec/omniauth_heroku_spec.rb
|
58
|
+
- spec/spec_helper.rb
|
61
59
|
homepage: https://github.com/heroku/omniauth-heroku
|
62
60
|
licenses: []
|
61
|
+
metadata: {}
|
63
62
|
post_install_message:
|
64
63
|
rdoc_options: []
|
65
64
|
require_paths:
|
66
65
|
- lib
|
67
66
|
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
-
none: false
|
69
67
|
requirements:
|
70
68
|
- - ! '>='
|
71
69
|
- !ruby/object:Gem::Version
|
72
70
|
version: '0'
|
73
71
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
72
|
requirements:
|
76
73
|
- - ! '>'
|
77
74
|
- !ruby/object:Gem::Version
|
78
75
|
version: 1.3.1
|
79
76
|
requirements: []
|
80
77
|
rubyforge_project:
|
81
|
-
rubygems_version:
|
78
|
+
rubygems_version: 2.0.7
|
82
79
|
signing_key:
|
83
|
-
specification_version:
|
80
|
+
specification_version: 4
|
84
81
|
summary: OmniAuth strategy for Heroku.
|
85
82
|
test_files: []
|
@@ -1,124 +0,0 @@
|
|
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
|