zaikio-oauth_client 0.18.1 → 0.19.2

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: 25dbc767b924d59fa2706f4d7da22fd940ff80da966856447b8027e1ebca986c
4
- data.tar.gz: 0a7dbef1ae4c475583c5958ce4320285ca32532b7f55cc7a2b33386109657e2d
3
+ metadata.gz: 34a7bf1aa494d16086807798f3f15a3634571b485afae332ec57e7871b61dbd6
4
+ data.tar.gz: 3ee46611f92593cdf2cfd60403fe08f0d5401aca3217b0d063e040d6583a95c0
5
5
  SHA512:
6
- metadata.gz: f7c542585a0f6d9b47736f587f3b4f75b4544c439f23da8013c67d2f5d27d081c649e7c62985d787956bc04363c0d27315a6cdeb6085c8d2d51b30e022f5e55c
7
- data.tar.gz: 2f418622e4ff38e2f2e3f0b9550ffc170a0278584cc2261012a2632c5e7d7de6ca472f73e0a2720e11dcc8129663377772e692085ffc28cd13cac0573e3f9d4b
6
+ metadata.gz: b81867f191fd382ab76e06c2e3f4d7c7e76ad351ef10bd477f4eb352a7bf9545e677fdaefb7b83c6cdf3706caa86b095da8fbcd610ef9fae851c78c393312fbf
7
+ data.tar.gz: 66de7443b83d3976aa42216969809ccb88c7e0d1e4c22c1c7a43bb59aad4c30b87e44fc41f3a72bdab4ecdb91ba1c4789676e97b48d40a5f03cc72a7555d72e2
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,24 @@ module Zaikio
3
3
  module TestHelper
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ VirtualAccessToken = Struct.new(:id, :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
+ id: id,
16
+ bearer_id: person_id,
17
+ audience: audience,
18
+ bearer_type: "Person",
19
+ expired?: false
20
+ )
21
+ end
22
+ end
23
+
6
24
  class TestSessionController < ActionController::Base # rubocop:disable Rails/ApplicationController
7
25
  def show
8
26
  if session[params[:key]].nil?
@@ -43,7 +61,15 @@ module Zaikio
43
61
  get "/zaikio/oauth_client/test_helper/session", params: { id: value, key: key }
44
62
  end
45
63
 
46
- def logged_in_as(person)
64
+ def logged_in_as(person, access_token: nil, client_name: nil)
65
+ client_name ||= Zaikio::OAuthClient.client_name ||
66
+ Zaikio::OAuthClient.configuration.all_client_names.first
67
+ set_session(
68
+ :zaikio_access_token_id,
69
+ access_token&.id || "AT:#{client_name}:#{person.id}"
70
+ )
71
+
72
+ # Deprecated please use zaikio_access_token_id
47
73
  set_session(:zaikio_person_id, person.id)
48
74
  end
49
75
  end
@@ -1,5 +1,5 @@
1
1
  module Zaikio
2
2
  module OAuthClient
3
- VERSION = "0.18.1".freeze
3
+ VERSION = "0.19.2".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.1
4
+ version: 0.19.2
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-29 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