zaikio-oauth_client 0.12.0 → 0.15.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: 2e007c62cd36b1b00aa8e542958bb5d627b5ca417ffc6559f45de3868e79149a
4
- data.tar.gz: 9977c82c5f734d93b05269a7e9fb30e6fe6df1b15a291d680a48fa38bea079a8
3
+ metadata.gz: fb0748eddd282729e6a9ca264b17a59d58b9822c5e900f1bc3690b2b10549567
4
+ data.tar.gz: 191d4f0652fa8dfb9dae28bbfcd550ef8b2114366ef41ad291f25620011e8d3e
5
5
  SHA512:
6
- metadata.gz: eeb3f43dc40d4cabeb1f585864ff76c716243e6d0336164b0e3b98c7e2e41bdbd25ffdeaeeeb4b7ee1ccefe20cf1f458bd0af62e1cb2238af3ad258ad6cf4804
7
- data.tar.gz: e3b47a58b780c92ed0b8a9c5ae0df7011026feed340204e8deb80a88ca2562b4a220cd59c8d5907982488001b6738d5c0eb0ba2495771c0de2a0310f44de42bd
6
+ metadata.gz: 21c66faa4cd6cad8b787b39f919b0e1c30ec718b912f5442ad0fd4c96b7871a0db798bdf84e798d3ddaf441f8ae96819abea31fad7b4a631b12d2983fef378be
7
+ data.tar.gz: acc5550981b27d38cb986e0b934d4dad992ea7f3c462d9dd1f6c202a304e4cd13bb8e202db070f66f458e3263606601943d1f078d9967125c89b068d82554126
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
@@ -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.
@@ -249,6 +266,18 @@ Zaikio::OAuthClient.with_auth(bearer_type: "Organization", bearer_id: "fd61f5f5-
249
266
  end
250
267
  ```
251
268
 
269
+ If you need the token for a certain period (e.g. a long-running job which makes many
270
+ requests in sequence), you can specify the `valid_for` interval when requesting the token.
271
+ By default, it won't return an access token which was due to expire in less than 30
272
+ seconds from now. If there is an existing token, but it was due to expire before the end
273
+ of the validity period, this will go and get a fresh token anyway:
274
+
275
+ ```rb
276
+ Zaikio::OAuthClient.with_auth(..., valid_for: 10.minutes) do |access_token|
277
+ # ...
278
+ end
279
+ ```
280
+
252
281
  ## Use of dummy app
253
282
 
254
283
  You can use the included dummy app as a showcase for the workflow and to adjust your own application. To set up the dummy application properly, go into `test/dummy` and use [puma-dev](https://github.com/puma/puma-dev) like this:
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,7 +3,6 @@ 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
6
  opts[:state] ||= session[:state] = SecureRandom.urlsafe_base64(32)
8
7
 
9
8
  plan = opts.delete(:plan)
@@ -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)
@@ -62,7 +62,7 @@ module Zaikio
62
62
  # * If the token has expired, it will be refreshed using the refresh_token flow
63
63
  # (if this fails, we fallback to getting a new token using client_credentials)
64
64
  # * If the token does not exist, we'll get a new one using the client_credentials flow
65
- def get_access_token(bearer_id:, client_name: nil, bearer_type: "Person", scopes: nil)
65
+ def get_access_token(bearer_id:, client_name: nil, bearer_type: "Person", scopes: nil, valid_for: 30.seconds)
66
66
  client_config = client_config_for(client_name || self.client_name)
67
67
  scopes ||= client_config.default_scopes_for(bearer_type)
68
68
 
@@ -71,7 +71,7 @@ module Zaikio
71
71
  bearer_id: bearer_id,
72
72
  requested_scopes: scopes)
73
73
 
74
- token = token.refresh! if token&.expired?
74
+ token = token.refresh! if token && (token.expired? || token.expires_at < valid_for.from_now)
75
75
 
76
76
  token ||= fetch_new_token(client_config: client_config,
77
77
  bearer_type: bearer_type,
@@ -82,9 +82,9 @@ 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
- "bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
87
+ "bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
88
88
 
89
89
  fetch_access_token = lambda {
90
90
  Zaikio::AccessToken
@@ -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,8 +4,8 @@ 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
10
  opts[:state] ||= session[:state] = SecureRandom.urlsafe_base64(32)
11
11
 
@@ -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,
@@ -81,7 +81,7 @@ module Zaikio
81
81
 
82
82
  def client_config
83
83
  client_config = Zaikio::OAuthClient.configuration.find!(client_name)
84
- client_config = use_org_config? ? client_config.org_config : client_config
84
+ client_config = client_config.org_config if use_org_config?
85
85
 
86
86
  client_config or raise ActiveRecord::RecordNotFound
87
87
  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,7 +3,7 @@ module Zaikio
3
3
  module TestHelper
4
4
  extend ActiveSupport::Concern
5
5
 
6
- class TestSessionController < ActionController::Base
6
+ class TestSessionController < ActionController::Base # rubocop:disable Rails/ApplicationController
7
7
  def show
8
8
  if session[params[:key]].nil?
9
9
  head :no_content
@@ -1,5 +1,5 @@
1
1
  module Zaikio
2
2
  module OAuthClient
3
- VERSION = "0.12.0".freeze
3
+ VERSION = "0.15.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.12.0
4
+ version: 0.15.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-23 00:00:00.000000000 Z
11
+ date: 2021-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -84,16 +84,22 @@ dependencies:
84
84
  name: zaikio-jwt_auth
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0.5'
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: '2.0'
90
93
  type: :runtime
91
94
  prerelease: false
92
95
  version_requirements: !ruby/object:Gem::Requirement
93
96
  requirements:
94
- - - "~>"
97
+ - - ">="
95
98
  - !ruby/object:Gem::Version
96
99
  version: '0.5'
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: '2.0'
97
103
  - !ruby/object:Gem::Dependency
98
104
  name: pg
99
105
  requirement: !ruby/object:Gem::Requirement
@@ -158,6 +164,7 @@ files:
158
164
  - lib/zaikio/oauth_client/configuration.rb
159
165
  - lib/zaikio/oauth_client/engine.rb
160
166
  - lib/zaikio/oauth_client/error.rb
167
+ - lib/zaikio/oauth_client/system_test_helper.rb
161
168
  - lib/zaikio/oauth_client/test_helper.rb
162
169
  - lib/zaikio/oauth_client/version.rb
163
170
  homepage: https://github.com/zaikio/zaikio-oauth_client