keycloak-api-rails 0.12.4 → 1.0.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 +4 -4
- data/.github/workflows/ci.yml +28 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +150 -134
- data/README.md +15 -15
- data/keycloak-api-rails.gemspec +4 -4
- data/lib/keycloak-api-rails/authentication.rb +6 -6
- data/lib/keycloak-api-rails/configuration.rb +1 -1
- data/lib/keycloak-api-rails/helper.rb +1 -1
- data/lib/keycloak-api-rails/http_client.rb +2 -2
- data/lib/keycloak-api-rails/middleware.rb +4 -4
- data/lib/keycloak-api-rails/public_key_cached_resolver.rb +1 -1
- data/lib/keycloak-api-rails/public_key_resolver.rb +1 -1
- data/lib/keycloak-api-rails/railtie.rb +2 -2
- data/lib/keycloak-api-rails/service.rb +5 -5
- data/lib/keycloak-api-rails/version.rb +2 -2
- data/lib/keycloak-api-rails.rb +4 -4
- data/spec/keycloak-api-rails/authentication_spec.rb +4 -4
- data/spec/keycloak-api-rails/helper_spec.rb +2 -2
- data/spec/keycloak-api-rails/public_key_cached_resolver_spec.rb +3 -3
- data/spec/keycloak-api-rails/service_spec.rb +7 -7
- data/spec/support/public_key_cached_resolver_stub.rb +1 -1
- data/spec/support/public_key_resolver_stub.rb +1 -1
- metadata +13 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c8848fb5696ab7e2962d8491b2df8e17c1bc88a3f08bb4b328b96e872b5858de
|
|
4
|
+
data.tar.gz: 9b2f8541d0a2e26f59cec67fcd6573e34c898db12a769335faa701a9c15b66be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e7f9ca820ba2eb32fca2bcbf72c9a19e70ed2bc62e95f6f059fcd848f7aafbb40847017a012a93ff7b5f55fe029b4e7cd353f2376eb90c7a5c0b11f4fac4e310
|
|
7
|
+
data.tar.gz: 57a3a77dec4b4daeb697ee3b3d8f4ed4ad349c2b68e60ca7001e46be2809a358c1e24e6dd1a3e2d31270be9e0e8daaac0176511e7009ce9cca4ea591e8040ba7
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Ruby
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "main" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ "main" ]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
ruby-version: ['3.2']
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- name: Set up Ruby
|
|
23
|
+
uses: ruby/setup-ruby@v1
|
|
24
|
+
with:
|
|
25
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
26
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
27
|
+
- name: Run tests
|
|
28
|
+
run: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ 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
|
+
## [1.0.0] - 2025-06-20
|
|
9
|
+
|
|
10
|
+
* *[BREAKING CHANGE!]* Rename top-level module from `Keycloak` to `KeycloakApiRails` to avoid conflicts with other gems. (thanks to @eilers)
|
|
11
|
+
* *Migration: Please do a global find and replace of `Keycloak.` to `KeycloakApiRails.` in your application.*
|
|
12
|
+
* Automate tests on Github Actions
|
|
13
|
+
* Dependencies: Upgrade test dependencies: timecop, rspec and byebug.
|
|
14
|
+
|
|
8
15
|
## [0.12.4] - 2024-06-20
|
|
9
16
|
|
|
10
17
|
* Log error when fetching the public keys from Keycloak
|
data/Gemfile.lock
CHANGED
|
@@ -1,228 +1,244 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
keycloak-api-rails (0.
|
|
4
|
+
keycloak-api-rails (1.0.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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
action_text-trix (2.1.15)
|
|
12
|
+
railties
|
|
13
|
+
actioncable (8.1.1)
|
|
14
|
+
actionpack (= 8.1.1)
|
|
15
|
+
activesupport (= 8.1.1)
|
|
14
16
|
nio4r (~> 2.0)
|
|
15
17
|
websocket-driver (>= 0.6.1)
|
|
16
18
|
zeitwerk (~> 2.6)
|
|
17
|
-
actionmailbox (
|
|
18
|
-
actionpack (=
|
|
19
|
-
activejob (=
|
|
20
|
-
activerecord (=
|
|
21
|
-
activestorage (=
|
|
22
|
-
activesupport (=
|
|
23
|
-
mail (>= 2.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
activejob (= 7.1.3.4)
|
|
31
|
-
activesupport (= 7.1.3.4)
|
|
32
|
-
mail (~> 2.5, >= 2.5.4)
|
|
33
|
-
net-imap
|
|
34
|
-
net-pop
|
|
35
|
-
net-smtp
|
|
19
|
+
actionmailbox (8.1.1)
|
|
20
|
+
actionpack (= 8.1.1)
|
|
21
|
+
activejob (= 8.1.1)
|
|
22
|
+
activerecord (= 8.1.1)
|
|
23
|
+
activestorage (= 8.1.1)
|
|
24
|
+
activesupport (= 8.1.1)
|
|
25
|
+
mail (>= 2.8.0)
|
|
26
|
+
actionmailer (8.1.1)
|
|
27
|
+
actionpack (= 8.1.1)
|
|
28
|
+
actionview (= 8.1.1)
|
|
29
|
+
activejob (= 8.1.1)
|
|
30
|
+
activesupport (= 8.1.1)
|
|
31
|
+
mail (>= 2.8.0)
|
|
36
32
|
rails-dom-testing (~> 2.2)
|
|
37
|
-
actionpack (
|
|
38
|
-
actionview (=
|
|
39
|
-
activesupport (=
|
|
33
|
+
actionpack (8.1.1)
|
|
34
|
+
actionview (= 8.1.1)
|
|
35
|
+
activesupport (= 8.1.1)
|
|
40
36
|
nokogiri (>= 1.8.5)
|
|
41
|
-
racc
|
|
42
37
|
rack (>= 2.2.4)
|
|
43
38
|
rack-session (>= 1.0.1)
|
|
44
39
|
rack-test (>= 0.6.3)
|
|
45
40
|
rails-dom-testing (~> 2.2)
|
|
46
41
|
rails-html-sanitizer (~> 1.6)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
useragent (~> 0.16)
|
|
43
|
+
actiontext (8.1.1)
|
|
44
|
+
action_text-trix (~> 2.1.15)
|
|
45
|
+
actionpack (= 8.1.1)
|
|
46
|
+
activerecord (= 8.1.1)
|
|
47
|
+
activestorage (= 8.1.1)
|
|
48
|
+
activesupport (= 8.1.1)
|
|
52
49
|
globalid (>= 0.6.0)
|
|
53
50
|
nokogiri (>= 1.8.5)
|
|
54
|
-
actionview (
|
|
55
|
-
activesupport (=
|
|
51
|
+
actionview (8.1.1)
|
|
52
|
+
activesupport (= 8.1.1)
|
|
56
53
|
builder (~> 3.1)
|
|
57
54
|
erubi (~> 1.11)
|
|
58
55
|
rails-dom-testing (~> 2.2)
|
|
59
56
|
rails-html-sanitizer (~> 1.6)
|
|
60
|
-
activejob (
|
|
61
|
-
activesupport (=
|
|
57
|
+
activejob (8.1.1)
|
|
58
|
+
activesupport (= 8.1.1)
|
|
62
59
|
globalid (>= 0.3.6)
|
|
63
|
-
activemodel (
|
|
64
|
-
activesupport (=
|
|
65
|
-
activerecord (
|
|
66
|
-
activemodel (=
|
|
67
|
-
activesupport (=
|
|
60
|
+
activemodel (8.1.1)
|
|
61
|
+
activesupport (= 8.1.1)
|
|
62
|
+
activerecord (8.1.1)
|
|
63
|
+
activemodel (= 8.1.1)
|
|
64
|
+
activesupport (= 8.1.1)
|
|
68
65
|
timeout (>= 0.4.0)
|
|
69
|
-
activestorage (
|
|
70
|
-
actionpack (=
|
|
71
|
-
activejob (=
|
|
72
|
-
activerecord (=
|
|
73
|
-
activesupport (=
|
|
66
|
+
activestorage (8.1.1)
|
|
67
|
+
actionpack (= 8.1.1)
|
|
68
|
+
activejob (= 8.1.1)
|
|
69
|
+
activerecord (= 8.1.1)
|
|
70
|
+
activesupport (= 8.1.1)
|
|
74
71
|
marcel (~> 1.0)
|
|
75
|
-
activesupport (
|
|
72
|
+
activesupport (8.1.1)
|
|
76
73
|
base64
|
|
77
74
|
bigdecimal
|
|
78
|
-
concurrent-ruby (~> 1.0, >= 1.
|
|
75
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
79
76
|
connection_pool (>= 2.2.5)
|
|
80
77
|
drb
|
|
81
78
|
i18n (>= 1.6, < 2)
|
|
79
|
+
json
|
|
80
|
+
logger (>= 1.4.2)
|
|
82
81
|
minitest (>= 5.1)
|
|
83
|
-
|
|
84
|
-
tzinfo (~> 2.0)
|
|
82
|
+
securerandom (>= 0.3)
|
|
83
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
84
|
+
uri (>= 0.13.1)
|
|
85
85
|
aes_key_wrap (1.1.0)
|
|
86
|
-
base64 (0.
|
|
87
|
-
bigdecimal (3.1
|
|
88
|
-
bindata (2.5.
|
|
86
|
+
base64 (0.3.0)
|
|
87
|
+
bigdecimal (3.3.1)
|
|
88
|
+
bindata (2.5.1)
|
|
89
89
|
builder (3.3.0)
|
|
90
|
-
byebug (
|
|
91
|
-
concurrent-ruby (1.3.
|
|
92
|
-
connection_pool (
|
|
90
|
+
byebug (12.0.0)
|
|
91
|
+
concurrent-ruby (1.3.5)
|
|
92
|
+
connection_pool (3.0.2)
|
|
93
93
|
crass (1.0.6)
|
|
94
|
-
date (3.
|
|
95
|
-
diff-lcs (1.
|
|
96
|
-
drb (2.2.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
94
|
+
date (3.5.1)
|
|
95
|
+
diff-lcs (1.6.2)
|
|
96
|
+
drb (2.2.3)
|
|
97
|
+
erb (6.0.0)
|
|
98
|
+
erubi (1.13.1)
|
|
99
|
+
faraday (2.14.0)
|
|
100
|
+
faraday-net_http (>= 2.0, < 3.5)
|
|
101
|
+
json
|
|
102
|
+
logger
|
|
103
|
+
faraday-follow_redirects (0.4.0)
|
|
101
104
|
faraday (>= 1, < 3)
|
|
102
|
-
faraday-net_http (3.
|
|
103
|
-
net-http
|
|
104
|
-
globalid (1.
|
|
105
|
+
faraday-net_http (3.4.2)
|
|
106
|
+
net-http (~> 0.5)
|
|
107
|
+
globalid (1.3.0)
|
|
105
108
|
activesupport (>= 6.1)
|
|
106
|
-
i18n (1.14.
|
|
109
|
+
i18n (1.14.7)
|
|
107
110
|
concurrent-ruby (~> 1.0)
|
|
108
|
-
io-console (0.
|
|
109
|
-
irb (1.
|
|
111
|
+
io-console (0.8.1)
|
|
112
|
+
irb (1.15.3)
|
|
113
|
+
pp (>= 0.6.0)
|
|
110
114
|
rdoc (>= 4.0.0)
|
|
111
115
|
reline (>= 0.4.2)
|
|
112
|
-
json
|
|
116
|
+
json (2.17.1)
|
|
117
|
+
json-jwt (1.17.0)
|
|
113
118
|
activesupport (>= 4.2)
|
|
114
119
|
aes_key_wrap
|
|
115
120
|
base64
|
|
116
121
|
bindata
|
|
117
122
|
faraday (~> 2.0)
|
|
118
123
|
faraday-follow_redirects
|
|
119
|
-
|
|
124
|
+
logger (1.7.0)
|
|
125
|
+
loofah (2.24.1)
|
|
120
126
|
crass (~> 1.0.2)
|
|
121
127
|
nokogiri (>= 1.12.0)
|
|
122
|
-
mail (2.
|
|
128
|
+
mail (2.9.0)
|
|
129
|
+
logger
|
|
123
130
|
mini_mime (>= 0.1.1)
|
|
124
131
|
net-imap
|
|
125
132
|
net-pop
|
|
126
133
|
net-smtp
|
|
127
|
-
marcel (1.0
|
|
134
|
+
marcel (1.1.0)
|
|
128
135
|
mini_mime (1.1.5)
|
|
129
|
-
mini_portile2 (2.8.
|
|
130
|
-
minitest (5.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
net-imap (0.4.13)
|
|
136
|
+
mini_portile2 (2.8.9)
|
|
137
|
+
minitest (5.26.2)
|
|
138
|
+
net-http (0.8.0)
|
|
139
|
+
uri (>= 0.11.1)
|
|
140
|
+
net-imap (0.5.12)
|
|
135
141
|
date
|
|
136
142
|
net-protocol
|
|
137
143
|
net-pop (0.1.2)
|
|
138
144
|
net-protocol
|
|
139
145
|
net-protocol (0.2.2)
|
|
140
146
|
timeout
|
|
141
|
-
net-smtp (0.5.
|
|
147
|
+
net-smtp (0.5.1)
|
|
142
148
|
net-protocol
|
|
143
|
-
nio4r (2.7.
|
|
144
|
-
nokogiri (1.
|
|
149
|
+
nio4r (2.7.5)
|
|
150
|
+
nokogiri (1.18.10)
|
|
145
151
|
mini_portile2 (~> 2.8.2)
|
|
146
152
|
racc (~> 1.4)
|
|
147
|
-
|
|
153
|
+
pp (0.6.3)
|
|
154
|
+
prettyprint
|
|
155
|
+
prettyprint (0.2.0)
|
|
156
|
+
psych (5.3.0)
|
|
157
|
+
date
|
|
148
158
|
stringio
|
|
149
|
-
racc (1.8.
|
|
150
|
-
rack (3.
|
|
151
|
-
rack-session (2.
|
|
159
|
+
racc (1.8.1)
|
|
160
|
+
rack (3.2.4)
|
|
161
|
+
rack-session (2.1.1)
|
|
162
|
+
base64 (>= 0.1.0)
|
|
152
163
|
rack (>= 3.0.0)
|
|
153
|
-
rack-test (2.
|
|
164
|
+
rack-test (2.2.0)
|
|
154
165
|
rack (>= 1.3)
|
|
155
|
-
rackup (2.1
|
|
166
|
+
rackup (2.3.1)
|
|
156
167
|
rack (>= 3)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
activesupport (= 7.1.3.4)
|
|
168
|
+
rails (8.1.1)
|
|
169
|
+
actioncable (= 8.1.1)
|
|
170
|
+
actionmailbox (= 8.1.1)
|
|
171
|
+
actionmailer (= 8.1.1)
|
|
172
|
+
actionpack (= 8.1.1)
|
|
173
|
+
actiontext (= 8.1.1)
|
|
174
|
+
actionview (= 8.1.1)
|
|
175
|
+
activejob (= 8.1.1)
|
|
176
|
+
activemodel (= 8.1.1)
|
|
177
|
+
activerecord (= 8.1.1)
|
|
178
|
+
activestorage (= 8.1.1)
|
|
179
|
+
activesupport (= 8.1.1)
|
|
170
180
|
bundler (>= 1.15.0)
|
|
171
|
-
railties (=
|
|
172
|
-
rails-dom-testing (2.
|
|
181
|
+
railties (= 8.1.1)
|
|
182
|
+
rails-dom-testing (2.3.0)
|
|
173
183
|
activesupport (>= 5.0.0)
|
|
174
184
|
minitest
|
|
175
185
|
nokogiri (>= 1.6)
|
|
176
|
-
rails-html-sanitizer (1.6.
|
|
186
|
+
rails-html-sanitizer (1.6.2)
|
|
177
187
|
loofah (~> 2.21)
|
|
178
|
-
nokogiri (
|
|
179
|
-
railties (
|
|
180
|
-
actionpack (=
|
|
181
|
-
activesupport (=
|
|
182
|
-
irb
|
|
188
|
+
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
|
189
|
+
railties (8.1.1)
|
|
190
|
+
actionpack (= 8.1.1)
|
|
191
|
+
activesupport (= 8.1.1)
|
|
192
|
+
irb (~> 1.13)
|
|
183
193
|
rackup (>= 1.0.0)
|
|
184
194
|
rake (>= 12.2)
|
|
185
195
|
thor (~> 1.0, >= 1.2.2)
|
|
196
|
+
tsort (>= 0.2)
|
|
186
197
|
zeitwerk (~> 2.6)
|
|
187
|
-
rake (13.
|
|
188
|
-
rdoc (6.
|
|
198
|
+
rake (13.3.1)
|
|
199
|
+
rdoc (6.17.0)
|
|
200
|
+
erb
|
|
189
201
|
psych (>= 4.0.0)
|
|
190
|
-
|
|
202
|
+
tsort
|
|
203
|
+
reline (0.6.3)
|
|
191
204
|
io-console (~> 0.5)
|
|
192
|
-
rspec (3.
|
|
193
|
-
rspec-core (~> 3.
|
|
194
|
-
rspec-expectations (~> 3.
|
|
195
|
-
rspec-mocks (~> 3.
|
|
196
|
-
rspec-core (3.
|
|
197
|
-
rspec-support (~> 3.
|
|
198
|
-
rspec-expectations (3.
|
|
205
|
+
rspec (3.13.2)
|
|
206
|
+
rspec-core (~> 3.13.0)
|
|
207
|
+
rspec-expectations (~> 3.13.0)
|
|
208
|
+
rspec-mocks (~> 3.13.0)
|
|
209
|
+
rspec-core (3.13.6)
|
|
210
|
+
rspec-support (~> 3.13.0)
|
|
211
|
+
rspec-expectations (3.13.5)
|
|
199
212
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
200
|
-
rspec-support (~> 3.
|
|
201
|
-
rspec-mocks (3.
|
|
213
|
+
rspec-support (~> 3.13.0)
|
|
214
|
+
rspec-mocks (3.13.7)
|
|
202
215
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
203
|
-
rspec-support (~> 3.
|
|
204
|
-
rspec-support (3.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
216
|
+
rspec-support (~> 3.13.0)
|
|
217
|
+
rspec-support (3.13.6)
|
|
218
|
+
securerandom (0.4.1)
|
|
219
|
+
stringio (3.1.9)
|
|
220
|
+
thor (1.4.0)
|
|
221
|
+
timecop (0.9.10)
|
|
222
|
+
timeout (0.5.0)
|
|
223
|
+
tsort (0.2.0)
|
|
209
224
|
tzinfo (2.0.6)
|
|
210
225
|
concurrent-ruby (~> 1.0)
|
|
211
|
-
uri (
|
|
212
|
-
|
|
213
|
-
websocket-driver (0.
|
|
226
|
+
uri (1.1.1)
|
|
227
|
+
useragent (0.16.11)
|
|
228
|
+
websocket-driver (0.8.0)
|
|
229
|
+
base64
|
|
214
230
|
websocket-extensions (>= 0.1.0)
|
|
215
231
|
websocket-extensions (0.1.5)
|
|
216
|
-
zeitwerk (2.
|
|
232
|
+
zeitwerk (2.7.3)
|
|
217
233
|
|
|
218
234
|
PLATFORMS
|
|
219
235
|
ruby
|
|
220
236
|
|
|
221
237
|
DEPENDENCIES
|
|
222
|
-
byebug (=
|
|
238
|
+
byebug (= 12.0.0)
|
|
223
239
|
keycloak-api-rails!
|
|
224
|
-
rspec (= 3.
|
|
225
|
-
timecop (= 0.9.
|
|
240
|
+
rspec (= 3.13.2)
|
|
241
|
+
timecop (= 0.9.10)
|
|
226
242
|
|
|
227
243
|
BUNDLED WITH
|
|
228
244
|
2.4.13
|
data/README.md
CHANGED
|
@@ -5,7 +5,7 @@ This gem validates Keycloak JWT token for Ruby On Rails APIs.
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```ruby
|
|
8
|
-
gem "keycloak-api-rails", "0.
|
|
8
|
+
gem "keycloak-api-rails", "1.0.0"
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Token validation
|
|
@@ -25,11 +25,11 @@ _If both method are used at the same time, The query string as a higher priority
|
|
|
25
25
|
|
|
26
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
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 `
|
|
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 `KeycloakApiRails::authentication` and calling `keycloak_authenticate`, for example in a `before_action`, like so:
|
|
29
29
|
|
|
30
30
|
```ruby
|
|
31
31
|
class MyApiController < ActionController::Base
|
|
32
|
-
include
|
|
32
|
+
include KeycloakApiRails::Authentication
|
|
33
33
|
|
|
34
34
|
before_action :keycloak_authenticate
|
|
35
35
|
end
|
|
@@ -41,7 +41,7 @@ In Rails controller, the request `env` variables has two more properties:
|
|
|
41
41
|
* `keycloak:keycloak_id`
|
|
42
42
|
* `keycloak:roles`
|
|
43
43
|
|
|
44
|
-
They can be accessed using `
|
|
44
|
+
They can be accessed using `KeycloakApiRails::Helper` methods.
|
|
45
45
|
|
|
46
46
|
## Overall configuration options
|
|
47
47
|
|
|
@@ -93,13 +93,13 @@ Once this gem is configured in your Rails project, you can read, validate and us
|
|
|
93
93
|
|
|
94
94
|
### Keycloak Id
|
|
95
95
|
|
|
96
|
-
If you identify users using their Keycloak Id, this value can be read from your controllers using `
|
|
96
|
+
If you identify users using their Keycloak Id, this value can be read from your controllers using `KeycloakApiRails::Helper.current_user_id(request.env)`.
|
|
97
97
|
|
|
98
98
|
```ruby
|
|
99
99
|
class AuthenticatedController < ApplicationController
|
|
100
100
|
|
|
101
101
|
def user
|
|
102
|
-
keycloak_id =
|
|
102
|
+
keycloak_id = KeycloakApiRails::Helper.current_user_id(request.env)
|
|
103
103
|
User.active.find_by(keycloak_id: keycloak_id)
|
|
104
104
|
end
|
|
105
105
|
end
|
|
@@ -108,12 +108,12 @@ end
|
|
|
108
108
|
Or if using opt-in mode, the controller can request validation conditionally:
|
|
109
109
|
```ruby
|
|
110
110
|
class MostlyAuthenticatedController < ApplicationController
|
|
111
|
-
include
|
|
111
|
+
include KeycloakApiRails::Authentication
|
|
112
112
|
|
|
113
113
|
before_action :keycloak_authenticate, only: show
|
|
114
114
|
|
|
115
115
|
def show
|
|
116
|
-
keycloak_id =
|
|
116
|
+
keycloak_id = KeycloakApiRails::Helper.current_user_id(request.env)
|
|
117
117
|
User.active.find_by(keycloak_id: keycloak_id)
|
|
118
118
|
end
|
|
119
119
|
|
|
@@ -125,7 +125,7 @@ end
|
|
|
125
125
|
|
|
126
126
|
### Roles
|
|
127
127
|
|
|
128
|
-
`
|
|
128
|
+
`KeycloakApiRails::Helper.current_user_roles` can be use against a Rails request to read user's roles.
|
|
129
129
|
|
|
130
130
|
For example, a controller can require users to be administrator (considering you defined an `application-admin` role):
|
|
131
131
|
|
|
@@ -143,18 +143,18 @@ class AdminController < ApplicationController
|
|
|
143
143
|
private
|
|
144
144
|
|
|
145
145
|
def current_user_roles
|
|
146
|
-
|
|
146
|
+
KeycloakApiRails::Helper.current_user_roles(request.env)
|
|
147
147
|
end
|
|
148
148
|
end
|
|
149
149
|
```
|
|
150
150
|
|
|
151
151
|
### Create an URL where the token must be passed via query string
|
|
152
152
|
|
|
153
|
-
`
|
|
153
|
+
`KeycloakApiRails::Helper.create_url_with_token` method can be used to build an url from another, by adding a token as query string.
|
|
154
154
|
|
|
155
155
|
```ruby
|
|
156
156
|
def example
|
|
157
|
-
|
|
157
|
+
KeycloakApiRails::Helper.create_url_with_token("https://api.pouet.io/api/more-pouets", "myToken")
|
|
158
158
|
end
|
|
159
159
|
```
|
|
160
160
|
|
|
@@ -163,7 +163,7 @@ This should output `https://api.pouet.io/api/more-pouets?authorizationToken=myTo
|
|
|
163
163
|
|
|
164
164
|
### Accessing Keycloak Service
|
|
165
165
|
|
|
166
|
-
A lazy-loaded service
|
|
166
|
+
A lazy-loaded service KeycloakApiRails::Service can be accessed using `Keycloak.service`.
|
|
167
167
|
For instance, to read a provided token:
|
|
168
168
|
```ruby
|
|
169
169
|
class RenderTokenController < ApplicationController
|
|
@@ -216,8 +216,8 @@ From the `keycloak-rails-api` directory:
|
|
|
216
216
|
$ docker build . -t keycloak-rails-api:test
|
|
217
217
|
$ docker run -v `pwd`:/usr/src/app/ keycloak-rails-api:test bundle exec rspec spec
|
|
218
218
|
```
|
|
219
|
-
|
|
219
|
+
rspe
|
|
220
220
|
## Next developments
|
|
221
221
|
|
|
222
222
|
* Manage multiple realms
|
|
223
|
-
* Avoid duplicate code in
|
|
223
|
+
* Avoid duplicate code in KeycloakApiRails::Middleware and `KeycloakApiRails::Authentication`
|
data/keycloak-api-rails.gemspec
CHANGED
|
@@ -4,7 +4,7 @@ require "keycloak-api-rails/version"
|
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "keycloak-api-rails"
|
|
7
|
-
spec.version =
|
|
7
|
+
spec.version = KeycloakApiRails::VERSION
|
|
8
8
|
spec.authors = ["Lorent Lempereur"]
|
|
9
9
|
spec.email = ["lorent.lempereur.dev@gmail.com"]
|
|
10
10
|
spec.homepage = "https://github.com/looorent/keycloak-api-rails"
|
|
@@ -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.
|
|
22
|
-
spec.add_development_dependency "timecop", "0.9.
|
|
23
|
-
spec.add_development_dependency "byebug", "
|
|
21
|
+
spec.add_development_dependency "rspec", "3.13.2"
|
|
22
|
+
spec.add_development_dependency "timecop", "0.9.10"
|
|
23
|
+
spec.add_development_dependency "byebug", "12.0.0"
|
|
24
24
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module
|
|
1
|
+
module KeycloakApiRails
|
|
2
2
|
module Authentication
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
@@ -16,16 +16,16 @@ module Keycloak
|
|
|
16
16
|
path = env["PATH_INFO"]
|
|
17
17
|
uri = env["REQUEST_URI"]
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
token =
|
|
21
|
-
decoded_token =
|
|
19
|
+
KeycloakApiRails.logger.debug("Start authentication for #{method} : #{path}")
|
|
20
|
+
token = KeycloakApiRails.service.read_token(uri, env)
|
|
21
|
+
decoded_token = KeycloakApiRails.service.decode_and_verify(token)
|
|
22
22
|
authentication_succeeded(env, decoded_token)
|
|
23
23
|
rescue TokenError => e
|
|
24
24
|
authentication_failed(e.message)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def authentication_failed(message)
|
|
28
|
-
|
|
28
|
+
KeycloakApiRails.logger.info(message)
|
|
29
29
|
render status: :unauthorized, json: { error: message }
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -34,7 +34,7 @@ module Keycloak
|
|
|
34
34
|
Helper.assign_current_authorized_party(env, decoded_token)
|
|
35
35
|
Helper.assign_current_user_email(env, decoded_token)
|
|
36
36
|
Helper.assign_current_user_locale(env, decoded_token)
|
|
37
|
-
Helper.assign_current_user_custom_attributes(env, decoded_token,
|
|
37
|
+
Helper.assign_current_user_custom_attributes(env, decoded_token, KeycloakApiRails.config.custom_attributes)
|
|
38
38
|
Helper.assign_realm_roles(env, decoded_token)
|
|
39
39
|
Helper.assign_resource_roles(env, decoded_token)
|
|
40
40
|
Helper.assign_keycloak_token(env, decoded_token)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module
|
|
1
|
+
module KeycloakApiRails
|
|
2
2
|
class HTTPClient
|
|
3
3
|
def initialize(configuration, logger)
|
|
4
4
|
@server_url = configuration.server_url
|
|
@@ -20,7 +20,7 @@ module Keycloak
|
|
|
20
20
|
response.value
|
|
21
21
|
JSON.parse(response.body)
|
|
22
22
|
rescue
|
|
23
|
-
@logger.error("
|
|
23
|
+
@logger.error("KeycloakApiRails responded with an error when calling '#{path}'. Status #{response.code}. Payload: #{response.body}")
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module
|
|
1
|
+
module KeycloakApiRails
|
|
2
2
|
|
|
3
3
|
class Middleware
|
|
4
4
|
def initialize(app)
|
|
@@ -41,15 +41,15 @@ module Keycloak
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def service
|
|
44
|
-
|
|
44
|
+
KeycloakApiRails.service
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def logger
|
|
48
|
-
|
|
48
|
+
KeycloakApiRails.logger
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def config
|
|
52
|
-
|
|
52
|
+
KeycloakApiRails.config
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
module
|
|
1
|
+
module KeycloakApiRails
|
|
2
2
|
class Railtie < Rails::Railtie
|
|
3
3
|
railtie_name :keycloak_api_rails
|
|
4
4
|
|
|
5
5
|
initializer("keycloak.insert_middleware") do |app|
|
|
6
|
-
app.config.middleware.use(
|
|
6
|
+
app.config.middleware.use(KeycloakApiRails::Middleware)
|
|
7
7
|
end
|
|
8
8
|
end
|
|
9
9
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
module
|
|
1
|
+
module KeycloakApiRails
|
|
2
2
|
class Service
|
|
3
3
|
|
|
4
4
|
def initialize(key_resolver)
|
|
5
5
|
@key_resolver = key_resolver
|
|
6
|
-
@skip_paths =
|
|
7
|
-
@opt_in =
|
|
8
|
-
@logger =
|
|
9
|
-
@token_expiration_tolerance_in_seconds =
|
|
6
|
+
@skip_paths = KeycloakApiRails.config.skip_paths
|
|
7
|
+
@opt_in = KeycloakApiRails.config.opt_in
|
|
8
|
+
@logger = KeycloakApiRails.config.logger
|
|
9
|
+
@token_expiration_tolerance_in_seconds = KeycloakApiRails.config.token_expiration_tolerance_in_seconds
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def decode_and_verify(token)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module
|
|
2
|
-
VERSION = "0.
|
|
1
|
+
module KeycloakApiRails
|
|
2
|
+
VERSION = "1.0.0"
|
|
3
3
|
end
|
data/lib/keycloak-api-rails.rb
CHANGED
|
@@ -15,10 +15,10 @@ require_relative "keycloak-api-rails/service"
|
|
|
15
15
|
require_relative "keycloak-api-rails/middleware"
|
|
16
16
|
require_relative "keycloak-api-rails/railtie" if defined?(Rails)
|
|
17
17
|
|
|
18
|
-
module
|
|
18
|
+
module KeycloakApiRails
|
|
19
19
|
|
|
20
20
|
def self.configure
|
|
21
|
-
yield @configuration ||=
|
|
21
|
+
yield @configuration ||= KeycloakApiRails::Configuration.new
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def self.config
|
|
@@ -26,7 +26,7 @@ module Keycloak
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def self.http_client
|
|
29
|
-
@http_client ||=
|
|
29
|
+
@http_client ||= KeycloakApiRails::HTTPClient.new(config, logger)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def self.public_key_resolver
|
|
@@ -34,7 +34,7 @@ module Keycloak
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def self.service
|
|
37
|
-
@service ||=
|
|
37
|
+
@service ||= KeycloakApiRails::Service.new(public_key_resolver)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def self.logger
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
|
|
3
|
-
describe
|
|
3
|
+
describe KeycloakApiRails::Authentication do
|
|
4
4
|
class ExampleController < ActionController::Base
|
|
5
|
-
include
|
|
5
|
+
include KeycloakApiRails::Authentication
|
|
6
6
|
# Mark protected methods public so they may be called in tests
|
|
7
|
-
public(*
|
|
7
|
+
public(*KeycloakApiRails::Authentication.protected_instance_methods)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
let(:controller) { ExampleController.new }
|
|
@@ -24,7 +24,7 @@ describe Keycloak::Authentication do
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
it "it authenticates with request header" do
|
|
27
|
-
expect_any_instance_of(
|
|
27
|
+
expect_any_instance_of(KeycloakApiRails::Service).to receive(:decode_and_verify).with(token).and_return("A User")
|
|
28
28
|
expect(controller).to receive(:authentication_succeeded)
|
|
29
29
|
controller.keycloak_authenticate
|
|
30
30
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
RSpec.describe
|
|
1
|
+
RSpec.describe KeycloakApiRails::Helper do
|
|
2
2
|
describe "#create_url_with_token" do
|
|
3
3
|
|
|
4
4
|
let(:uri) { "http://www.an-url.io" }
|
|
5
5
|
let(:token) { "aToken" }
|
|
6
6
|
|
|
7
7
|
before(:each) do
|
|
8
|
-
@url_with_token =
|
|
8
|
+
@url_with_token = KeycloakApiRails::Helper.create_url_with_token(uri, token)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
context "when the uri has no query string yet" do
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
RSpec.describe
|
|
1
|
+
RSpec.describe KeycloakApiRails::Service do
|
|
2
2
|
|
|
3
3
|
let(:public_key_cache_ttl) { 86400 }
|
|
4
4
|
let(:server_url) { "whatever:8080" }
|
|
5
5
|
let(:realm_id) { "pouet" }
|
|
6
|
-
let!(:resolver) {
|
|
6
|
+
let!(:resolver) { KeycloakApiRails::PublicKeyCachedResolver.new(server_url, realm_id, public_key_cache_ttl) }
|
|
7
7
|
|
|
8
8
|
before(:each) do
|
|
9
|
-
resolver.instance_variable_set(:@resolver,
|
|
9
|
+
resolver.instance_variable_set(:@resolver, KeycloakApiRails::PublicKeyResolverStub.new)
|
|
10
10
|
now = Time.local(2018, 1, 9, 12, 0, 0)
|
|
11
11
|
Timecop.freeze(now)
|
|
12
12
|
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
RSpec.describe
|
|
1
|
+
RSpec.describe KeycloakApiRails::Service do
|
|
2
2
|
|
|
3
3
|
let!(:private_key) { OpenSSL::PKey::RSA.generate(2048) }
|
|
4
4
|
let!(:public_key) { private_key.public_key }
|
|
5
|
-
let!(:key_resolver) {
|
|
6
|
-
let!(:service) {
|
|
5
|
+
let!(:key_resolver) { KeycloakApiRails::PublicKeyCachedResolverStub.new(public_key) }
|
|
6
|
+
let!(:service) { KeycloakApiRails::Service.new(key_resolver) }
|
|
7
7
|
|
|
8
8
|
before(:each) do
|
|
9
9
|
now = Time.local(2018, 1, 9, 12, 0, 0)
|
|
@@ -17,7 +17,7 @@ RSpec.describe Keycloak::Service do
|
|
|
17
17
|
describe "#decode_and_verify" do
|
|
18
18
|
def create_token(private_key, expiration_date, algorithm)
|
|
19
19
|
claim = {
|
|
20
|
-
iss: "
|
|
20
|
+
iss: "KeycloakApiRails",
|
|
21
21
|
exp: expiration_date,
|
|
22
22
|
nbf: Time.local(2018, 1, 1, 0, 0, 0)
|
|
23
23
|
}
|
|
@@ -111,7 +111,7 @@ RSpec.describe Keycloak::Service do
|
|
|
111
111
|
|
|
112
112
|
|
|
113
113
|
before(:each) do
|
|
114
|
-
|
|
114
|
+
KeycloakApiRails.config.skip_paths = {
|
|
115
115
|
post: [/^\/skip/],
|
|
116
116
|
get: [/^\/skip/]
|
|
117
117
|
}
|
|
@@ -178,8 +178,8 @@ RSpec.describe Keycloak::Service do
|
|
|
178
178
|
|
|
179
179
|
context "when configured as opt_in" do
|
|
180
180
|
before do
|
|
181
|
-
|
|
182
|
-
service2 =
|
|
181
|
+
KeycloakApiRails.config.opt_in = true
|
|
182
|
+
service2 = KeycloakApiRails::Service.new(key_resolver)
|
|
183
183
|
@result = service2.need_middleware_authentication?(method, path, headers)
|
|
184
184
|
end
|
|
185
185
|
|
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.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lorent Lempereur
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-12-10 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.
|
|
47
|
+
version: 3.13.2
|
|
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.
|
|
54
|
+
version: 3.13.2
|
|
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.
|
|
61
|
+
version: 0.9.10
|
|
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.
|
|
68
|
+
version: 0.9.10
|
|
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:
|
|
75
|
+
version: 12.0.0
|
|
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:
|
|
82
|
+
version: 12.0.0
|
|
83
83
|
description: Rails middleware that validates Authorization token emitted by Keycloak
|
|
84
84
|
email:
|
|
85
85
|
- lorent.lempereur.dev@gmail.com
|
|
@@ -87,6 +87,7 @@ executables: []
|
|
|
87
87
|
extensions: []
|
|
88
88
|
extra_rdoc_files: []
|
|
89
89
|
files:
|
|
90
|
+
- ".github/workflows/ci.yml"
|
|
90
91
|
- ".gitignore"
|
|
91
92
|
- ".rspec"
|
|
92
93
|
- CHANGELOG.md
|
|
@@ -120,7 +121,7 @@ homepage: https://github.com/looorent/keycloak-api-rails
|
|
|
120
121
|
licenses:
|
|
121
122
|
- MIT
|
|
122
123
|
metadata: {}
|
|
123
|
-
post_install_message:
|
|
124
|
+
post_install_message:
|
|
124
125
|
rdoc_options: []
|
|
125
126
|
require_paths:
|
|
126
127
|
- lib
|
|
@@ -135,8 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
135
136
|
- !ruby/object:Gem::Version
|
|
136
137
|
version: '0'
|
|
137
138
|
requirements: []
|
|
138
|
-
rubygems_version: 3.
|
|
139
|
-
signing_key:
|
|
139
|
+
rubygems_version: 3.0.3.1
|
|
140
|
+
signing_key:
|
|
140
141
|
specification_version: 4
|
|
141
142
|
summary: Rails middleware that validates Authorization token emitted by Keycloak
|
|
142
143
|
test_files: []
|