zaikio-oauth_client 0.18.0 → 0.19.1

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: 4f6d99b08d0e3fc512ce6a4bf8184be7c7d95144f3798062756f8f8159f86655
4
- data.tar.gz: 4ed2286c417bdac976e6ad1f26c4ec84fc8d18b52312b082fd548800edfbec9b
3
+ metadata.gz: fd5390d254c886ad8c082def82463c6653bdb91b4f08433bf138b872e9fb54ff
4
+ data.tar.gz: b9bca34becf29861bd4e5f57d88492a9dfb7aecb8ad6ed2306c2007ee75740e5
5
5
  SHA512:
6
- metadata.gz: fb66005f53cbb480678247a36aa77af00c32fb93cdf4ca9615aa3bf51efa82e83e60fdf4f61d68123e331a369451db548b40a8cc0f8e57cec3d6cd686872918f
7
- data.tar.gz: 63e5d71e4025046ef18c1759d582262f319581a8462092026b7f21e19640250ce94f6caefe5a6365e823c910eb4d8a390cb3a65a328a579739b06387e2732141
6
+ metadata.gz: 61f6e1657014daa3b0cc5efb2e5a0ac97c0d81708d68ad7a98b030e24ce5fd2e3918c2613371dc7f9ed64f5546dad84e8f189e996fe1db113a5a295137cba74c
7
+ data.tar.gz: 38e9e845d6bae276a28ef32d6fab275ae0539598c1f7c85680ba87554e3ac0f5619261cb9346435b787c06526d0a87ca2ddfbb502a299027d1b81ea75bc424af
data/README.md CHANGED
@@ -145,12 +145,19 @@ redirect_to zaikio_oauth_client.new_subscription_path(plan: "free")
145
145
 
146
146
  #### Session handling
147
147
 
148
- The Zaikio gem engine will set a cookie for the user after a successful OAuth flow: `session[:zaikio_person_id]`.
148
+ The Zaikio gem engine will set a cookie for the access token after a successful OAuth flow: `session[:zaikio_access_token_id]`.
149
149
 
150
150
  If you are using for example `Zaikio::Hub::Models`, you can use this snippet to set the current user:
151
151
 
152
152
  ```ruby
153
- Current.user ||= Zaikio::Hub::Models::Person.find_by(id: session[:zaikio_person_id])
153
+ access_token = Zaikio::OAuthClient.find_active_access_token(session[:zaikio_access_token_id])
154
+ session[:zaikio_access_token_id] = access_token&.id
155
+ Current.user = Zaikio::Hub::Models::Person.find_by(id: access_token&.bearer_id)
156
+
157
+ unless Current.user
158
+ session[:origin] = request.fullpath
159
+ redirect_to zaikio_oauth_client.new_session_path
160
+ end
154
161
  ````
155
162
 
156
163
  You can then use `Current.user` anywhere.
@@ -9,7 +9,7 @@ module Zaikio
9
9
  encrypts :token
10
10
  encrypts :refresh_token
11
11
 
12
- def self.build_from_access_token(access_token, requested_scopes: nil)
12
+ def self.build_from_access_token(access_token, requested_scopes: nil, include_refresh_token: true)
13
13
  payload = JWT.decode(access_token.token, nil, false).first rescue {} # rubocop:disable Style/RescueModifier
14
14
  scopes = access_token.params["scope"].split(",")
15
15
  new(
@@ -18,7 +18,7 @@ module Zaikio
18
18
  bearer_id: access_token.params["bearer"]["id"],
19
19
  audience: access_token.params["audiences"].first,
20
20
  token: access_token.token,
21
- refresh_token: access_token.refresh_token,
21
+ refresh_token: (access_token.refresh_token if include_refresh_token),
22
22
  expires_at: Time.strptime(access_token.expires_at.to_s, "%s"),
23
23
  scopes: scopes,
24
24
  requested_scopes: requested_scopes || scopes
@@ -67,7 +67,7 @@ module Zaikio
67
67
  end
68
68
 
69
69
  def bearer_klass
70
- return unless Zaikio.const_defined?("Hub::Models", false) # rubocop:disable Performance/StringIdentifierArgument
70
+ return unless Zaikio.const_defined?("Hub::Models", false)
71
71
 
72
72
  if Zaikio::Hub::Models.configuration.respond_to?(:"#{bearer_type.underscore}_class_name")
73
73
  Zaikio::Hub::Models.configuration.public_send(:"#{bearer_type.underscore}_class_name").constantize
@@ -95,5 +95,15 @@ module Zaikio
95
95
  destroy
96
96
  nil
97
97
  end
98
+
99
+ def revoke!
100
+ return unless Zaikio.const_defined?("Hub::RevokedAccessToken", false)
101
+
102
+ Zaikio::Hub.with_token(token) do
103
+ Zaikio::Hub::RevokedAccessToken.create
104
+ end
105
+ rescue Zaikio::ConnectionError => e
106
+ Zaikio::OAuthClient.configuration.logger.warn "Access Token #{id} could not be revoked: #{e.message}"
107
+ end
98
108
  end
99
109
  end
@@ -55,13 +55,16 @@ module Zaikio
55
55
  end
56
56
 
57
57
  def destroy
58
- access_token_id = session[:zaikio_access_token_id]
58
+ if (access_token = Zaikio::AccessToken.valid.or(Zaikio::AccessToken.valid_refresh)
59
+ .find_by(id: session[:zaikio_access_token_id]))
60
+ access_token.revoke!
61
+ end
59
62
  session.delete(:zaikio_access_token_id)
60
63
  session.delete(:origin)
61
64
 
62
65
  redirect_to send(
63
66
  respond_to?(:after_destroy_path_for) ? :after_destroy_path_for : :default_after_destroy_path_for,
64
- access_token_id
67
+ access_token.id
65
68
  )
66
69
  end
67
70
 
@@ -3,6 +3,23 @@ module Zaikio
3
3
  module TestHelper
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ VirtualAccessToken = Struct.new(:bearer_id, :bearer_type, :audience, :expired?, keyword_init: true)
7
+
8
+ class << self
9
+ def find_active_access_token(id)
10
+ return unless id.to_s.starts_with?("AT:")
11
+
12
+ _, audience, person_id = id.split(":")
13
+
14
+ VirtualAccessToken.new(
15
+ bearer_id: person_id,
16
+ audience: audience,
17
+ bearer_type: "Person",
18
+ expired?: false
19
+ )
20
+ end
21
+ end
22
+
6
23
  class TestSessionController < ActionController::Base # rubocop:disable Rails/ApplicationController
7
24
  def show
8
25
  if session[params[:key]].nil?
@@ -43,7 +60,15 @@ module Zaikio
43
60
  get "/zaikio/oauth_client/test_helper/session", params: { id: value, key: key }
44
61
  end
45
62
 
46
- def logged_in_as(person)
63
+ def logged_in_as(person, access_token: nil, client_name: nil)
64
+ client_name ||= Zaikio::OAuthClient.client_name ||
65
+ Zaikio::OAuthClient.configuration.all_client_names.first
66
+ set_session(
67
+ :zaikio_access_token_id,
68
+ access_token&.id || "AT:#{client_name}:#{person.id}"
69
+ )
70
+
71
+ # Deprecated please use zaikio_access_token_id
47
72
  set_session(:zaikio_person_id, person.id)
48
73
  end
49
74
  end
@@ -1,5 +1,5 @@
1
1
  module Zaikio
2
2
  module OAuthClient
3
- VERSION = "0.18.0".freeze
3
+ VERSION = "0.19.1".freeze
4
4
  end
5
5
  end
@@ -6,7 +6,7 @@ require "zaikio/oauth_client/configuration"
6
6
  require "zaikio/oauth_client/authenticatable"
7
7
 
8
8
  module Zaikio
9
- module OAuthClient
9
+ module OAuthClient # rubocop:disable Metrics/ModuleLength
10
10
  class << self
11
11
  attr_reader :client_name
12
12
 
@@ -58,9 +58,8 @@ module Zaikio
58
58
  end
59
59
  end
60
60
 
61
- # Finds the best possible access token, using the DB or an API call
62
- # * If the token has expired, it will be refreshed using the refresh_token flow
63
- # (if this fails, we fallback to getting a new token using client_credentials)
61
+ # Finds active access token, using the DB or Client Credentials flow
62
+ # * It searches in the DB for an active access token
64
63
  # * If the token does not exist, we'll get a new one using the client_credentials flow
65
64
  def get_access_token(bearer_id:, client_name: nil, bearer_type: "Person", scopes: nil, valid_for: 30.seconds)
66
65
  client_config = client_config_for(client_name || self.client_name)
@@ -72,8 +71,6 @@ module Zaikio
72
71
  requested_scopes: scopes,
73
72
  valid_for: valid_for)
74
73
 
75
- token = token.refresh! if token&.expired?
76
-
77
74
  token ||= fetch_new_token(client_config: client_config,
78
75
  bearer_type: bearer_type,
79
76
  bearer_id: bearer_id,
@@ -81,21 +78,36 @@ module Zaikio
81
78
  token
82
79
  end
83
80
 
84
- # Finds the best usable access token. Note that this token may have expired and
85
- # would require refreshing.
86
- def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:, valid_for: 30.seconds) # rubocop:disable Metrics/MethodLength
87
- configuration.logger.debug "Try to fetch token for client_name: #{client_name}, "\
81
+ # This method can be used to find an active access token by id.
82
+ # It might refresh the access token to get an active one.
83
+ def find_active_access_token(id)
84
+ return unless id
85
+
86
+ if Rails.env.test?
87
+ access_token = TestHelper.find_active_access_token(id)
88
+ return access_token if access_token
89
+ end
90
+
91
+ access_token = Zaikio::AccessToken.find_by(id: id)
92
+ access_token = access_token.refresh! if access_token&.expired?
93
+
94
+ access_token
95
+ end
96
+
97
+ # Finds active access token with matching criteria for bearer and scopes.
98
+ def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:, valid_for: 30.seconds) # rubocop:disable Metrics/MethodLength
99
+ configuration.logger.debug "Try to fetch token for client_name: #{client_name}, " \
88
100
  "bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
89
101
 
90
102
  fetch_access_token = lambda {
91
103
  Zaikio::AccessToken
92
104
  .where(audience: client_name)
93
- .usable(
105
+ .by_bearer(
94
106
  bearer_type: bearer_type,
95
107
  bearer_id: bearer_id,
96
- requested_scopes: requested_scopes,
97
- valid_until: valid_for.from_now
108
+ requested_scopes: requested_scopes
98
109
  )
110
+ .valid(valid_for.from_now)
99
111
  .first
100
112
  }
101
113
 
@@ -113,7 +125,10 @@ module Zaikio
113
125
  bearer_id: bearer_id,
114
126
  scopes: scopes
115
127
  ),
116
- requested_scopes: scopes
128
+ requested_scopes: scopes,
129
+ include_refresh_token: false
130
+ # Do not store refresh token on client credentials flow
131
+ # https://docs.zaikio.com/changelog/2022-08-09_client-credentials-drop-refresh-token.html
117
132
  ).tap(&:save!)
118
133
  end
119
134
 
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.18.0
4
+ version: 0.19.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zaikio GmbH
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-26 00:00:00.000000000 Z
11
+ date: 2022-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -89,7 +89,7 @@ dependencies:
89
89
  version: '0.5'
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
- version: '2.0'
92
+ version: '3.0'
93
93
  type: :runtime
94
94
  prerelease: false
95
95
  version_requirements: !ruby/object:Gem::Requirement
@@ -99,7 +99,7 @@ dependencies:
99
99
  version: '0.5'
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
- version: '2.0'
102
+ version: '3.0'
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: pg
105
105
  requirement: !ruby/object:Gem::Requirement