zaikio-oauth_client 0.8.1 → 0.12.0
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 +4 -4
- data/README.md +23 -5
- data/app/controllers/zaikio/oauth_client/subscriptions_controller.rb +28 -0
- data/config/locales/de.yml +4 -0
- data/config/locales/en.yml +2 -1
- data/config/routes.rb +13 -11
- data/lib/zaikio/oauth_client.rb +20 -8
- data/lib/zaikio/oauth_client/authenticatable.rb +35 -7
- data/lib/zaikio/oauth_client/configuration.rb +13 -3
- data/lib/zaikio/oauth_client/error.rb +5 -0
- data/lib/zaikio/oauth_client/test_helper.rb +41 -6
- data/lib/zaikio/oauth_client/version.rb +1 -1
- metadata +10 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e007c62cd36b1b00aa8e542958bb5d627b5ca417ffc6559f45de3868e79149a
|
4
|
+
data.tar.gz: 9977c82c5f734d93b05269a7e9fb30e6fe6df1b15a291d680a48fa38bea079a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eeb3f43dc40d4cabeb1f585864ff76c716243e6d0336164b0e3b98c7e2e41bdbd25ffdeaeeeb4b7ee1ccefe20cf1f458bd0af62e1cb2238af3ad258ad6cf4804
|
7
|
+
data.tar.gz: e3b47a58b780c92ed0b8a9c5ae0df7011026feed340204e8deb80a88ca2562b4a220cd59c8d5907982488001b6738d5c0eb0ba2495771c0de2a0310f44de42bd
|
data/README.md
CHANGED
@@ -118,14 +118,27 @@ redirect_to zaikio_oauth_client.new_session_path(force_login: true)
|
|
118
118
|
redirect_to zaikio_oauth_client.new_session_path(state: "something-my-app-uses")
|
119
119
|
```
|
120
120
|
|
121
|
+
You can also send them to the [Subscription Redirect
|
122
|
+
flow](https://docs.zaikio.com/api/directory/guides/subscriptions/redirect-flow/), which
|
123
|
+
behaves & redirects back like a regular Organization flow except it additionally sets up a
|
124
|
+
subscription for the organization:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
# Require them to select a plan themselves...
|
128
|
+
redirect_to zaikio_oauth_client.new_subscription_path
|
129
|
+
|
130
|
+
# Or preselect a plan for them
|
131
|
+
redirect_to zaikio_oauth_client.new_subscription_path(plan: "free")
|
132
|
+
```
|
133
|
+
|
121
134
|
#### Session handling
|
122
135
|
|
123
|
-
The Zaikio gem engine will set a cookie for the user after a successful OAuth flow: `
|
136
|
+
The Zaikio gem engine will set a cookie for the user after a successful OAuth flow: `session[:zaikio_person_id]`.
|
124
137
|
|
125
138
|
If you are using for example `Zaikio::Hub::Models`, you can use this snippet to set the current user:
|
126
139
|
|
127
140
|
```ruby
|
128
|
-
Current.user ||= Zaikio::Hub::Models::Person.find_by(id:
|
141
|
+
Current.user ||= Zaikio::Hub::Models::Person.find_by(id: session[:zaikio_person_id])
|
129
142
|
````
|
130
143
|
|
131
144
|
You can then use `Current.user` anywhere.
|
@@ -159,7 +172,7 @@ Additionally you can also specify your own redirect handlers in your `Applicatio
|
|
159
172
|
```rb
|
160
173
|
class ApplicationController < ActionController::Base
|
161
174
|
def after_approve_path_for(access_token, origin)
|
162
|
-
|
175
|
+
session[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
|
163
176
|
|
164
177
|
# Sync data on login
|
165
178
|
Zaikio::Hub.with_token(access_token.token) do
|
@@ -170,8 +183,13 @@ class ApplicationController < ActionController::Base
|
|
170
183
|
end
|
171
184
|
|
172
185
|
def after_destroy_path_for(access_token_id)
|
173
|
-
|
186
|
+
reset_session
|
187
|
+
|
188
|
+
main_app.root_path
|
189
|
+
end
|
174
190
|
|
191
|
+
def error_path_for(error_code, description: nil)
|
192
|
+
# Handle error
|
175
193
|
main_app.root_path
|
176
194
|
end
|
177
195
|
end
|
@@ -254,7 +272,7 @@ To release a new version of the gem:
|
|
254
272
|
- Update the version in `lib/zaikio/oauth_client/version.rb`
|
255
273
|
- Update `CHANGELOG.md` to include the new version and its release date
|
256
274
|
- Commit and push your changes
|
257
|
-
- Create a [new release on GitHub](https://github.com/zaikio/zaikio-
|
275
|
+
- Create a [new release on GitHub](https://github.com/zaikio/zaikio-oauth_client/releases/new)
|
258
276
|
- CircleCI will build the Gem package and push it Rubygems for you
|
259
277
|
|
260
278
|
## License
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Zaikio
|
2
|
+
module OAuthClient
|
3
|
+
class SubscriptionsController < ConnectionsController
|
4
|
+
def new
|
5
|
+
opts = params.permit(:client_name, :state, :plan, :organization_id)
|
6
|
+
opts[:redirect_with_error] = 1
|
7
|
+
opts[:state] ||= session[:state] = SecureRandom.urlsafe_base64(32)
|
8
|
+
|
9
|
+
plan = opts.delete(:plan)
|
10
|
+
organization_id = opts.delete(:organization_id)
|
11
|
+
|
12
|
+
subscription_scope = if organization_id.present?
|
13
|
+
"Org/#{organization_id}.subscription_create"
|
14
|
+
else
|
15
|
+
"Org.subscription_create"
|
16
|
+
end
|
17
|
+
|
18
|
+
subscription_scope << ".#{plan}" if plan.present?
|
19
|
+
|
20
|
+
redirect_to oauth_client.auth_code.authorize_url(
|
21
|
+
redirect_uri: approve_url(opts.delete(:client_name)),
|
22
|
+
scope: subscription_scope,
|
23
|
+
**opts
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/config/locales/en.yml
CHANGED
data/config/routes.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
Zaikio::OAuthClient::Engine.routes.draw do
|
2
|
-
|
3
|
-
connections_controller = Zaikio::OAuthClient.configuration.connections_controller_name
|
2
|
+
config = Zaikio::OAuthClient.configuration
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
scope path: "(/:client_name)" do
|
5
|
+
# People
|
6
|
+
get "/sessions/new", action: :new, controller: config.sessions_controller_name, as: :new_session
|
7
|
+
get "/sessions/approve", action: :approve, controller: config.sessions_controller_name, as: :approve_session
|
8
|
+
delete "/session", action: :destroy, controller: config.sessions_controller_name, as: :session
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
# Organizations
|
11
|
+
get "/connections/new", action: :new, controller: config.connections_controller_name, as: :new_connection
|
12
|
+
get "/connections/approve", action: :approve, controller: config.connections_controller_name, as: :approve_connection
|
13
|
+
|
14
|
+
# Subscriptions
|
15
|
+
get "/subscriptions/new", action: :new, controller: config.subscriptions_controller_name, as: :new_subscription
|
16
|
+
end
|
15
17
|
end
|
data/lib/zaikio/oauth_client.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "oauth2"
|
2
2
|
|
3
|
+
require "zaikio/oauth_client/error"
|
3
4
|
require "zaikio/oauth_client/engine"
|
4
5
|
require "zaikio/oauth_client/configuration"
|
5
6
|
require "zaikio/oauth_client/authenticatable"
|
@@ -82,14 +83,25 @@ module Zaikio
|
|
82
83
|
# Finds the best usable access token. Note that this token may have expired and
|
83
84
|
# would require refreshing.
|
84
85
|
def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
86
|
+
configuration.logger.debug "Try to fetch token for client_name: #{client_name}, "\
|
87
|
+
"bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
|
88
|
+
|
89
|
+
fetch_access_token = lambda {
|
90
|
+
Zaikio::AccessToken
|
91
|
+
.where(audience: client_name)
|
92
|
+
.usable(
|
93
|
+
bearer_type: bearer_type,
|
94
|
+
bearer_id: bearer_id,
|
95
|
+
requested_scopes: requested_scopes
|
96
|
+
)
|
97
|
+
.first
|
98
|
+
}
|
99
|
+
|
100
|
+
if configuration.logger.respond_to?(:silence)
|
101
|
+
configuration.logger.silence { fetch_access_token.call }
|
102
|
+
else
|
103
|
+
fetch_access_token.call
|
104
|
+
end
|
93
105
|
end
|
94
106
|
|
95
107
|
def fetch_new_token(client_config:, bearer_type:, bearer_id:, scopes:)
|
@@ -5,7 +5,9 @@ module Zaikio
|
|
5
5
|
|
6
6
|
def new
|
7
7
|
opts = params.permit(:client_name, :show_signup, :force_login, :state)
|
8
|
+
opts[:redirect_with_error] = 1
|
8
9
|
client_name = opts.delete(:client_name)
|
10
|
+
opts[:state] ||= session[:state] = SecureRandom.urlsafe_base64(32)
|
9
11
|
|
10
12
|
redirect_to oauth_client.auth_code.authorize_url(
|
11
13
|
redirect_uri: approve_url(client_name),
|
@@ -15,12 +17,27 @@ module Zaikio
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def approve
|
20
|
+
if params[:error].present?
|
21
|
+
redirect_to send(
|
22
|
+
respond_to?(:error_path_for) ? :error_path_for : :default_error_path_for,
|
23
|
+
params[:error],
|
24
|
+
description: params[:error_description]
|
25
|
+
) and return
|
26
|
+
end
|
27
|
+
|
28
|
+
if session[:state].present? && params[:state] != session[:state]
|
29
|
+
return redirect_to send(
|
30
|
+
respond_to?(:error_path_for) ? :error_path_for : :default_error_path_for,
|
31
|
+
"invalid_state"
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
18
35
|
access_token = create_access_token
|
19
36
|
|
20
|
-
origin =
|
21
|
-
|
37
|
+
origin = session[:origin]
|
38
|
+
session.delete(:origin)
|
22
39
|
|
23
|
-
|
40
|
+
session[:zaikio_access_token_id] = access_token.id unless access_token.organization?
|
24
41
|
|
25
42
|
redirect_to send(
|
26
43
|
respond_to?(:after_approve_path_for) ? :after_approve_path_for : :default_after_approve_path_for,
|
@@ -29,8 +46,9 @@ module Zaikio
|
|
29
46
|
end
|
30
47
|
|
31
48
|
def destroy
|
32
|
-
access_token_id =
|
33
|
-
|
49
|
+
access_token_id = session[:zaikio_access_token_id]
|
50
|
+
session.delete(:zaikio_access_token_id)
|
51
|
+
session.delete(:origin)
|
34
52
|
|
35
53
|
redirect_to send(
|
36
54
|
respond_to?(:after_destroy_path_for) ? :after_destroy_path_for : :default_after_destroy_path_for,
|
@@ -77,13 +95,23 @@ module Zaikio
|
|
77
95
|
end
|
78
96
|
|
79
97
|
def default_after_approve_path_for(access_token, origin)
|
80
|
-
|
98
|
+
session[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
|
81
99
|
|
82
100
|
origin || main_app.root_path
|
83
101
|
end
|
84
102
|
|
85
103
|
def default_after_destroy_path_for(_access_token_id)
|
86
|
-
|
104
|
+
session.delete(:origin)
|
105
|
+
|
106
|
+
main_app.root_path
|
107
|
+
end
|
108
|
+
|
109
|
+
def default_error_path_for(error_code, description: nil)
|
110
|
+
raise Zaikio::OAuthClient::InvalidScopesError, description if error_code == "invalid_scope"
|
111
|
+
|
112
|
+
unless error_code == "access_denied"
|
113
|
+
flash[:alert] = I18n.t("zaikio.oauth_client.error_occured", error: error_code, description: description)
|
114
|
+
end
|
87
115
|
|
88
116
|
main_app.root_path
|
89
117
|
end
|
@@ -13,19 +13,25 @@ module Zaikio
|
|
13
13
|
}.freeze
|
14
14
|
|
15
15
|
attr_accessor :host
|
16
|
-
attr_writer :logger
|
17
16
|
attr_reader :client_configurations, :environment, :around_auth_block,
|
18
|
-
:sessions_controller_name, :connections_controller_name
|
17
|
+
:sessions_controller_name, :connections_controller_name, :subscriptions_controller_name
|
19
18
|
|
20
19
|
def initialize
|
21
20
|
@client_configurations = {}
|
22
21
|
@around_auth_block = nil
|
23
22
|
@sessions_controller_name = "sessions"
|
24
23
|
@connections_controller_name = "connections"
|
24
|
+
@subscriptions_controller_name = "subscriptions"
|
25
|
+
Zaikio::AccessToken.logger = logger
|
25
26
|
end
|
26
27
|
|
27
28
|
def logger
|
28
|
-
@logger ||= Logger.new($stdout)
|
29
|
+
@logger ||= ActiveSupport::Logger.new($stdout)
|
30
|
+
end
|
31
|
+
|
32
|
+
def logger=(logger)
|
33
|
+
@logger = logger
|
34
|
+
Zaikio::AccessToken.logger = @logger
|
29
35
|
end
|
30
36
|
|
31
37
|
def register_client(name)
|
@@ -58,6 +64,10 @@ module Zaikio
|
|
58
64
|
@connections_controller_name = "/#{name}"
|
59
65
|
end
|
60
66
|
|
67
|
+
def subscriptions_controller_name=(name)
|
68
|
+
@subscriptions_controller_name = "/#{name}"
|
69
|
+
end
|
70
|
+
|
61
71
|
private
|
62
72
|
|
63
73
|
def host_for(environment)
|
@@ -3,13 +3,48 @@ module Zaikio
|
|
3
3
|
module TestHelper
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
class TestSessionController < ActionController::Base
|
7
|
+
def show
|
8
|
+
if session[params[:key]].nil?
|
9
|
+
head :no_content
|
10
|
+
else
|
11
|
+
render plain: session[params[:key]]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
session[params[:key]] = params[:id]
|
17
|
+
|
18
|
+
head :ok
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
included do
|
23
|
+
# This is needed as it is not possible to set sesison values in an ActionDispatch::IntegrationTest
|
24
|
+
# This creates a dummy controller to set the session
|
25
|
+
Rails.application.routes.disable_clear_and_finalize = true # Keep existing routes
|
26
|
+
Rails.application.routes.draw do
|
27
|
+
get "/zaikio/oauth_client/test_helper/get_session", to: "zaikio/oauth_client/test_helper/test_session#show"
|
28
|
+
get "/zaikio/oauth_client/test_helper/session", to: "zaikio/oauth_client/test_helper/test_session#create"
|
29
|
+
end
|
30
|
+
end
|
11
31
|
|
12
|
-
|
32
|
+
def get_session(key)
|
33
|
+
get "/zaikio/oauth_client/test_helper/get_session", params: { key: key }
|
34
|
+
|
35
|
+
if response.status == 204
|
36
|
+
nil
|
37
|
+
else
|
38
|
+
response.body
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_session(key, value)
|
43
|
+
get "/zaikio/oauth_client/test_helper/session", params: { id: value, key: key }
|
44
|
+
end
|
45
|
+
|
46
|
+
def logged_in_as(person)
|
47
|
+
set_session(:zaikio_person_id, person.id)
|
13
48
|
end
|
14
49
|
end
|
15
50
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zaikio-oauth_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zaikio GmbH
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -84,22 +84,16 @@ dependencies:
|
|
84
84
|
name: zaikio-jwt_auth
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: 0.2.1
|
90
|
-
- - "<"
|
87
|
+
- - "~>"
|
91
88
|
- !ruby/object:Gem::Version
|
92
|
-
version: 0.5
|
89
|
+
version: '0.5'
|
93
90
|
type: :runtime
|
94
91
|
prerelease: false
|
95
92
|
version_requirements: !ruby/object:Gem::Requirement
|
96
93
|
requirements:
|
97
|
-
- - "
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
version: 0.2.1
|
100
|
-
- - "<"
|
94
|
+
- - "~>"
|
101
95
|
- !ruby/object:Gem::Version
|
102
|
-
version: 0.5
|
96
|
+
version: '0.5'
|
103
97
|
- !ruby/object:Gem::Dependency
|
104
98
|
name: pg
|
105
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -144,11 +138,13 @@ files:
|
|
144
138
|
- Rakefile
|
145
139
|
- app/controllers/zaikio/oauth_client/connections_controller.rb
|
146
140
|
- app/controllers/zaikio/oauth_client/sessions_controller.rb
|
141
|
+
- app/controllers/zaikio/oauth_client/subscriptions_controller.rb
|
147
142
|
- app/helpers/zaikio/application_helper.rb
|
148
143
|
- app/jobs/zaikio/application_job.rb
|
149
144
|
- app/jobs/zaikio/cleanup_access_tokens_job.rb
|
150
145
|
- app/models/zaikio/access_token.rb
|
151
146
|
- config/initializers/inflections.rb
|
147
|
+
- config/locales/de.yml
|
152
148
|
- config/locales/en.yml
|
153
149
|
- config/routes.rb
|
154
150
|
- db/migrate/20190426155505_enable_postgres_extensions_for_uuids.rb
|
@@ -161,13 +157,14 @@ files:
|
|
161
157
|
- lib/zaikio/oauth_client/client_configuration.rb
|
162
158
|
- lib/zaikio/oauth_client/configuration.rb
|
163
159
|
- lib/zaikio/oauth_client/engine.rb
|
160
|
+
- lib/zaikio/oauth_client/error.rb
|
164
161
|
- lib/zaikio/oauth_client/test_helper.rb
|
165
162
|
- lib/zaikio/oauth_client/version.rb
|
166
163
|
homepage: https://github.com/zaikio/zaikio-oauth_client
|
167
164
|
licenses:
|
168
165
|
- MIT
|
169
166
|
metadata:
|
170
|
-
changelog_uri: https://github.com/zaikio/zaikio-oauth_client/blob/
|
167
|
+
changelog_uri: https://github.com/zaikio/zaikio-oauth_client/blob/main/CHANGELOG.md
|
171
168
|
post_install_message:
|
172
169
|
rdoc_options: []
|
173
170
|
require_paths:
|