keycloak-api-rails 0.11.1 → 0.12.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: 90c326858b9b9eb917fb48a1de41b8bb04bda9ee9c335c9d54cc32a2cf1e6cf1
4
- data.tar.gz: 0f2e7ffb1ff96cf183db47552561d7bde77c98178f2568874ef1ddfe55c09a9f
3
+ metadata.gz: d0e8e7c47df127347543955ffc2ed362dc9c2efb549bc970f0efdd519f8cfb1a
4
+ data.tar.gz: 5b77f9cf1171a36db3d80c6cd31e0df8f0acb00a58916e9b7a4fdcfdec331ecd
5
5
  SHA512:
6
- metadata.gz: c9bf1dd58e9da0fbc485c12cf9dc73ccb31d88bef5158107a8d141542380a818d89fc90810cdfb3a867048d854ed616d0b640d8edb17d9d48999cc2ec8469b77
7
- data.tar.gz: 39e57c6bacf0c31bb94bfdd53e454745bb3c100e831b804e840183b80b6472338731b01a5fcb70c9b46029c01e118670a3f4e503bf6003bbb449c60915a4c0f1
6
+ metadata.gz: 38edbedbe88b629c6c6728eda1b60670cd9dd6b03f6246c4bfd79bcc6fd3832922c504b91c15f4f4c7e86128e4d143800f5562292cf0f38877e73f0f39f4a8ff
7
+ data.tar.gz: d6e9d6ca5a7d5a531e09e7e2fe63d026bd53f088ceabbb2484e59ab36ac1aee234d949ac30c342f67a2784442dacfb1d502762f35999d977d8175189c19193fa
data/CHANGELOG.md CHANGED
@@ -5,14 +5,23 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.12.0] - 2023-04-11
9
+
10
+ * Introduce Opt-in mode as an alternative configuration (thanks to @theSteveMitchell)
11
+
12
+ ## [0.11.2] - 2022-03-30
13
+
14
+ * Update `Gemfile.lock` to avoid wrong CVE detections. The version of Rails should always be specified by the parent project. This change has no functional impact.
15
+ * Update `json-jwt` to `>=1.13.0`
16
+
8
17
  ## [0.11.1] - 2019-11-27
9
18
 
10
19
  * When a token validation error occurs, do not log it as a `warn` (but as an `info` instead)
11
20
 
12
21
  ## [0.11.0] - 2019-11-21
13
22
 
14
- * Remove dependency to `rest-client` (thanks to @@loicvigneron)
15
- * Access Authorization Party from ENV (thanks to @@loicvigneron)
16
- * New configuration option: `ca_certificate_file` (thanks to @@loicvigneron)
23
+ * Remove dependency to `rest-client` (thanks to @loicvigneron)
24
+ * Access Authorization Party from ENV (thanks to @loicvigneron)
25
+ * New configuration option: `ca_certificate_file` (thanks to @loicvigneron)
17
26
  * Access the token from ENV
18
27
  * Upgrade `json-jwt` to `1.11.0`
data/Dockerfile CHANGED
@@ -1,5 +1,8 @@
1
- FROM ruby:2.5.0
2
- RUN mkdir -p /usr/src/app/lib/keycloak-api-rails
1
+ FROM ruby:2.7.5-slim-bullseye
2
+
3
+ RUN apt-get update -qq && apt-get install -y build-essential git ruby-dev && apt-get clean && \
4
+ mkdir -p /usr/src/app/lib/keycloak-api-rails
5
+
3
6
  WORKDIR /usr/src/app
4
7
 
5
8
  COPY Gemfile /usr/src/app/
data/Gemfile.lock CHANGED
@@ -1,167 +1,192 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- keycloak-api-rails (0.11.1)
4
+ keycloak-api-rails (0.12.0)
5
5
  json-jwt (>= 1.11.0)
6
6
  rails (>= 4.2)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actioncable (6.0.1)
12
- actionpack (= 6.0.1)
11
+ actioncable (7.0.4.3)
12
+ actionpack (= 7.0.4.3)
13
+ activesupport (= 7.0.4.3)
13
14
  nio4r (~> 2.0)
14
15
  websocket-driver (>= 0.6.1)
15
- actionmailbox (6.0.1)
16
- actionpack (= 6.0.1)
17
- activejob (= 6.0.1)
18
- activerecord (= 6.0.1)
19
- activestorage (= 6.0.1)
20
- activesupport (= 6.0.1)
16
+ actionmailbox (7.0.4.3)
17
+ actionpack (= 7.0.4.3)
18
+ activejob (= 7.0.4.3)
19
+ activerecord (= 7.0.4.3)
20
+ activestorage (= 7.0.4.3)
21
+ activesupport (= 7.0.4.3)
21
22
  mail (>= 2.7.1)
22
- actionmailer (6.0.1)
23
- actionpack (= 6.0.1)
24
- actionview (= 6.0.1)
25
- activejob (= 6.0.1)
23
+ net-imap
24
+ net-pop
25
+ net-smtp
26
+ actionmailer (7.0.4.3)
27
+ actionpack (= 7.0.4.3)
28
+ actionview (= 7.0.4.3)
29
+ activejob (= 7.0.4.3)
30
+ activesupport (= 7.0.4.3)
26
31
  mail (~> 2.5, >= 2.5.4)
32
+ net-imap
33
+ net-pop
34
+ net-smtp
27
35
  rails-dom-testing (~> 2.0)
28
- actionpack (6.0.1)
29
- actionview (= 6.0.1)
30
- activesupport (= 6.0.1)
31
- rack (~> 2.0)
36
+ actionpack (7.0.4.3)
37
+ actionview (= 7.0.4.3)
38
+ activesupport (= 7.0.4.3)
39
+ rack (~> 2.0, >= 2.2.0)
32
40
  rack-test (>= 0.6.3)
33
41
  rails-dom-testing (~> 2.0)
34
42
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
35
- actiontext (6.0.1)
36
- actionpack (= 6.0.1)
37
- activerecord (= 6.0.1)
38
- activestorage (= 6.0.1)
39
- activesupport (= 6.0.1)
43
+ actiontext (7.0.4.3)
44
+ actionpack (= 7.0.4.3)
45
+ activerecord (= 7.0.4.3)
46
+ activestorage (= 7.0.4.3)
47
+ activesupport (= 7.0.4.3)
48
+ globalid (>= 0.6.0)
40
49
  nokogiri (>= 1.8.5)
41
- actionview (6.0.1)
42
- activesupport (= 6.0.1)
50
+ actionview (7.0.4.3)
51
+ activesupport (= 7.0.4.3)
43
52
  builder (~> 3.1)
44
53
  erubi (~> 1.4)
45
54
  rails-dom-testing (~> 2.0)
46
55
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
47
- activejob (6.0.1)
48
- activesupport (= 6.0.1)
56
+ activejob (7.0.4.3)
57
+ activesupport (= 7.0.4.3)
49
58
  globalid (>= 0.3.6)
50
- activemodel (6.0.1)
51
- activesupport (= 6.0.1)
52
- activerecord (6.0.1)
53
- activemodel (= 6.0.1)
54
- activesupport (= 6.0.1)
55
- activestorage (6.0.1)
56
- actionpack (= 6.0.1)
57
- activejob (= 6.0.1)
58
- activerecord (= 6.0.1)
59
- marcel (~> 0.3.1)
60
- activesupport (6.0.1)
59
+ activemodel (7.0.4.3)
60
+ activesupport (= 7.0.4.3)
61
+ activerecord (7.0.4.3)
62
+ activemodel (= 7.0.4.3)
63
+ activesupport (= 7.0.4.3)
64
+ activestorage (7.0.4.3)
65
+ actionpack (= 7.0.4.3)
66
+ activejob (= 7.0.4.3)
67
+ activerecord (= 7.0.4.3)
68
+ activesupport (= 7.0.4.3)
69
+ marcel (~> 1.0)
70
+ mini_mime (>= 1.1.0)
71
+ activesupport (7.0.4.3)
61
72
  concurrent-ruby (~> 1.0, >= 1.0.2)
62
- i18n (>= 0.7, < 2)
63
- minitest (~> 5.1)
64
- tzinfo (~> 1.1)
65
- zeitwerk (~> 2.2)
66
- aes_key_wrap (1.0.1)
67
- bindata (2.4.4)
68
- builder (3.2.3)
69
- byebug (9.1.0)
70
- concurrent-ruby (1.1.5)
71
- crass (1.0.5)
72
- diff-lcs (1.3)
73
- erubi (1.9.0)
74
- globalid (0.4.2)
75
- activesupport (>= 4.2.0)
76
- i18n (1.7.0)
73
+ i18n (>= 1.6, < 2)
74
+ minitest (>= 5.1)
75
+ tzinfo (~> 2.0)
76
+ aes_key_wrap (1.1.0)
77
+ bindata (2.4.15)
78
+ builder (3.2.4)
79
+ byebug (11.1.3)
80
+ concurrent-ruby (1.2.2)
81
+ crass (1.0.6)
82
+ date (3.3.3)
83
+ diff-lcs (1.5.0)
84
+ erubi (1.12.0)
85
+ faraday (2.7.4)
86
+ faraday-net_http (>= 2.0, < 3.1)
87
+ ruby2_keywords (>= 0.0.4)
88
+ faraday-follow_redirects (0.3.0)
89
+ faraday (>= 1, < 3)
90
+ faraday-net_http (3.0.2)
91
+ globalid (1.1.0)
92
+ activesupport (>= 5.0)
93
+ i18n (1.12.0)
77
94
  concurrent-ruby (~> 1.0)
78
- json-jwt (1.11.0)
95
+ json-jwt (1.16.3)
79
96
  activesupport (>= 4.2)
80
97
  aes_key_wrap
81
98
  bindata
82
- loofah (2.4.0)
99
+ faraday (~> 2.0)
100
+ faraday-follow_redirects
101
+ loofah (2.20.0)
83
102
  crass (~> 1.0.2)
84
103
  nokogiri (>= 1.5.9)
85
- mail (2.7.1)
104
+ mail (2.8.1)
86
105
  mini_mime (>= 0.1.1)
87
- marcel (0.3.3)
88
- mimemagic (~> 0.3.2)
89
- method_source (0.9.2)
90
- mimemagic (0.3.3)
91
- mini_mime (1.0.2)
92
- mini_portile2 (2.4.0)
93
- minitest (5.13.0)
94
- nio4r (2.5.2)
95
- nokogiri (1.10.5)
96
- mini_portile2 (~> 2.4.0)
97
- rack (2.0.7)
98
- rack-test (1.1.0)
99
- rack (>= 1.0, < 3)
100
- rails (6.0.1)
101
- actioncable (= 6.0.1)
102
- actionmailbox (= 6.0.1)
103
- actionmailer (= 6.0.1)
104
- actionpack (= 6.0.1)
105
- actiontext (= 6.0.1)
106
- actionview (= 6.0.1)
107
- activejob (= 6.0.1)
108
- activemodel (= 6.0.1)
109
- activerecord (= 6.0.1)
110
- activestorage (= 6.0.1)
111
- activesupport (= 6.0.1)
112
- bundler (>= 1.3.0)
113
- railties (= 6.0.1)
114
- sprockets-rails (>= 2.0.0)
106
+ net-imap
107
+ net-pop
108
+ net-smtp
109
+ marcel (1.0.2)
110
+ method_source (1.0.0)
111
+ mini_mime (1.1.2)
112
+ mini_portile2 (2.8.1)
113
+ minitest (5.18.0)
114
+ net-imap (0.3.4)
115
+ date
116
+ net-protocol
117
+ net-pop (0.1.2)
118
+ net-protocol
119
+ net-protocol (0.2.1)
120
+ timeout
121
+ net-smtp (0.3.3)
122
+ net-protocol
123
+ nio4r (2.5.9)
124
+ nokogiri (1.14.3)
125
+ mini_portile2 (~> 2.8.0)
126
+ racc (~> 1.4)
127
+ racc (1.6.2)
128
+ rack (2.2.6.4)
129
+ rack-test (2.1.0)
130
+ rack (>= 1.3)
131
+ rails (7.0.4.3)
132
+ actioncable (= 7.0.4.3)
133
+ actionmailbox (= 7.0.4.3)
134
+ actionmailer (= 7.0.4.3)
135
+ actionpack (= 7.0.4.3)
136
+ actiontext (= 7.0.4.3)
137
+ actionview (= 7.0.4.3)
138
+ activejob (= 7.0.4.3)
139
+ activemodel (= 7.0.4.3)
140
+ activerecord (= 7.0.4.3)
141
+ activestorage (= 7.0.4.3)
142
+ activesupport (= 7.0.4.3)
143
+ bundler (>= 1.15.0)
144
+ railties (= 7.0.4.3)
115
145
  rails-dom-testing (2.0.3)
116
146
  activesupport (>= 4.2.0)
117
147
  nokogiri (>= 1.6)
118
- rails-html-sanitizer (1.3.0)
119
- loofah (~> 2.3)
120
- railties (6.0.1)
121
- actionpack (= 6.0.1)
122
- activesupport (= 6.0.1)
148
+ rails-html-sanitizer (1.5.0)
149
+ loofah (~> 2.19, >= 2.19.1)
150
+ railties (7.0.4.3)
151
+ actionpack (= 7.0.4.3)
152
+ activesupport (= 7.0.4.3)
123
153
  method_source
124
- rake (>= 0.8.7)
125
- thor (>= 0.20.3, < 2.0)
126
- rake (13.0.1)
127
- rspec (3.7.0)
128
- rspec-core (~> 3.7.0)
129
- rspec-expectations (~> 3.7.0)
130
- rspec-mocks (~> 3.7.0)
131
- rspec-core (3.7.1)
132
- rspec-support (~> 3.7.0)
133
- rspec-expectations (3.7.0)
154
+ rake (>= 12.2)
155
+ thor (~> 1.0)
156
+ zeitwerk (~> 2.5)
157
+ rake (13.0.6)
158
+ rspec (3.12.0)
159
+ rspec-core (~> 3.12.0)
160
+ rspec-expectations (~> 3.12.0)
161
+ rspec-mocks (~> 3.12.0)
162
+ rspec-core (3.12.1)
163
+ rspec-support (~> 3.12.0)
164
+ rspec-expectations (3.12.2)
134
165
  diff-lcs (>= 1.2.0, < 2.0)
135
- rspec-support (~> 3.7.0)
136
- rspec-mocks (3.7.0)
166
+ rspec-support (~> 3.12.0)
167
+ rspec-mocks (3.12.5)
137
168
  diff-lcs (>= 1.2.0, < 2.0)
138
- rspec-support (~> 3.7.0)
139
- rspec-support (3.7.0)
140
- sprockets (4.0.0)
169
+ rspec-support (~> 3.12.0)
170
+ rspec-support (3.12.0)
171
+ ruby2_keywords (0.0.5)
172
+ thor (1.2.1)
173
+ timecop (0.9.6)
174
+ timeout (0.3.2)
175
+ tzinfo (2.0.6)
141
176
  concurrent-ruby (~> 1.0)
142
- rack (> 1, < 3)
143
- sprockets-rails (3.2.1)
144
- actionpack (>= 4.0)
145
- activesupport (>= 4.0)
146
- sprockets (>= 3.0.0)
147
- thor (0.20.3)
148
- thread_safe (0.3.6)
149
- timecop (0.9.1)
150
- tzinfo (1.2.5)
151
- thread_safe (~> 0.1)
152
- websocket-driver (0.7.1)
177
+ websocket-driver (0.7.5)
153
178
  websocket-extensions (>= 0.1.0)
154
- websocket-extensions (0.1.4)
155
- zeitwerk (2.2.1)
179
+ websocket-extensions (0.1.5)
180
+ zeitwerk (2.6.7)
156
181
 
157
182
  PLATFORMS
158
183
  ruby
159
184
 
160
185
  DEPENDENCIES
161
- byebug (= 9.1.0)
186
+ byebug (= 11.1.3)
162
187
  keycloak-api-rails!
163
- rspec (= 3.7.0)
164
- timecop (= 0.9.1)
188
+ rspec (= 3.12.0)
189
+ timecop (= 0.9.6)
165
190
 
166
191
  BUNDLED WITH
167
- 1.17.3
192
+ 2.1.4
data/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # Keycloak-Rails-Api
2
2
 
3
- This gem aims at validates Keycloak JWT token in Ruby On Rails APIs.
3
+ This gem validates Keycloak JWT token for Ruby On Rails APIs.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```ruby
8
- gem "keycloak-api-rails", "0.11.1"
8
+ gem "keycloak-api-rails", "0.12.0"
9
9
  ```
10
10
 
11
11
  ## Token validation
12
12
 
13
- Tokens send (through query strings or Authorization headers) to this Railtie Middleware are validated against a Keycloak public key. This public key is downloaded every day by default (this interval can be changed through `public_key_cache_ttl`).
13
+ Tokens sent (through query strings or Authorization headers) are validated against a Keycloak public key. This public key is downloaded every day by default (this interval can be changed through `public_key_cache_ttl`).
14
14
 
15
15
  ## Pass token to the API
16
16
 
@@ -21,6 +21,20 @@ Tokens send (through query strings or Authorization headers) to this Railtie Mid
21
21
 
22
22
  _If both method are used at the same time, The query string as a higher priority when reading given tokens._
23
23
 
24
+ ## Opt-in vs. Opt-out validation
25
+
26
+ By default, Keycloak-api-rails installs as a Rack Middleware. It processes all requests before any application logic. URIs/Paths can be excluded (opted-out) from this validation using the 'skip_paths' config option
27
+
28
+ Alternatively, it can be configured to `opt-in` to validation. In this case, no Rack middleware is used, and controllers can request (opt-in) by including the module `Keycloak::authentication` and calling `keycloak_authenticate`, for example in a `before_action`, like so:
29
+
30
+ ```ruby
31
+ class MyApiController < ActionController::Base
32
+ include Keycloak::Authentication
33
+
34
+ before_action :keycloak_authenticate
35
+ end
36
+ ```
37
+
24
38
  ## When a token is validated
25
39
 
26
40
  In Rails controller, the request `env` variables has two more properties:
@@ -39,6 +53,7 @@ All options have a default value. However, all of them can be changed in your in
39
53
  | `realm_id` | `nil`| String | Required | Realm's name (not id, actually) | `master` |
40
54
  | `logger` | `Logger.new(STDOUT)`| Logger | Optional | The logger used by `keycloak-api-rails` | `Rails.logger` | 
41
55
  | `skip_paths` | `{}`| Hash of methods and paths regexp | Optional | Paths whose the token must not be validatefd | `{ get: [/^\/health\/.+/] }`| 
56
+ | `opt_in` | `false` | Boolean | Optional | When true, All requests will be validated (excluding requests matching `skip_paths`). When false, validation must be explicitly requested | `true`
42
57
  | `token_expiration_tolerance_in_seconds` | `10`| Logger | Optional | Number of seconds a token can expire before being rejected by the API. | `15` | 
43
58
  | `public_key_cache_ttl` | `86400`| Integer | Optional | Amount of time, in seconds, specifying maximum interval between two requests to {project_name} to retrieve new public keys. It is 86400 seconds (1 day) by default. At least once per this configured interval (1 day by default) will be new public key always downloaded. | `Rails.logger` | 
44
59
  | `custom_attributes` | `[]`| Array Of String | Optional | List of token attributes to read from each token and to add to their http request env | `["originalFirstName", "originalLastName"]` | 
@@ -59,6 +74,19 @@ Keycloak.configure do |config|
59
74
  end
60
75
  ```
61
76
 
77
+ Or using opt-in configuration:
78
+
79
+ ```ruby
80
+ Keycloak.configure do |config|
81
+ config.server_url = ENV["KEYCLOAK_SERVER_URL"]
82
+ config.realm_id = ENV["KEYCLOAK_REALM_ID"]
83
+ config.logger = Rails.logger
84
+ config.opt_in = true
85
+ end
86
+ ```
87
+
88
+ When using `opt-in` is true, `skip_paths` is not used.
89
+
62
90
  ## Use cases
63
91
 
64
92
  Once this gem is configured in your Rails project, you can read, validate and use tokens in your controllers.
@@ -77,6 +105,24 @@ class AuthenticatedController < ApplicationController
77
105
  end
78
106
  ```
79
107
 
108
+ Or if using opt-in mode, the controller can request validation conditionally:
109
+ ```ruby
110
+ class MostlyAuthenticatedController < ApplicationController
111
+ include Keycloak::Authentication
112
+
113
+ before_action :keycloak_authenticate, only: show
114
+
115
+ def show
116
+ keycloak_id = Keycloak::Helper.current_user_id(request.env)
117
+ User.active.find_by(keycloak_id: keycloak_id)
118
+ end
119
+
120
+ def index
121
+ # unauthenticated
122
+ end
123
+ end
124
+ ```
125
+
80
126
  ### Roles
81
127
 
82
128
  `Keycloak::Helper.current_user_roles` can be use against a Rails request to read user's roles.
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.add_dependency "rails", ">= 4.2"
19
19
  spec.add_dependency "json-jwt", ">= 1.11.0"
20
20
 
21
- spec.add_development_dependency "rspec", "3.7.0"
22
- spec.add_development_dependency "timecop", "0.9.1"
23
- spec.add_development_dependency "byebug", "9.1.0"
21
+ spec.add_development_dependency "rspec", "3.12.0"
22
+ spec.add_development_dependency "timecop", "0.9.6"
23
+ spec.add_development_dependency "byebug", "11.1.3"
24
24
  end
@@ -0,0 +1,57 @@
1
+ module Keycloak
2
+ module Authentication
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ if respond_to?(:helper_method)
7
+ helper_method :keycloak_authenticate
8
+ end
9
+ end
10
+
11
+ protected
12
+
13
+ def keycloak_authenticate
14
+
15
+ env = request.env
16
+ method = env["REQUEST_METHOD"]
17
+ path = env["PATH_INFO"]
18
+ uri = env["REQUEST_URI"]
19
+
20
+ logger.debug("Start authentication for #{method} : #{path}")
21
+ token = service.read_token(uri, env)
22
+ decoded_token = service.decode_and_verify(token)
23
+ authentication_succeeded(env, decoded_token)
24
+
25
+ rescue TokenError => e
26
+ authentication_failed(e.message)
27
+ end
28
+
29
+ def authentication_failed(message)
30
+ logger.info(message)
31
+ [401, {"Content-Type" => "application/json"}, [ { error: message }.to_json]]
32
+ end
33
+
34
+ def authentication_succeeded(env, decoded_token)
35
+ Helper.assign_current_user_id(env, decoded_token)
36
+ Helper.assign_current_authorized_party(env, decoded_token)
37
+ Helper.assign_current_user_email(env, decoded_token)
38
+ Helper.assign_current_user_locale(env, decoded_token)
39
+ Helper.assign_current_user_custom_attributes(env, decoded_token, config.custom_attributes)
40
+ Helper.assign_realm_roles(env, decoded_token)
41
+ Helper.assign_resource_roles(env, decoded_token)
42
+ Helper.assign_keycloak_token(env, decoded_token)
43
+ end
44
+
45
+ def service
46
+ Keycloak.service
47
+ end
48
+
49
+ def logger
50
+ Keycloak.logger
51
+ end
52
+
53
+ def config
54
+ Keycloak.config
55
+ end
56
+ end
57
+ end
@@ -4,6 +4,7 @@ module Keycloak
4
4
  config_accessor :server_url
5
5
  config_accessor :realm_id
6
6
  config_accessor :skip_paths
7
+ config_accessor :opt_in
7
8
  config_accessor :token_expiration_tolerance_in_seconds
8
9
  config_accessor :public_key_cache_ttl
9
10
  config_accessor :custom_attributes
@@ -10,7 +10,7 @@ module Keycloak
10
10
  path = env["PATH_INFO"]
11
11
  uri = env["REQUEST_URI"]
12
12
 
13
- if service.need_authentication?(method, path, env)
13
+ if service.need_middleware_authentication?(method, path, env)
14
14
  logger.debug("Start authentication for #{method} : #{path}")
15
15
  token = service.read_token(uri, env)
16
16
  decoded_token = service.decode_and_verify(token)
@@ -4,6 +4,7 @@ module Keycloak
4
4
  def initialize(key_resolver)
5
5
  @key_resolver = key_resolver
6
6
  @skip_paths = Keycloak.config.skip_paths
7
+ @opt_in = Keycloak.config.opt_in
7
8
  @logger = Keycloak.config.logger
8
9
  @token_expiration_tolerance_in_seconds = Keycloak.config.token_expiration_tolerance_in_seconds
9
10
  end
@@ -34,8 +35,8 @@ module Keycloak
34
35
  Helper.read_token_from_query_string(uri) || Helper.read_token_from_headers(headers)
35
36
  end
36
37
 
37
- def need_authentication?(method, path, headers)
38
- !should_skip?(method, path) && !is_preflight?(method, headers)
38
+ def need_middleware_authentication?(method, path, headers)
39
+ !is_preflight?(method, headers) && (!@opt_in && !should_skip?(method, path))
39
40
  end
40
41
 
41
42
  private
@@ -1,3 +1,3 @@
1
1
  module Keycloak
2
- VERSION = "0.11.1"
2
+ VERSION = "0.12.0"
3
3
  end
@@ -4,6 +4,7 @@ require "uri"
4
4
  require "date"
5
5
  require "net/http"
6
6
 
7
+ require_relative "keycloak-api-rails/authentication"
7
8
  require_relative "keycloak-api-rails/configuration"
8
9
  require_relative "keycloak-api-rails/http_client"
9
10
  require_relative "keycloak-api-rails/token_error"
@@ -46,6 +47,7 @@ module Keycloak
46
47
  config.realm_id = nil
47
48
  config.logger = ::Logger.new(STDOUT)
48
49
  config.skip_paths = {}
50
+ config.opt_in = false
49
51
  config.token_expiration_tolerance_in_seconds = 10
50
52
  config.public_key_cache_ttl = 86400
