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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3caeb6fd8b46df684ae2ead61a41965d33d0c8447576ca3dd4472e035917732
4
- data.tar.gz: 7efeeb1977f82515ac60e41dfeec76a2e03867cead09e4e7bdee225f9e2d7051
3
+ metadata.gz: 0ff245bb6a309f304b580e81ad30acc9a91916919697b2df717fdb884d3e4a25
4
+ data.tar.gz: c8db756a72615d02de42a58804e23b597f095e709506a6055008a8682cc72bbd
5
5
  SHA512:
6
- metadata.gz: 49c66d7cee9b78180b46f5f75318e9cdab0e0ea04cf7bf349c09990ac337dc367e32fcf15f70a3728fa524a53ea3a5771e0c436b9902d4f7a023ad72a0b21adb
7
- data.tar.gz: b82883c6b3b85dabe9759266bd5c5f4b338bb9917c3bd60696412e4651a23c45e73e296a600258aa7072ad5c417dd728742afecdba8a5f14b66a673ff836e0f4
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
- Zaikio::OAuthClient.configure do |config|
40
- config.environment = :sandbox
41
-
42
- config.register_client :warehouse do |warehouse|
43
- warehouse.client_id = "52022d7a-7ba2-41ed-8890-97d88e6472f6"
44
- warehouse.client_secret = "ShiKTnHqEf3M8nyHQPyZgbz7"
45
- warehouse.default_scopes = %w[directory.person.r]
46
-
47
- warehouse.register_organization_connection do |org|
48
- org.default_scopes = %w[directory.organization.r]
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
- config.register_client :warehouse_goods_call_of do |warehouse_goods_call_of|
53
- warehouse_goods_call_of.client_id = "12345-7ba2-41ed-8890-97d88e6472f6"
54
- warehouse_goods_call_of.client_secret = "secret"
55
- warehouse_goods_call_of.default_scopes = %w[directory.person.r]
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
- warehouse_goods_call_of.register_organization_connection do |org|
58
- org.default_scopes = %w[directory.organization.r]
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
- config.around_auth do |access_token, block|
63
- Zaikio::Hub.with_token(access_token.token) do
64
- block.call(access_token)
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: `cookies.encrypted[:zaikio_person_id]`.
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: cookies.encrypted[:zaikio_person_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
- cookies.encrypted[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
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
- cookies.delete :zaikio_person_id
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) do |task|
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[:redirect_with_error] = 1
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) # rubocop:disable Metrics/AbcSize
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("refresh_token IS NOT NULL")
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"|
@@ -49,7 +49,7 @@ module Zaikio
49
49
  get_access_token(**options_or_access_token)
50
50
  end
51
51
 
52
- return unless block_given?
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.map do |scope|
120
+ scopes.filter_map do |scope|
121
121
  (regex.match(scope) || [])[3]
122
- end.compact
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[:redirect_with_error] = 1
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] ||= cookies.encrypted[:state] = SecureRandom.urlsafe_base64(32)
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 cookies.encrypted[:state].present? && params[:state] != cookies.encrypted[:state]
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 = cookies.encrypted[:origin]
38
- cookies.delete :origin
37
+ origin = session[:origin]
38
+ session.delete(:origin)
39
39
 
40
- cookies.encrypted[:zaikio_access_token_id] = access_token.id unless access_token.organization?
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 = cookies.encrypted[:zaikio_access_token_id]
50
- cookies.delete :zaikio_access_token_id
51
- cookies.delete :state
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
- cookies.encrypted[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
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
- cookies.delete :zaikio_person_id
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: { "Accept": "application/json" } },
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
- def logged_in_as(person)
7
- # We need to manually encrypt the value since the tests cookie jar does not
8
- # support encrypted or signed cookies
9
- encrypted_cookies = ActionDispatch::Request.new(Rails.application.env_config.deep_dup).cookie_jar
10
- encrypted_cookies.encrypted[:zaikio_person_id] = person.id
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
- cookies["zaikio_person_id"] = encrypted_cookies["zaikio_person_id"]
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
@@ -1,5 +1,5 @@
1
1
  module Zaikio
2
2
  module OAuthClient
3
- VERSION = "0.11.0".freeze
3
+ VERSION = "0.14.0".freeze
4
4
  end
5
5
  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.11.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-04-19 00:00:00.000000000 Z
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.2.1
89
+ version: '0.5'
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
- version: 0.5.0
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.2.1
99
+ version: '0.5'
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
- version: 0.5.0
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/master/CHANGELOG.md
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: