keycloak-api-rails 0.10.2 → 0.11.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +23 -0
- data/Dockerfile +7 -4
- data/Gemfile.lock +131 -110
- data/README.md +6 -6
- data/keycloak-api-rails.gemspec +2 -3
- data/lib/keycloak-api-rails/configuration.rb +1 -0
- data/lib/keycloak-api-rails/helper.rb +38 -8
- data/lib/keycloak-api-rails/http_client.rb +28 -0
- data/lib/keycloak-api-rails/middleware.rb +5 -2
- data/lib/keycloak-api-rails/public_key_cached_resolver.rb +4 -4
- data/lib/keycloak-api-rails/public_key_resolver.rb +5 -14
- data/lib/keycloak-api-rails/version.rb +1 -1
- data/lib/keycloak-api-rails.rb +7 -1
- metadata +10 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ff480abdc3a9317e66060416095339c0612ff902fec1200bf1178c7445bfad39
|
4
|
+
data.tar.gz: 29d7cb681cb2b05d801ceac2634b6773278516413112500968cdfe5fe7cae76e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bd3bac623390a4efe1cf24a80106c820e2b66c186350ddab00140ccab44f1a919117afb28a2bdcf02651cc1b780d0e9cfc4e75256d6083339e140bdd44669f6
|
7
|
+
data.tar.gz: fdbc7a9b37f8d5efdf5c11ee9ca01075ccfe9bbfaf7d5babfda1653eef9557a275c34487569d4589c2f5902c8ff13a7877f5e6d55133b0e4a7b9b4bd4fb00a58
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [0.11.2] - 2022-03-30
|
9
|
+
|
10
|
+
* 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.
|
11
|
+
* Update `json-jwt` to `>=1.13.0`
|
12
|
+
|
13
|
+
## [0.11.1] - 2019-11-27
|
14
|
+
|
15
|
+
* When a token validation error occurs, do not log it as a `warn` (but as an `info` instead)
|
16
|
+
|
17
|
+
## [0.11.0] - 2019-11-21
|
18
|
+
|
19
|
+
* Remove dependency to `rest-client` (thanks to @@loicvigneron)
|
20
|
+
* Access Authorization Party from ENV (thanks to @@loicvigneron)
|
21
|
+
* New configuration option: `ca_certificate_file` (thanks to @@loicvigneron)
|
22
|
+
* Access the token from ENV
|
23
|
+
* Upgrade `json-jwt` to `1.11.0`
|
data/Dockerfile
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
-
FROM ruby:2.
|
2
|
-
|
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/
|
6
9
|
COPY Gemfile.lock /usr/src/app/
|
7
10
|
COPY keycloak-api-rails.gemspec /usr/src/app/
|
8
11
|
COPY lib/keycloak-api-rails/version.rb /usr/src/app/lib/keycloak-api-rails/
|
9
|
-
RUN bundle install
|
12
|
+
# RUN bundle install
|
10
13
|
COPY . /usr/src/app
|
11
|
-
RUN bundle install
|
14
|
+
# RUN bundle install
|
data/Gemfile.lock
CHANGED
@@ -1,127 +1,156 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
keycloak-api-rails (0.
|
5
|
-
json-jwt (>= 1.
|
4
|
+
keycloak-api-rails (0.11.2)
|
5
|
+
json-jwt (>= 1.11.0)
|
6
6
|
rails (>= 4.2)
|
7
|
-
rest-client (>= 2.0.2)
|
8
7
|
|
9
8
|
GEM
|
10
9
|
remote: https://rubygems.org/
|
11
10
|
specs:
|
12
|
-
actioncable (
|
13
|
-
actionpack (=
|
11
|
+
actioncable (7.0.2.3)
|
12
|
+
actionpack (= 7.0.2.3)
|
13
|
+
activesupport (= 7.0.2.3)
|
14
14
|
nio4r (~> 2.0)
|
15
15
|
websocket-driver (>= 0.6.1)
|
16
|
-
|
17
|
-
actionpack (=
|
18
|
-
|
19
|
-
|
16
|
+
actionmailbox (7.0.2.3)
|
17
|
+
actionpack (= 7.0.2.3)
|
18
|
+
activejob (= 7.0.2.3)
|
19
|
+
activerecord (= 7.0.2.3)
|
20
|
+
activestorage (= 7.0.2.3)
|
21
|
+
activesupport (= 7.0.2.3)
|
22
|
+
mail (>= 2.7.1)
|
23
|
+
net-imap
|
24
|
+
net-pop
|
25
|
+
net-smtp
|
26
|
+
actionmailer (7.0.2.3)
|
27
|
+
actionpack (= 7.0.2.3)
|
28
|
+
actionview (= 7.0.2.3)
|
29
|
+
activejob (= 7.0.2.3)
|
30
|
+
activesupport (= 7.0.2.3)
|
20
31
|
mail (~> 2.5, >= 2.5.4)
|
32
|
+
net-imap
|
33
|
+
net-pop
|
34
|
+
net-smtp
|
21
35
|
rails-dom-testing (~> 2.0)
|
22
|
-
actionpack (
|
23
|
-
actionview (=
|
24
|
-
activesupport (=
|
25
|
-
rack (~> 2.0)
|
36
|
+
actionpack (7.0.2.3)
|
37
|
+
actionview (= 7.0.2.3)
|
38
|
+
activesupport (= 7.0.2.3)
|
39
|
+
rack (~> 2.0, >= 2.2.0)
|
26
40
|
rack-test (>= 0.6.3)
|
27
41
|
rails-dom-testing (~> 2.0)
|
28
|
-
rails-html-sanitizer (~> 1.0, >= 1.0
|
29
|
-
|
30
|
-
|
42
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
43
|
+
actiontext (7.0.2.3)
|
44
|
+
actionpack (= 7.0.2.3)
|
45
|
+
activerecord (= 7.0.2.3)
|
46
|
+
activestorage (= 7.0.2.3)
|
47
|
+
activesupport (= 7.0.2.3)
|
48
|
+
globalid (>= 0.6.0)
|
49
|
+
nokogiri (>= 1.8.5)
|
50
|
+
actionview (7.0.2.3)
|
51
|
+
activesupport (= 7.0.2.3)
|
31
52
|
builder (~> 3.1)
|
32
53
|
erubi (~> 1.4)
|
33
54
|
rails-dom-testing (~> 2.0)
|
34
|
-
rails-html-sanitizer (~> 1.
|
35
|
-
activejob (
|
36
|
-
activesupport (=
|
55
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
56
|
+
activejob (7.0.2.3)
|
57
|
+
activesupport (= 7.0.2.3)
|
37
58
|
globalid (>= 0.3.6)
|
38
|
-
activemodel (
|
39
|
-
activesupport (=
|
40
|
-
activerecord (
|
41
|
-
activemodel (=
|
42
|
-
activesupport (=
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
activerecord (=
|
47
|
-
|
48
|
-
|
59
|
+
activemodel (7.0.2.3)
|
60
|
+
activesupport (= 7.0.2.3)
|
61
|
+
activerecord (7.0.2.3)
|
62
|
+
activemodel (= 7.0.2.3)
|
63
|
+
activesupport (= 7.0.2.3)
|
64
|
+
activestorage (7.0.2.3)
|
65
|
+
actionpack (= 7.0.2.3)
|
66
|
+
activejob (= 7.0.2.3)
|
67
|
+
activerecord (= 7.0.2.3)
|
68
|
+
activesupport (= 7.0.2.3)
|
69
|
+
marcel (~> 1.0)
|
70
|
+
mini_mime (>= 1.1.0)
|
71
|
+
activesupport (7.0.2.3)
|
49
72
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
50
|
-
i18n (>=
|
51
|
-
minitest (
|
52
|
-
tzinfo (~>
|
53
|
-
aes_key_wrap (1.0
|
54
|
-
|
55
|
-
|
56
|
-
builder (3.2.3)
|
73
|
+
i18n (>= 1.6, < 2)
|
74
|
+
minitest (>= 5.1)
|
75
|
+
tzinfo (~> 2.0)
|
76
|
+
aes_key_wrap (1.1.0)
|
77
|
+
bindata (2.4.10)
|
78
|
+
builder (3.2.4)
|
57
79
|
byebug (9.1.0)
|
58
|
-
concurrent-ruby (1.
|
59
|
-
crass (1.0.
|
60
|
-
diff-lcs (1.
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
http-cookie (1.0.3)
|
67
|
-
domain_name (~> 0.5)
|
68
|
-
i18n (1.1.0)
|
80
|
+
concurrent-ruby (1.1.10)
|
81
|
+
crass (1.0.6)
|
82
|
+
diff-lcs (1.5.0)
|
83
|
+
digest (3.1.0)
|
84
|
+
erubi (1.10.0)
|
85
|
+
globalid (1.0.0)
|
86
|
+
activesupport (>= 5.0)
|
87
|
+
i18n (1.10.0)
|
69
88
|
concurrent-ruby (~> 1.0)
|
70
|
-
|
71
|
-
|
89
|
+
io-wait (0.2.1)
|
90
|
+
json-jwt (1.13.0)
|
91
|
+
activesupport (>= 4.2)
|
72
92
|
aes_key_wrap
|
73
93
|
bindata
|
74
|
-
loofah (2.
|
94
|
+
loofah (2.15.0)
|
75
95
|
crass (~> 1.0.2)
|
76
96
|
nokogiri (>= 1.5.9)
|
77
|
-
mail (2.7.
|
97
|
+
mail (2.7.1)
|
78
98
|
mini_mime (>= 0.1.1)
|
79
|
-
marcel (0.
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
99
|
+
marcel (1.0.2)
|
100
|
+
method_source (1.0.0)
|
101
|
+
mini_mime (1.1.2)
|
102
|
+
mini_portile2 (2.8.0)
|
103
|
+
minitest (5.15.0)
|
104
|
+
net-imap (0.2.3)
|
105
|
+
digest
|
106
|
+
net-protocol
|
107
|
+
strscan
|
108
|
+
net-pop (0.1.1)
|
109
|
+
digest
|
110
|
+
net-protocol
|
111
|
+
timeout
|
112
|
+
net-protocol (0.1.2)
|
113
|
+
io-wait
|
114
|
+
timeout
|
115
|
+
net-smtp (0.3.1)
|
116
|
+
digest
|
117
|
+
net-protocol
|
118
|
+
timeout
|
119
|
+
nio4r (2.5.8)
|
120
|
+
nokogiri (1.13.3)
|
121
|
+
mini_portile2 (~> 2.8.0)
|
122
|
+
racc (~> 1.4)
|
123
|
+
racc (1.6.0)
|
124
|
+
rack (2.2.3)
|
94
125
|
rack-test (1.1.0)
|
95
126
|
rack (>= 1.0, < 3)
|
96
|
-
rails (
|
97
|
-
actioncable (=
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
127
|
+
rails (7.0.2.3)
|
128
|
+
actioncable (= 7.0.2.3)
|
129
|
+
actionmailbox (= 7.0.2.3)
|
130
|
+
actionmailer (= 7.0.2.3)
|
131
|
+
actionpack (= 7.0.2.3)
|
132
|
+
actiontext (= 7.0.2.3)
|
133
|
+
actionview (= 7.0.2.3)
|
134
|
+
activejob (= 7.0.2.3)
|
135
|
+
activemodel (= 7.0.2.3)
|
136
|
+
activerecord (= 7.0.2.3)
|
137
|
+
activestorage (= 7.0.2.3)
|
138
|
+
activesupport (= 7.0.2.3)
|
139
|
+
bundler (>= 1.15.0)
|
140
|
+
railties (= 7.0.2.3)
|
109
141
|
rails-dom-testing (2.0.3)
|
110
142
|
activesupport (>= 4.2.0)
|
111
143
|
nokogiri (>= 1.6)
|
112
|
-
rails-html-sanitizer (1.
|
113
|
-
loofah (~> 2.
|
114
|
-
railties (
|
115
|
-
actionpack (=
|
116
|
-
activesupport (=
|
144
|
+
rails-html-sanitizer (1.4.2)
|
145
|
+
loofah (~> 2.3)
|
146
|
+
railties (7.0.2.3)
|
147
|
+
actionpack (= 7.0.2.3)
|
148
|
+
activesupport (= 7.0.2.3)
|
117
149
|
method_source
|
118
|
-
rake (>=
|
119
|
-
thor (
|
120
|
-
|
121
|
-
|
122
|
-
http-cookie (>= 1.0.2, < 2.0)
|
123
|
-
mime-types (>= 1.16, < 4.0)
|
124
|
-
netrc (~> 0.8)
|
150
|
+
rake (>= 12.2)
|
151
|
+
thor (~> 1.0)
|
152
|
+
zeitwerk (~> 2.5)
|
153
|
+
rake (13.0.6)
|
125
154
|
rspec (3.7.0)
|
126
155
|
rspec-core (~> 3.7.0)
|
127
156
|
rspec-expectations (~> 3.7.0)
|
@@ -134,25 +163,17 @@ GEM
|
|
134
163
|
rspec-mocks (3.7.0)
|
135
164
|
diff-lcs (>= 1.2.0, < 2.0)
|
136
165
|
rspec-support (~> 3.7.0)
|
137
|
-
rspec-support (3.7.
|
138
|
-
|
139
|
-
|
140
|
-
rack (> 1, < 3)
|
141
|
-
sprockets-rails (3.2.1)
|
142
|
-
actionpack (>= 4.0)
|
143
|
-
activesupport (>= 4.0)
|
144
|
-
sprockets (>= 3.0.0)
|
145
|
-
thor (0.20.0)
|
146
|
-
thread_safe (0.3.6)
|
166
|
+
rspec-support (3.7.1)
|
167
|
+
strscan (3.0.1)
|
168
|
+
thor (1.2.1)
|
147
169
|
timecop (0.9.1)
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
unf_ext (0.0.7.5)
|
153
|
-
websocket-driver (0.7.0)
|
170
|
+
timeout (0.2.0)
|
171
|
+
tzinfo (2.0.4)
|
172
|
+
concurrent-ruby (~> 1.0)
|
173
|
+
websocket-driver (0.7.5)
|
154
174
|
websocket-extensions (>= 0.1.0)
|
155
|
-
websocket-extensions (0.1.
|
175
|
+
websocket-extensions (0.1.5)
|
176
|
+
zeitwerk (2.5.4)
|
156
177
|
|
157
178
|
PLATFORMS
|
158
179
|
ruby
|
@@ -164,4 +185,4 @@ DEPENDENCIES
|
|
164
185
|
timecop (= 0.9.1)
|
165
186
|
|
166
187
|
BUNDLED WITH
|
167
|
-
1.
|
188
|
+
2.1.4
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ This gem aims at validates Keycloak JWT token in Ruby On Rails APIs.
|
|
5
5
|
## Install
|
6
6
|
|
7
7
|
```ruby
|
8
|
-
gem "keycloak-api-rails", "0.
|
8
|
+
gem "keycloak-api-rails", "0.11.2"
|
9
9
|
```
|
10
10
|
|
11
11
|
## Token validation
|
@@ -14,7 +14,7 @@ Tokens send (through query strings or Authorization headers) to this Railtie Mid
|
|
14
14
|
|
15
15
|
## Pass token to the API
|
16
16
|
|
17
|
-
* Method 1: By adding an `Authorization` HTTP Header with its value set to `Bearer <your token>`.
|
17
|
+
* Method 1: By adding an `Authorization` HTTP Header with its value set to `Bearer <your token>`.
|
18
18
|
_e.g_ using curl: `curl -H "Authorization: Bearer <your-token>" https://api.pouet.io/api/more-pouets`
|
19
19
|
* Method 2: By providing the token via query string, especially via the parameter named `authorizationToken`. Keep in mind that this method is less secure (url are kept intact in your browser history, and so on...)
|
20
20
|
_e.g._ using curl: `curl https://api.pouet.io/api/more-pouets?authorizationToken<your-token>`
|
@@ -42,8 +42,8 @@ All options have a default value. However, all of them can be changed in your in
|
|
42
42
|
| `token_expiration_tolerance_in_seconds` | `10`| Logger | Optional | Number of seconds a token can expire before being rejected by the API. | `15` |
|
43
43
|
| `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
44
|
| `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"]` |
|
45
|
-
|
46
|
-
## Configure it
|
45
|
+
| `ca_certificate_file` | `nil`| String | Optional | Path to the certificate authority used to validate the Keycloak server certificate | `/credentials/production_root_ca_cert.pem` |
|
46
|
+
## Configure it
|
47
47
|
|
48
48
|
Create a `keycloak.rb` file in your Rails `config/initializers` folder. For instance:
|
49
49
|
|
@@ -65,7 +65,7 @@ Once this gem is configured in your Rails project, you can read, validate and us
|
|
65
65
|
|
66
66
|
### Keycloak Id
|
67
67
|
|
68
|
-
If you identify users using their Keycloak Id, this value can be read from your controllers using `Keycloak::Helper.current_user_id(request.env)`.
|
68
|
+
If you identify users using their Keycloak Id, this value can be read from your controllers using `Keycloak::Helper.current_user_id(request.env)`.
|
69
69
|
|
70
70
|
```ruby
|
71
71
|
class AuthenticatedController < ApplicationController
|
@@ -173,4 +173,4 @@ From the `keycloak-rails-api` directory:
|
|
173
173
|
|
174
174
|
## Next developments
|
175
175
|
|
176
|
-
*
|
176
|
+
* Manage multiple realms
|
data/keycloak-api-rails.gemspec
CHANGED
@@ -16,10 +16,9 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.require_paths = ["lib"]
|
17
17
|
|
18
18
|
spec.add_dependency "rails", ">= 4.2"
|
19
|
-
spec.add_dependency "json-jwt", ">= 1.
|
20
|
-
spec.add_dependency "rest-client", ">= 2.0.2"
|
19
|
+
spec.add_dependency "json-jwt", ">= 1.11.0"
|
21
20
|
|
22
21
|
spec.add_development_dependency "rspec", "3.7.0"
|
23
22
|
spec.add_development_dependency "timecop", "0.9.1"
|
24
23
|
spec.add_development_dependency "byebug", "9.1.0"
|
25
|
-
end
|
24
|
+
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module Keycloak
|
2
2
|
class Helper
|
3
|
-
|
4
|
-
CURRENT_USER_ID_KEY
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
|
4
|
+
CURRENT_USER_ID_KEY = "keycloak:keycloak_id"
|
5
|
+
CURRENT_AUTHORIZED_PARTY_KEY = "keycloak:authorized_party"
|
6
|
+
CURRENT_USER_EMAIL_KEY = "keycloak:email"
|
7
|
+
CURRENT_USER_LOCALE_KEY = "keycloak:locale"
|
8
|
+
CURRENT_USER_ATTRIBUTES = "keycloak:attributes"
|
9
|
+
ROLES_KEY = "keycloak:roles"
|
10
|
+
RESOURCE_ROLES_KEY = "keycloak:resource_roles"
|
11
|
+
TOKEN_KEY = "keycloak:token"
|
12
|
+
QUERY_STRING_TOKEN_KEY = "authorizationToken"
|
10
13
|
|
11
14
|
def self.current_user_id(env)
|
12
15
|
env[CURRENT_USER_ID_KEY]
|
@@ -16,6 +19,22 @@ module Keycloak
|
|
16
19
|
env[CURRENT_USER_ID_KEY] = token["sub"]
|
17
20
|
end
|
18
21
|
|
22
|
+
def self.keycloak_token(env)
|
23
|
+
env[TOKEN_KEY]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.assign_keycloak_token(env, token)
|
27
|
+
env[TOKEN_KEY] = token
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.current_authorized_party(env)
|
31
|
+
env[CURRENT_AUTHORIZED_PARTY_KEY]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.assign_current_authorized_party(env, token)
|
35
|
+
env[CURRENT_AUTHORIZED_PARTY_KEY] = token["azp"]
|
36
|
+
end
|
37
|
+
|
19
38
|
def self.current_user_email(env)
|
20
39
|
env[CURRENT_USER_EMAIL_KEY]
|
21
40
|
end
|
@@ -40,8 +59,19 @@ module Keycloak
|
|
40
59
|
env[ROLES_KEY] = token.dig("realm_access", "roles")
|
41
60
|
end
|
42
61
|
|
62
|
+
def self.current_resource_roles(env)
|
63
|
+
env[RESOURCE_ROLES_KEY]
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.assign_resource_roles(env, token)
|
67
|
+
env[RESOURCE_ROLES_KEY] = token.fetch("resource_access", {}).inject({}) do |resource_roles, (name, resource_attributes)|
|
68
|
+
resource_roles[name] = resource_attributes.fetch("roles", [])
|
69
|
+
resource_roles
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
43
73
|
def self.assign_current_user_custom_attributes(env, token, attribute_names)
|
44
|
-
env[CURRENT_USER_ATTRIBUTES] = token.select { |key,value| attribute_names.include?(key) }
|
74
|
+
env[CURRENT_USER_ATTRIBUTES] = token.select { |key, value| attribute_names.include?(key) }
|
45
75
|
end
|
46
76
|
|
47
77
|
def self.current_user_custom_attributes(env)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Keycloak
|
2
|
+
class HTTPClient
|
3
|
+
def initialize(configuration)
|
4
|
+
@server_url = configuration.server_url
|
5
|
+
@ca_certificate_file = configuration.ca_certificate_file
|
6
|
+
@x509_store = OpenSSL::X509::Store.new
|
7
|
+
@x509_store.set_default_paths
|
8
|
+
@x509_store.add_file(@ca_certificate_file) if @ca_certificate_file
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(realm_id, path)
|
12
|
+
uri = build_uri(realm_id, path)
|
13
|
+
use_ssl = uri.scheme == "http" ? false : true
|
14
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => use_ssl, :cert_store => @x509_store) do |http|
|
15
|
+
request = Net::HTTP::Get.new(uri)
|
16
|
+
response = http.request(request)
|
17
|
+
JSON.parse(response.body)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_uri(realm_id, path)
|
24
|
+
string_uri = File.join(@server_url, "realms", realm_id, path)
|
25
|
+
URI(string_uri)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -9,7 +9,7 @@ module Keycloak
|
|
9
9
|
method = env["REQUEST_METHOD"]
|
10
10
|
path = env["PATH_INFO"]
|
11
11
|
uri = env["REQUEST_URI"]
|
12
|
-
|
12
|
+
|
13
13
|
if service.need_authentication?(method, path, env)
|
14
14
|
logger.debug("Start authentication for #{method} : #{path}")
|
15
15
|
token = service.read_token(uri, env)
|
@@ -24,16 +24,19 @@ module Keycloak
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def authentication_failed(message)
|
27
|
-
logger.
|
27
|
+
logger.info(message)
|
28
28
|
[401, {"Content-Type" => "application/json"}, [ { error: message }.to_json]]
|
29
29
|
end
|
30
30
|
|
31
31
|
def authentication_succeeded(env, decoded_token)
|
32
32
|
Helper.assign_current_user_id(env, decoded_token)
|
33
|
+
Helper.assign_current_authorized_party(env, decoded_token)
|
33
34
|
Helper.assign_current_user_email(env, decoded_token)
|
34
35
|
Helper.assign_current_user_locale(env, decoded_token)
|
35
36
|
Helper.assign_current_user_custom_attributes(env, decoded_token, config.custom_attributes)
|
36
37
|
Helper.assign_realm_roles(env, decoded_token)
|
38
|
+
Helper.assign_resource_roles(env, decoded_token)
|
39
|
+
Helper.assign_keycloak_token(env, decoded_token)
|
37
40
|
@app.call(env)
|
38
41
|
end
|
39
42
|
|
@@ -2,15 +2,15 @@ module Keycloak
|
|
2
2
|
class PublicKeyCachedResolver
|
3
3
|
attr_reader :cached_public_key_retrieved_at
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@resolver = PublicKeyResolver.new(
|
5
|
+
def initialize(http_client, realm_id, public_key_cache_ttl)
|
6
|
+
@resolver = PublicKeyResolver.new(http_client, realm_id)
|
7
7
|
@public_key_cache_ttl = public_key_cache_ttl
|
8
8
|
@cached_public_keys = nil
|
9
9
|
@cached_public_key_retrieved_at = nil
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.from_configuration(configuration)
|
13
|
-
PublicKeyCachedResolver.new(
|
12
|
+
def self.from_configuration(http_client, configuration)
|
13
|
+
PublicKeyCachedResolver.new(http_client, configuration.realm_id, configuration.public_key_cache_ttl)
|
14
14
|
end
|
15
15
|
|
16
16
|
def find_public_keys
|
@@ -1,21 +1,12 @@
|
|
1
1
|
module Keycloak
|
2
2
|
class PublicKeyResolver
|
3
|
-
def initialize(
|
4
|
-
@
|
3
|
+
def initialize(http_client, realm_id)
|
4
|
+
@realm_id = realm_id
|
5
|
+
@http_client = http_client
|
5
6
|
end
|
6
7
|
|
7
8
|
def find_public_keys
|
8
|
-
JSON::JWK::Set.new(
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def create_realm_url(server_url, realm_id)
|
14
|
-
"#{server_url}/realms/#{realm_id}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def create_public_certificate_url(server_url, realm_id)
|
18
|
-
"#{create_realm_url(server_url, realm_id)}/protocol/openid-connect/certs"
|
9
|
+
JSON::JWK::Set.new(@http_client.get(@realm_id, "protocol/openid-connect/certs")["keys"])
|
19
10
|
end
|
20
11
|
end
|
21
|
-
end
|
12
|
+
end
|
data/lib/keycloak-api-rails.rb
CHANGED
@@ -2,8 +2,10 @@ require "logger"
|
|
2
2
|
require "json/jwt"
|
3
3
|
require "uri"
|
4
4
|
require "date"
|
5
|
+
require "net/http"
|
5
6
|
|
6
7
|
require_relative "keycloak-api-rails/configuration"
|
8
|
+
require_relative "keycloak-api-rails/http_client"
|
7
9
|
require_relative "keycloak-api-rails/token_error"
|
8
10
|
require_relative "keycloak-api-rails/helper"
|
9
11
|
require_relative "keycloak-api-rails/public_key_resolver"
|
@@ -22,8 +24,12 @@ module Keycloak
|
|
22
24
|
@configuration
|
23
25
|
end
|
24
26
|
|
27
|
+
def self.http_client
|
28
|
+
@http_client ||= Keycloak::HTTPClient.new(config)
|
29
|
+
end
|
30
|
+
|
25
31
|
def self.public_key_resolver
|
26
|
-
@public_key_resolver ||= PublicKeyCachedResolver.from_configuration(config)
|
32
|
+
@public_key_resolver ||= PublicKeyCachedResolver.from_configuration(http_client, config)
|
27
33
|
end
|
28
34
|
|
29
35
|
def self.service
|
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: 0.11.2
|
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: 2022-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -30,28 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.11.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rest-client
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 2.0.2
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 2.0.2
|
40
|
+
version: 1.11.0
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: rspec
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,6 +89,7 @@ extra_rdoc_files: []
|
|
103
89
|
files:
|
104
90
|
- ".gitignore"
|
105
91
|
- ".rspec"
|
92
|
+
- CHANGELOG.md
|
106
93
|
- Dockerfile
|
107
94
|
- Gemfile
|
108
95
|
- Gemfile.lock
|
@@ -112,6 +99,7 @@ files:
|
|
112
99
|
- lib/keycloak-api-rails.rb
|
113
100
|
- lib/keycloak-api-rails/configuration.rb
|
114
101
|
- lib/keycloak-api-rails/helper.rb
|
102
|
+
- lib/keycloak-api-rails/http_client.rb
|
115
103
|
- lib/keycloak-api-rails/middleware.rb
|
116
104
|
- lib/keycloak-api-rails/public_key_cached_resolver.rb
|
117
105
|
- lib/keycloak-api-rails/public_key_resolver.rb
|
@@ -130,7 +118,7 @@ homepage: https://github.com/looorent/keycloak-api-rails
|
|
130
118
|
licenses:
|
131
119
|
- MIT
|
132
120
|
metadata: {}
|
133
|
-
post_install_message:
|
121
|
+
post_install_message:
|
134
122
|
rdoc_options: []
|
135
123
|
require_paths:
|
136
124
|
- lib
|
@@ -145,9 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
133
|
- !ruby/object:Gem::Version
|
146
134
|
version: '0'
|
147
135
|
requirements: []
|
148
|
-
|
149
|
-
|
150
|
-
signing_key:
|
136
|
+
rubygems_version: 3.2.3
|
137
|
+
signing_key:
|
151
138
|
specification_version: 4
|
152
139
|
summary: Rails middleware that validates Authorization token emitted by Keycloak
|
153
140
|
test_files: []
|