gamora 0.8.0 → 0.9.0

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: d898db3b0a39bb00099a8912953f6dcdfda11cddbb38eccfe72a798986a4dbb9
4
- data.tar.gz: 943a549def5cc2b014fe7200cb72cfdfd00acef025b2db74731cce0eecfa5927
3
+ metadata.gz: 6fff76821e79e75149f4d407303a9b52dac3b68ac711ffc38ac4e8d517ab7225
4
+ data.tar.gz: 4f5d52c9ef04b8d1219ca84a28fe25d3bb0dad677d97edc7c863d3c039a9e8d4
5
5
  SHA512:
6
- metadata.gz: a71915324e16d094db423133defdfa83f21a4451eb32ac468d4d2be35eb0768493e6cba8ed48c2efea746f4219e406751159c3d5eac500fe3e52f1e7c94c99d9
7
- data.tar.gz: 86a1b5282d7bfc407264f971bc3f5ba2c6f756028d5afdb857e069ede7cc9787c9ad4b291b9e4fcf9365bc9a4f4e26e977a3b13f4a870b1c32c0b24bd6ba95e4
6
+ metadata.gz: eaec688075667ad6184c0567aa2637480a1781e50e5a7bb9448ba27f0b39cc969f42d83374afb5c1c2a5ccc1a339cfc95c553e71492e1e0de65a836f247bde45
7
+ data.tar.gz: a7d1eadca9cd826bcb13f22c01e332324199877fd9e43285e3daae60a6b3ce29102f3beeccfb20db200563d7a6a90c8ae7dfe25d4097e9cb6fd8a2762ef9f0bb
@@ -15,9 +15,15 @@ module Gamora
15
15
  }.freeze
16
16
 
17
17
  def authenticate_user!
18
+ return authentication_failed! unless access_token.present?
19
+
20
+ token_data = introspect_access_token(access_token)
21
+ return authentication_failed! unless valid_token_data?(token_data)
22
+
18
23
  claims = resource_owner_claims(access_token)
19
- assign_current_user_from_claims(claims) if claims.present?
20
- validate_authentication!
24
+ return authentication_failed! unless claims.present?
25
+
26
+ assign_current_user_from_claims(claims)
21
27
  end
22
28
 
23
29
  def current_user
@@ -26,21 +32,29 @@ module Gamora
26
32
 
27
33
  private
28
34
 
29
- def validate_authentication!
35
+ def access_token
30
36
  raise NotImplementedError
31
37
  end
32
38
 
33
- def access_token
39
+ def authentication_failed!
34
40
  raise NotImplementedError
35
41
  end
36
42
 
37
- def user_authentication_failed!
38
- raise NotImplementedError
43
+ def valid_token_data?(token_data)
44
+ token_data[:active] && whitelisted_client?(token_data[:client_id])
45
+ end
46
+
47
+ def whitelisted_client?(client_id)
48
+ whitelisted_clients.include?(client_id)
49
+ end
50
+
51
+ def whitelisted_clients
52
+ Configuration.whitelisted_clients | [Configuration.client_id]
39
53
  end
40
54
 
41
55
  def assign_current_user_from_claims(claims)
42
- attrs = user_attributes_from_claims(claims)
43
- @current_user = User.new(attrs)
56
+ attributes = user_attributes_from_claims(claims)
57
+ @current_user = User.new(attributes)
44
58
  end
45
59
 
46
60
  def user_attributes_from_claims(claims)
@@ -48,27 +62,29 @@ module Gamora
48
62
  end
49
63
 
50
64
  def resource_owner_claims(access_token)
51
- return {} if access_token.blank?
52
-
53
- resource_owner_claims!(access_token)
54
- end
65
+ cache_key = cache_key(:userinfo, access_token)
66
+ expires_in = Configuration.userinfo_cache_expires_in
55
67
 
56
- def resource_owner_claims!(access_token)
57
- Rails.cache.fetch(cache_key(access_token), cache_options) do
68
+ Rails.cache.fetch(cache_key, { expires_in: expires_in }) do
58
69
  oauth_client.userinfo(access_token)
59
70
  end
60
71
  end
61
72
 
62
- def oauth_client
63
- Client.from_config
73
+ def introspect_access_token(access_token)
74
+ cache_key = cache_key(:introspect, access_token)
75
+ expires_in = Configuration.introspect_cache_expires_in
76
+
77
+ Rails.cache.fetch(cache_key, { expires_in: expires_in }) do
78
+ oauth_client.introspect(access_token)
79
+ end
64
80
  end
65
81
 
66
- def cache_options
67
- { expires_in: Configuration.userinfo_cache_expires_in }
82
+ def cache_key(context, access_token)
83
+ "gamora:#{context}:#{Digest::SHA256.hexdigest(access_token)}"
68
84
  end
69
85
 
70
- def cache_key(access_token)
71
- "userinfo:#{Digest::SHA256.hexdigest(access_token)}"
86
+ def oauth_client
87
+ Client.from_config
72
88
  end
73
89
  end
74
90
  end
@@ -7,12 +7,6 @@ module Gamora
7
7
 
8
8
  private
9
9
 
10
- def validate_authentication!
11
- return if current_user.present?
12
-
13
- user_authentication_failed!
14
- end
15
-
16
10
  def access_token
17
11
  pattern = /^Bearer /
18
12
  header = request.headers["Authorization"]
@@ -21,7 +15,7 @@ module Gamora
21
15
  header.gsub(pattern, "")
22
16
  end
23
17
 