51
53
  config.custom_attributes = []
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+
3
+ describe Keycloak::Authentication do
4
+ class ExampleController < ActionController::Base
5
+ include Keycloak::Authentication
6
+ # Mark protected methods public so they may be called in tests
7
+ public(*Keycloak::Authentication.protected_instance_methods)
8
+ end
9
+
10
+ let(:controller) { ExampleController.new }
11
+ let(:token) { 'keycloak_valid_token'}
12
+ let(:headers) do
13
+ {
14
+ 'REQUEST_METHOD' => :get,
15
+ 'REQUEST_URI' => 'http://www.an-url.io',
16
+ 'HTTP_AUTHORIZATION' => "Bearer #{token}"
17
+ }
18
+ end
19
+
20
+ describe "#keycloak_authenticate" do
21
+ before do
22
+ # Mock request object because we aren't using real request spec
23
+ allow(controller).to receive(:request).and_return(double("request", env: headers ))
24
+ end
25
+
26
+ it "it authenticates with request header" do
27
+ expect_any_instance_of(Keycloak::Service).to receive(:decode_and_verify).with(token).and_return("A User")
28
+ expect(controller).to receive(:authentication_succeeded)
29
+ controller.keycloak_authenticate
30
+ end
31
+ end
32
+ end
@@ -103,7 +103,7 @@ RSpec.describe Keycloak::Service do
103
103
  end
104
104
  end
105
105
 
106
- describe "#need_authentication?" do
106
+ describe "#need_middleware_authentication?" do
107
107
 
108
108
  let(:method) { nil }
109
109
  let(:path) { nil }
@@ -115,7 +115,7 @@ RSpec.describe Keycloak::Service do
115
115
  post: [/^\/skip/],
116
116
  get: [/^\/skip/]
117
117
  }
118
- @result = service.need_authentication?(method, path, headers)
118
+ @result = service.need_middleware_authentication?(method, path, headers)
119
119
  end
120
120
 
121
121
  context "when method is nil" do
@@ -175,6 +175,18 @@ RSpec.describe Keycloak::Service do
175
175
  expect(@result).to be false
176
176
  end
177
177
  end
178
+
179
+ context "when configured as opt_in" do
180
+ before do
181
+ Keycloak.config.opt_in = true
182
+ service2 = Keycloak::Service.new(key_resolver)
183
+ @result = service2.need_middleware_authentication?(method, path, headers)
184
+ end
185
+
186
+ it "should return false" do
187
+ expect(@result).to be false
188
+ end
189
+ end
178
190
  end
179
191
 
180
192
  describe "#read_token" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keycloak-api-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorent Lempereur
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-27 00:00:00.000000000 Z
11
+ date: 2023-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -44,42 +44,42 @@ dependencies:
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 3.7.0
47
+ version: 3.12.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 3.7.0
54
+ version: 3.12.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: timecop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 0.9.1
61
+ version: 0.9.6
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 0.9.1
68
+ version: 0.9.6
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: byebug
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 9.1.0
75
+ version: 11.1.3
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 9.1.0
82
+ version: 11.1.3
83
83
  description: Rails middleware that validates Authorization token emitted by Keycloak
84
84
  email:
85
85
  - lorent.lempereur.dev@gmail.com
@@ -97,6 +97,7 @@ files:
97
97
  - README.md
98
98
  - keycloak-api-rails.gemspec
99
99
  - lib/keycloak-api-rails.rb
100
+ - lib/keycloak-api-rails/authentication.rb
100
101
  - lib/keycloak-api-rails/configuration.rb
101
102
  - lib/keycloak-api-rails/helper.rb
102
103
  - lib/keycloak-api-rails/http_client.rb
@@ -107,6 +108,7 @@ files:
107
108
  - lib/keycloak-api-rails/service.rb
108
109
  - lib/keycloak-api-rails/token_error.rb
109
110
  - lib/keycloak-api-rails/version.rb
111
+ - spec/keycloak-api-rails/authentication_spec.rb
110
112
  - spec/keycloak-api-rails/helper_spec.rb
111
113
  - spec/keycloak-api-rails/public_key_cached_resolver_spec.rb
112
114
  - spec/keycloak-api-rails/service_spec.rb
@@ -133,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
135
  - !ruby/object:Gem::Version
134
136
  version: '0'
135
137
  requirements: []
136
- rubygems_version: 3.0.3
138
+ rubygems_version: 3.0.3.1
137
139
  signing_key:
138
140
  specification_version: 4
139
141
  summary: Rails middleware that validates Authorization token emitted by Keycloak