zaikio-oauth_client 0.11.0 → 0.14.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 +42 -25
- data/Rakefile +1 -3
- data/app/controllers/zaikio/oauth_client/subscriptions_controller.rb +1 -2
- data/app/models/zaikio/access_token.rb +2 -2
- data/lib/zaikio/oauth_client.rb +4 -4
- data/lib/zaikio/oauth_client/authenticatable.rb +13 -13
- data/lib/zaikio/oauth_client/client_configuration.rb +1 -1
- data/lib/zaikio/oauth_client/system_test_helper.rb +18 -0
- data/lib/zaikio/oauth_client/test_helper.rb +41 -6
- data/lib/zaikio/oauth_client/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ff245bb6a309f304b580e81ad30acc9a91916919697b2df717fdb884d3e4a25
|
4
|
+
data.tar.gz: c8db756a72615d02de42a58804e23b597f095e709506a6055008a8682cc72bbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45d03fc98118ae5c283139628d0b8b9eaf1dd9a5ddcf22a02f1a57d8052365190907627831992976d8607329e404a021516403000b54ee072fbd9bc155bb9a89
|
7
|
+
data.tar.gz: 6ecae0a7e65289cad9c6691dcdaf3179694db40df26cedefe93cecaf7b16b999617f7931cbbc112116744e418b333c787b4b5e426baf6f6db0591ff6a399e6e7
|
data/README.md
CHANGED
@@ -36,32 +36,34 @@ mount Zaikio::OAuthClient::Engine => "/zaikio"
|
|
36
36
|
|
37
37
|
```rb
|
38
38
|
# config/initializers/zaikio_oauth_client.rb
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
39
|
+
Rails.application.reloader.to_prepare do
|
40
|
+
Zaikio::OAuthClient.configure do |config|
|
41
|
+
config.environment = :sandbox
|
42
|
+
|
43
|
+
config.register_client :warehouse do |warehouse|
|
44
|
+
warehouse.client_id = "52022d7a-7ba2-41ed-8890-97d88e6472f6"
|
45
|
+
warehouse.client_secret = "ShiKTnHqEf3M8nyHQPyZgbz7"
|
46
|
+
warehouse.default_scopes = %w[directory.person.r]
|
47
|
+
|
48
|
+
warehouse.register_organization_connection do |org|
|
49
|
+
org.default_scopes = %w[directory.organization.r]
|
50
|
+
end
|
49
51
|
end
|
50
|
-
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
config.register_client :warehouse_goods_call_of do |warehouse_goods_call_of|
|
54
|
+
warehouse_goods_call_of.client_id = "12345-7ba2-41ed-8890-97d88e6472f6"
|
55
|
+
warehouse_goods_call_of.client_secret = "secret"
|
56
|
+
warehouse_goods_call_of.default_scopes = %w[directory.person.r]
|
56
57
|
|
57
|
-
|
58
|
-
|
58
|
+
warehouse_goods_call_of.register_organization_connection do |org|
|
59
|
+
org.default_scopes = %w[directory.organization.r]
|
60
|
+
end
|
59
61
|
end
|
60
|
-
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
config.around_auth do |access_token, block|
|
64
|
+
Zaikio::Hub.with_token(access_token.token) do
|
65
|
+
block.call(access_token)
|
66
|
+
end
|
65
67
|
end
|
66
68
|
end
|
67
69
|
end
|
@@ -133,12 +135,12 @@ redirect_to zaikio_oauth_client.new_subscription_path(plan: "free")
|
|
133
135
|
|
134
136
|
#### Session handling
|
135
137
|
|
136
|
-
The Zaikio gem engine will set a cookie for the user after a successful OAuth flow: `
|
138
|
+
The Zaikio gem engine will set a cookie for the user after a successful OAuth flow: `session[:zaikio_person_id]`.
|
137
139
|
|
138
140
|
If you are using for example `Zaikio::Hub::Models`, you can use this snippet to set the current user:
|
139
141
|
|
140
142
|
```ruby
|
141
|
-
Current.user ||= Zaikio::Hub::Models::Person.find_by(id:
|
143
|
+
Current.user ||= Zaikio::Hub::Models::Person.find_by(id: session[:zaikio_person_id])
|
142
144
|
````
|
143
145
|
|
144
146
|
You can then use `Current.user` anywhere.
|
@@ -172,7 +174,7 @@ Additionally you can also specify your own redirect handlers in your `Applicatio
|
|
172
174
|
```rb
|
173
175
|
class ApplicationController < ActionController::Base
|
174
176
|
def after_approve_path_for(access_token, origin)
|
175
|
-
|
177
|
+
session[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
|
176
178
|
|
177
179
|
# Sync data on login
|
178
180
|
Zaikio::Hub.with_token(access_token.token) do
|
@@ -183,7 +185,7 @@ class ApplicationController < ActionController::Base
|
|
183
185
|
end
|
184
186
|
|
185
187
|
def after_destroy_path_for(access_token_id)
|
186
|
-
|
188
|
+
reset_session
|
187
189
|
|
188
190
|
main_app.root_path
|
189
191
|
end
|
@@ -239,6 +241,21 @@ class MyControllerTest < ActionDispatch::IntegrationTest
|
|
239
241
|
end
|
240
242
|
```
|
241
243
|
|
244
|
+
For system tests (e.g. with a separate browser instance), there's a special helper:
|
245
|
+
|
246
|
+
```rb
|
247
|
+
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
248
|
+
include Zaikio::OAuthClient::SystemTestHelper
|
249
|
+
|
250
|
+
test "does request" do
|
251
|
+
person = people(:my_person)
|
252
|
+
logged_in_as(person)
|
253
|
+
|
254
|
+
visit "/"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
```
|
258
|
+
|
242
259
|
#### Authenticated requests
|
243
260
|
|
244
261
|
Now further requests to the Directory API or to other Zaikio APIs should be made. For this purpose the OAuthClient provides a helper method `with_auth` that automatically fetches an access token from the database, requests a refresh token or creates a new access token via client credentials flow.
|
data/Rakefile
CHANGED
@@ -35,9 +35,7 @@ require 'rubocop/rake_task'
|
|
35
35
|
|
36
36
|
namespace :test do
|
37
37
|
desc 'Runs RuboCop on specified directories'
|
38
|
-
RuboCop::RakeTask.new(:rubocop)
|
39
|
-
task.fail_on_error = false
|
40
|
-
end
|
38
|
+
RuboCop::RakeTask.new(:rubocop)
|
41
39
|
end
|
42
40
|
|
43
41
|
Rake::Task[:test].enhance ['test:rubocop']
|
@@ -3,8 +3,7 @@ module Zaikio
|
|
3
3
|
class SubscriptionsController < ConnectionsController
|
4
4
|
def new
|
5
5
|
opts = params.permit(:client_name, :state, :plan, :organization_id)
|
6
|
-
opts[:
|
7
|
-
opts[:state] ||= cookies.encrypted[:state] = SecureRandom.urlsafe_base64(32)
|
6
|
+
opts[:state] ||= session[:state] = SecureRandom.urlsafe_base64(32)
|
8
7
|
|
9
8
|
plan = opts.delete(:plan)
|
10
9
|
organization_id = opts.delete(:organization_id)
|
@@ -5,7 +5,7 @@ module Zaikio
|
|
5
5
|
class AccessToken < ApplicationRecord
|
6
6
|
self.table_name = "zaikio_access_tokens"
|
7
7
|
|
8
|
-
def self.build_from_access_token(access_token, requested_scopes: nil)
|
8
|
+
def self.build_from_access_token(access_token, requested_scopes: nil)
|
9
9
|
payload = JWT.decode(access_token.token, nil, false).first rescue {} # rubocop:disable Style/RescueModifier
|
10
10
|
scopes = access_token.params["scope"].split(",")
|
11
11
|
new(
|
@@ -37,7 +37,7 @@ module Zaikio
|
|
37
37
|
where("expires_at <= :now AND created_at > :created_at_max",
|
38
38
|
now: Time.current,
|
39
39
|
created_at_max: Time.current - refresh_token_valid_for)
|
40
|
-
.where(
|
40
|
+
.where.not(refresh_token: nil)
|
41
41
|
.where.not(id: Zaikio::JWTAuth.revoked_token_ids)
|
42
42
|
}
|
43
43
|
scope :by_bearer, lambda { |bearer_id:, requested_scopes: [], bearer_type: "Person"|
|
data/lib/zaikio/oauth_client.rb
CHANGED
@@ -49,7 +49,7 @@ module Zaikio
|
|
49
49
|
get_access_token(**options_or_access_token)
|
50
50
|
end
|
51
51
|
|
52
|
-
return unless
|
52
|
+
return unless block
|
53
53
|
|
54
54
|
if configuration.around_auth_block
|
55
55
|
configuration.around_auth_block.call(access_token, block)
|
@@ -82,7 +82,7 @@ module Zaikio
|
|
82
82
|
|
83
83
|
# Finds the best usable access token. Note that this token may have expired and
|
84
84
|
# would require refreshing.
|
85
|
-
def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:)
|
85
|
+
def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:) # rubocop:disable Metrics/MethodLength
|
86
86
|
configuration.logger.debug "Try to fetch token for client_name: #{client_name}, "\
|
87
87
|
"bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
|
88
88
|
|
@@ -117,9 +117,9 @@ module Zaikio
|
|
117
117
|
|
118
118
|
def get_plain_scopes(scopes)
|
119
119
|
regex = /^((Org|Per)\.)?(.*)$/
|
120
|
-
scopes.
|
120
|
+
scopes.filter_map do |scope|
|
121
121
|
(regex.match(scope) || [])[3]
|
122
|
-
end
|
122
|
+
end
|
123
123
|
end
|
124
124
|
|
125
125
|
private
|
@@ -4,10 +4,10 @@ module Zaikio
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
def new
|
7
|
-
opts = params.permit(:client_name, :show_signup, :force_login, :state)
|
8
|
-
opts[:
|
7
|
+
opts = params.permit(:client_name, :show_signup, :prompt, :force_login, :state, :lang)
|
8
|
+
opts[:lang] ||= I18n.locale if defined?(I18n)
|
9
9
|
client_name = opts.delete(:client_name)
|
10
|
-
opts[:state] ||=
|
10
|
+
opts[:state] ||= session[:state] = SecureRandom.urlsafe_base64(32)
|
11
11
|
|
12
12
|
redirect_to oauth_client.auth_code.authorize_url(
|
13
13
|
redirect_uri: approve_url(client_name),
|
@@ -16,7 +16,7 @@ module Zaikio
|
|
16
16
|
)
|
17
17
|
end
|
18
18
|
|
19
|
-
def approve
|
19
|
+
def approve # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
20
20
|
if params[:error].present?
|
21
21
|
redirect_to send(
|
22
22
|
respond_to?(:error_path_for) ? :error_path_for : :default_error_path_for,
|
@@ -25,7 +25,7 @@ module Zaikio
|
|
25
25
|
) and return
|
26
26
|
end
|
27
27
|
|
28
|
-
if
|
28
|
+
if session[:state].present? && params[:state] != session[:state]
|
29
29
|
return redirect_to send(
|
30
30
|
respond_to?(:error_path_for) ? :error_path_for : :default_error_path_for,
|
31
31
|
"invalid_state"
|
@@ -34,10 +34,10 @@ module Zaikio
|
|
34
34
|
|
35
35
|
access_token = create_access_token
|
36
36
|
|
37
|
-
origin =
|
38
|
-
|
37
|
+
origin = session[:origin]
|
38
|
+
session.delete(:origin)
|
39
39
|
|
40
|
-
|
40
|
+
session[:zaikio_access_token_id] = access_token.id unless access_token.organization?
|
41
41
|
|
42
42
|
redirect_to send(
|
43
43
|
respond_to?(:after_approve_path_for) ? :after_approve_path_for : :default_after_approve_path_for,
|
@@ -46,9 +46,9 @@ module Zaikio
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def destroy
|
49
|
-
access_token_id =
|
50
|
-
|
51
|
-
|
49
|
+
access_token_id = session[:zaikio_access_token_id]
|
50
|
+
session.delete(:zaikio_access_token_id)
|
51
|
+
session.delete(:origin)
|
52
52
|
|
53
53
|
redirect_to send(
|
54
54
|
respond_to?(:after_destroy_path_for) ? :after_destroy_path_for : :default_after_destroy_path_for,
|
@@ -95,13 +95,13 @@ module Zaikio
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def default_after_approve_path_for(access_token, origin)
|
98
|
-
|
98
|
+
session[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
|
99
99
|
|
100
100
|
origin || main_app.root_path
|
101
101
|
end
|
102
102
|
|
103
103
|
def default_after_destroy_path_for(_access_token_id)
|
104
|
-
|
104
|
+
session.delete(:origin)
|
105
105
|
|
106
106
|
main_app.root_path
|
107
107
|
end
|
@@ -20,7 +20,7 @@ module Zaikio
|
|
20
20
|
client_secret,
|
21
21
|
authorize_url: "oauth/authorize",
|
22
22
|
token_url: "oauth/access_token",
|
23
|
-
connection_opts: { headers: {
|
23
|
+
connection_opts: { headers: { Accept: "application/json" } },
|
24
24
|
site: Zaikio::OAuthClient.configuration.host
|
25
25
|
)
|
26
26
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "./test_helper"
|
2
|
+
|
3
|
+
module Zaikio
|
4
|
+
module OAuthClient
|
5
|
+
module SystemTestHelper
|
6
|
+
include ::Zaikio::OAuthClient::TestHelper
|
7
|
+
|
8
|
+
def set_session(key, value)
|
9
|
+
visit "/zaikio/oauth_client/test_helper/session?#{{ key: key, id: value }.to_query}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_session(key)
|
13
|
+
visit "/zaikio/oauth_client/test_helper/get_session?#{{ key: key }.to_query}"
|
14
|
+
page.text
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -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 # rubocop:disable Rails/ApplicationController
|
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.14.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-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -86,20 +86,20 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.
|
89
|
+
version: '0.5'
|
90
90
|
- - "<"
|
91
91
|
- !ruby/object:Gem::Version
|
92
|
-
version:
|
92
|
+
version: '2.0'
|
93
93
|
type: :runtime
|
94
94
|
prerelease: false
|
95
95
|
version_requirements: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
97
|
- - ">="
|
98
98
|
- !ruby/object:Gem::Version
|
99
|
-
version: 0.
|
99
|
+
version: '0.5'
|
100
100
|
- - "<"
|
101
101
|
- !ruby/object:Gem::Version
|
102
|
-
version:
|
102
|
+
version: '2.0'
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
104
|
name: pg
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,13 +164,14 @@ files:
|
|
164
164
|
- lib/zaikio/oauth_client/configuration.rb
|
165
165
|
- lib/zaikio/oauth_client/engine.rb
|
166
166
|
- lib/zaikio/oauth_client/error.rb
|
167
|
+
- lib/zaikio/oauth_client/system_test_helper.rb
|
167
168
|
- lib/zaikio/oauth_client/test_helper.rb
|
168
169
|
- lib/zaikio/oauth_client/version.rb
|
169
170
|
homepage: https://github.com/zaikio/zaikio-oauth_client
|
170
171
|
licenses:
|
171
172
|
- MIT
|
172
173
|
metadata:
|
173
|
-
changelog_uri: https://github.com/zaikio/zaikio-oauth_client/blob/
|
174
|
+
changelog_uri: https://github.com/zaikio/zaikio-oauth_client/blob/main/CHANGELOG.md
|
174
175
|
post_install_message:
|
175
176
|
rdoc_options: []
|
176
177
|
require_paths:
|