24
- def user_authentication_failed!
18
+ def authentication_failed!
25
19
  render json: { error: "Access token invalid" }, status: :unauthorized
26
20
  end
27
21
  end
@@ -11,18 +11,12 @@ module Gamora
11
11
 
12
12
  private
13
13
 
14
- def validate_authentication!
15
- return if current_user.present?
16
-
17
- session["gamora.origin"] = request.original_url
18
- user_authentication_failed!
19
- end
20
-
21
14
  def access_token
22
15
  session[:access_token]
23
16
  end
24
17
 
25
- def user_authentication_failed!
18
+ def authentication_failed!
19
+ session["gamora.origin"] = request.original_url
26
20
  redirect_to gamora.authentication_path
27
21
  end
28
22
  end
data/lib/gamora/client.rb CHANGED
@@ -20,13 +20,25 @@ module Gamora
20
20
  token_method: Configuration.token_method,
21
21
  redirect_uri: Configuration.redirect_uri,
22
22
  userinfo_url: Configuration.userinfo_url,
23
- authorize_url: Configuration.authorize_url
23
+ authorize_url: Configuration.authorize_url,
24
+ introspect_url: Configuration.introspect_url
24
25
  }
25
26
  end
26
27
  end
27
28
 
28
29
  def userinfo(access_token)
29
- response = userinfo_request(access_token)
30
+ params = userinfo_params(access_token)
31
+ opts = request_options(params)
32
+ response = request(:post, options[:userinfo_url], opts)
33
+ JSON.parse(response.body).symbolize_keys
34
+ rescue OAuth2::Error
35
+ {}
36
+ end
37
+
38
+ def introspect(access_token)
39
+ params = introspect_params(access_token)
40
+ opts = request_options(params)
41
+ response = request(:post, options[:introspect_url], opts)
30
42
  JSON.parse(response.body).symbolize_keys
31
43
  rescue OAuth2::Error
32
44
  {}
@@ -34,15 +46,22 @@ module Gamora
34
46
 
35
47
  private
36
48
 
37
- def userinfo_request(access_token)
38
- opts = userinfo_request_options(access_token)
39
- request(:post, options[:userinfo_url], opts)
49
+ def request_options(params)
50
+ {
51
+ body: params.to_json,
52
+ headers: { "Content-Type": "application/json" }
53
+ }
40
54
  end
41
55
 
42
- def userinfo_request_options(access_token)
56
+ def userinfo_params(access_token)
57
+ { access_token: access_token }
58
+ end
59
+
60
+ def introspect_params(access_token)
43
61
  {
44
- body: { access_token: access_token }.to_json,
45
- headers: { "Content-Type": "application/json" }
62
+ token: access_token,
63
+ client_id: Configuration.client_id,
64
+ client_secret: Configuration.client_secret
46
65
  }
47
66
  end
48
67
  end
@@ -6,8 +6,9 @@ module Gamora
6
6
  mattr_accessor :client_secret, default: nil
7
7
  mattr_accessor :site, default: nil
8
8
  mattr_accessor :token_url, default: "/oauth2/token"
9
- mattr_accessor :authorize_url, default: "/oauth2/authorize"
10
9
  mattr_accessor :userinfo_url, default: "/oauth2/userinfo"
10
+ mattr_accessor :authorize_url, default: "/oauth2/authorize"
11
+ mattr_accessor :introspect_url, default: "/oauth2/introspect"
11
12
  mattr_accessor :token_method, default: :post
12
13
  mattr_accessor :redirect_uri, default: nil
13
14
  mattr_accessor :default_scope, default: "openid profile email"
@@ -16,7 +17,9 @@ module Gamora
16
17
  mattr_accessor :default_branding, default: "amco"
17
18
  mattr_accessor :default_theme, default: "default"
18
19
  mattr_accessor :ui_locales, default: -> { I18n.locale }
19
- mattr_accessor :userinfo_cache_expires_in, default: 0.seconds
20
+ mattr_accessor :userinfo_cache_expires_in, default: 1.minute
21
+ mattr_accessor :introspect_cache_expires_in, default: 0.seconds
22
+ mattr_accessor :whitelisted_clients, default: []
20
23
 
21
24
  def setup
22
25
  yield(self) if block_given?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gamora
4
- VERSION = "0.8.0"
4
+ VERSION = "0.9.0"
5
5
  end
@@ -8,8 +8,9 @@ Gamora.setup do |config|
8
8
 
9
9
  # ===> Optional OAuth2 configuration options and its defaults.
10
10
  # config.token_url = "/oauth2/token"
11
- # config.authorize_url = "/oauth2/authorize"
12
11
  # config.userinfo_url = "/oauth2/userinfo"
12
+ # config.authorize_url = "/oauth2/authorize"
13
+ # config.introspect_url = "/oauth2/introspect"
13
14
  # config.token_method = :post
14
15
  # config.redirect_uri = nil
15
16
  # config.default_scope = "openid profile email"
@@ -18,5 +19,7 @@ Gamora.setup do |config|
18
19
  # config.default_branding = "amco"
19
20
  # config.default_theme = "default"
20
21
  # config.ui_locales = -> { I18n.locale }
21
- # config.userinfo_cache_expires_in = 0.seconds
22
+ # config.userinfo_cache_expires_in = 1.minute
23
+ # config.introspect_cache_expires_in = 0.seconds
24
+ # config.whitelisted_clients = []
22
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gamora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Gutiérrez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-21 00:00:00.000000000 Z
11
+ date: 2023-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth2