gamora 0.7.0 → 0.9.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: e164eceeb7c3a744ed43be46877cb904fff4add871d4a7b4fac25e4837f2f731
4
- data.tar.gz: cff5f7b7f3ffd07b13d6e6cc0e476ae86c87788bdf47a4e9c9ff4703dfe54d64
3
+ metadata.gz: 6fff76821e79e75149f4d407303a9b52dac3b68ac711ffc38ac4e8d517ab7225
4
+ data.tar.gz: 4f5d52c9ef04b8d1219ca84a28fe25d3bb0dad677d97edc7c863d3c039a9e8d4
5
5
  SHA512:
6
- metadata.gz: b5da9c118a7f13441147ded22bb7bc237e7b51cd583e7355fa65370ef4e71dfa5256150f6ff0b6aad0f0169a1113dc9a8af2514aecff33454bb571391dea74de
7
- data.tar.gz: ad67d0b0be691f544bd2ffcc277b6a70f036bd20ddbabfd9a48b1f92023f84023e8eaa715b6ccc82a9f8a90f4be975b0ac54a657bc18a14e6fd6e40f4bff6f23
6
+ metadata.gz: eaec688075667ad6184c0567aa2637480a1781e50e5a7bb9448ba27f0b39cc969f42d83374afb5c1c2a5ccc1a339cfc95c553e71492e1e0de65a836f247bde45
7
+ data.tar.gz: a7d1eadca9cd826bcb13f22c01e332324199877fd9e43285e3daae60a6b3ce29102f3beeccfb20db200563d7a6a90c8ae7dfe25d4097e9cb6fd8a2762ef9f0bb
@@ -5,6 +5,7 @@ module Gamora
5
5
  module Base
6
6
  CLAIMS = {
7
7
  sub: :id,
8
+ roles: :roles,
8
9
  email: :email,
9
10
  given_name: :first_name,
10
11
  family_name: :last_name,
@@ -14,9 +15,15 @@ module Gamora
14
15
  }.freeze
15
16
 
16
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
+
17
23
  claims = resource_owner_claims(access_token)
18
- assign_current_user_from_claims(claims) if claims.present?
19
- validate_authentication!
24
+ return authentication_failed! unless claims.present?
25
+
26
+ assign_current_user_from_claims(claims)
20
27
  end
21
28
 
22
29
  def current_user
@@ -25,21 +32,29 @@ module Gamora
25
32
 
26
33
  private
27
34
 
28
- def validate_authentication!
35
+ def access_token
29
36
  raise NotImplementedError
30
37
  end
31
38
 
32
- def access_token
39
+ def authentication_failed!
33
40
  raise NotImplementedError
34
41
  end
35
42
 
36
- def user_authentication_failed!
37
- 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]
38
53
  end
39
54
 
40
55
  def assign_current_user_from_claims(claims)
41
- attrs = user_attributes_from_claims(claims)
42
- @current_user = User.new(attrs)
56
+ attributes = user_attributes_from_claims(claims)
57
+ @current_user = User.new(attributes)
43
58
  end
44
59
 
45
60
  def user_attributes_from_claims(claims)
@@ -47,27 +62,29 @@ module Gamora
47
62
  end
48
63
 
49
64
  def resource_owner_claims(access_token)
50
- return {} if access_token.blank?
51
-
52
- resource_owner_claims!(access_token)
53
- end
65
+ cache_key = cache_key(:userinfo, access_token)
66
+ expires_in = Configuration.userinfo_cache_expires_in
54
67
 
55
- def resource_owner_claims!(access_token)
56
- Rails.cache.fetch(cache_key(access_token), cache_options) do
68
+ Rails.cache.fetch(cache_key, { expires_in: expires_in }) do
57
69
  oauth_client.userinfo(access_token)
58
70
  end
59
71
  end
60
72
 
61
- def oauth_client
62
- 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
63
80
  end
64
81
 
65
- def cache_options
66
- { expires_in: Configuration.userinfo_cache_expires_in }
82
+ def cache_key(context, access_token)
83
+ "gamora:#{context}:#{Digest::SHA256.hexdigest(access_token)}"
67
84
  end
68
85
 
69
- def cache_key(access_token)
70
- "userinfo:#{Digest::SHA256.hexdigest(access_token)}"
86
+ def oauth_client
87
+ Client.from_config
71
88
  end
72
89
  end
73
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?
data/lib/gamora/user.rb CHANGED
@@ -5,6 +5,7 @@ module Gamora
5
5
  include ActiveModel::Model
6
6
 
7
7
  attr_accessor :id,
8
+ :roles,
8
9
  :email,
9
10
  :last_name,
10
11
  :first_name,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gamora
4
- VERSION = "0.7.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.7.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-02 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