zaikio-oauth_client 0.11.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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: