zaikio-oauth_client 0.12.1 → 0.15.1.beta1

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: 2e0377cbc59afa07b79f540877cbba7c79c0a23240202cdd1e1b0b1f79d21104
4
- data.tar.gz: 3b99c3429d501c37bb259046159794df88a26789d519a7ec50203961a62cfd43
3
+ metadata.gz: 5695820de8df28288feb3794016c0288e2dce2d7890a8c3bd9b11685fc39c32f
4
+ data.tar.gz: 2616666c8df490d153339d6953f6066a46f00669dfd037dcc2faf62873b44e9a
5
5
  SHA512:
6
- metadata.gz: f6b9f87688b92771ee8bb9ae1eea9ae9c83a09f393860925698ffa7adf515478b70d1621e438420ae39642a27c8c193a5a8232e1d028c58858428d8835b685e2
7
- data.tar.gz: 153edcd1c0eb91874efd44ad501c157ad5210da20447064b07d59967593cb59a2e940767f3a3c32943ae550a55e0f537a737bcab4f17fe6d373ff44f049c06f8
6
+ metadata.gz: dd7d9785f60d8c025ec461d6ab006f714f7f9abfd83ebffcfcf261c17a386903a6d9a42eb57708fd23b23662060190be1b5fd3089f03c10e0459a5106bcf4268
7
+ data.tar.gz: 1a554847284740a40cd231681572c30a0ae32c441a3da4de9feafdc36ea9057ff66ec93281be4108e4e1e7683c8f550a4bdf4b63153292f295295b29d0007a3f
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
@@ -264,6 +266,18 @@ Zaikio::OAuthClient.with_auth(bearer_type: "Organization", bearer_id: "fd61f5f5-
264
266
  end
265
267
  ```
266
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
+
267
281
  ## Use of dummy app
268
282
 
269
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(
@@ -26,27 +26,28 @@ module Zaikio
26
26
  end
27
27
 
28
28
  # Scopes
29
- scope :valid, lambda {
30
- where("expires_at > :now", now: Time.current)
29
+ scope :valid, lambda { |valid_until = Time.current|
30
+ where("expires_at > :valid_until", valid_until: valid_until)
31
31
  .where.not(id: Zaikio::JWTAuth.revoked_token_ids)
32
32
  }
33
33
  scope :with_invalid_refresh_token, lambda {
34
34
  where("created_at <= ?", Time.current - Zaikio::AccessToken.refresh_token_valid_for)
35
35
  }
36
- scope :valid_refresh, lambda {
37
- where("expires_at <= :now AND created_at > :created_at_max",
38
- now: Time.current,
39
- created_at_max: Time.current - refresh_token_valid_for)
40
- .where("refresh_token IS NOT NULL")
36
+ scope :valid_refresh, lambda { |valid_until = Time.current|
37
+ where("expires_at <= :valid_until AND created_at > :created_at_max",
38
+ valid_until: valid_until,
39
+ created_at_max: valid_until - refresh_token_valid_for)
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"|
44
44
  where(bearer_type: bearer_type, bearer_id: bearer_id)
45
45
  .where("requested_scopes @> ARRAY[?]::varchar[]", requested_scopes)
46
46
  }
47
- scope :usable, lambda { |options|
48
- by_bearer(**options).valid.or(by_bearer(**options).valid_refresh)
49
- .order(expires_at: :desc)
47
+ scope :usable, lambda { |valid_until: Time.current, **options|
48
+ by_bearer(**options).valid(valid_until).or(
49
+ by_bearer(**options).valid_refresh
50
+ ).order(expires_at: :desc)
50
51
  }
51
52
 
52
53
  def expired?
@@ -72,6 +73,8 @@ module Zaikio
72
73
  end
73
74
 
74
75
  def refresh!
76
+ return unless refresh_token?
77
+
75
78
  Zaikio::OAuthClient.with_oauth_scheme(:basic_auth) do
76
79
  refreshed_token = OAuth2::AccessToken.from_hash(
77
80
  Zaikio::OAuthClient.for(audience),
@@ -80,16 +83,12 @@ module Zaikio
80
83
 
81
84
  destroy
82
85
 
83
- self.class.build_from_access_token(
84
- refreshed_token,
85
- requested_scopes: requested_scopes
86
- ).tap(&:save!)
86
+ self.class.build_from_access_token(refreshed_token, requested_scopes: requested_scopes).tap(&:save!)
87
87
  end
88
88
  rescue OAuth2::Error => e
89
89
  raise unless e.code == "invalid_grant"
90
90
 
91
91
  destroy
92
-
93
92
  nil
94
93
  end
95
94
  end
@@ -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,14 +62,15 @@ 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
 
69
69
  token = find_usable_access_token(client_name: client_config.client_name,
70
70
  bearer_type: bearer_type,
71
71
  bearer_id: bearer_id,
72
- requested_scopes: scopes)
72
+ requested_scopes: scopes,
73
+ valid_for: valid_for)
73
74
 
74
75
  token = token.refresh! if token&.expired?
75
76
 
@@ -82,9 +83,9 @@ module Zaikio
82
83
 
83
84
  # Finds the best usable access token. Note that this token may have expired and
84
85
  # would require refreshing.
85
- def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:)
86
+ def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:, valid_for: 30.seconds) # rubocop:disable Metrics/MethodLength
86
87
  configuration.logger.debug "Try to fetch token for client_name: #{client_name}, "\
87
- "bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
88
+ "bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
88
89
 
89
90
  fetch_access_token = lambda {
90
91
  Zaikio::AccessToken
@@ -92,7 +93,8 @@ module Zaikio
92
93
  .usable(
93
94
  bearer_type: bearer_type,
94
95
  bearer_id: bearer_id,
95
- requested_scopes: requested_scopes
96
+ requested_scopes: requested_scopes,
97
+ valid_until: valid_for.from_now
96
98
  )
97
99
  .first
98
100
  }
@@ -117,9 +119,9 @@ module Zaikio
117
119
 
118
120
  def get_plain_scopes(scopes)
119
121
  regex = /^((Org|Per)\.)?(.*)$/
120
- scopes.map do |scope|
122
+ scopes.filter_map do |scope|
121
123
  (regex.match(scope) || [])[3]
122
- end.compact
124
+ end
123
125
  end
124
126
 
125
127
  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
 
@@ -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.1".freeze
3
+ VERSION = "0.15.1.beta1".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.1
4
+ version: 0.15.1.beta1
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-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -183,9 +183,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
183
  version: '0'
184
184
  required_rubygems_version: !ruby/object:Gem::Requirement
185
185
  requirements:
186
- - - ">="
186
+ - - ">"
187
187
  - !ruby/object:Gem::Version
188
- version: '0'
188
+ version: 1.3.1
189
189
  requirements: []
190
190
  rubygems_version: 3.2.3
191
191
  signing_key: