keycloak_oauth 1.1.0 → 2.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/README.md +19 -4
- data/app/controllers/keycloak_oauth/callbacks_controller.rb +2 -4
- data/app/services/keycloak_oauth/authentication_service.rb +12 -19
- data/app/services/keycloak_oauth/authentication_service_base.rb +42 -0
- data/app/services/keycloak_oauth/{post_token_service.rb → post_authorization_code_service.rb} +1 -1
- data/app/services/keycloak_oauth/post_refresh_token_service.rb +39 -0
- data/app/services/keycloak_oauth/refresh_authentication_service.rb +21 -0
- data/lib/keycloak_oauth/version.rb +1 -1
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: baa20f03dc097cf9b5f18e60f1cd860e3590fa2eafe097989d39d1b29690dd57
|
4
|
+
data.tar.gz: 477b1887a6020aa95bd7e680bf1abe508ad90b99cc480606fdd5daec81adf210
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5b936cdf70211176742efcad5d1b799d6c72ecc1047c141e07c55ddb6c1b33985879d018616f30ab6ce7bb9b4e2be970977c4a1bcecb417bcf0ebd9e0787d68
|
7
|
+
data.tar.gz: 6f99f5fd86bff651312a0477ca719fb227ae1b5a960c9ebf066cb7e3a2d7a150f1d42a69c0df25efc6ccd78fd733ab220982e053e73202dfadf87d9268c8a1e5
|
data/README.md
CHANGED
@@ -22,6 +22,12 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
### Using `keycloak_oauth` in a Ruby on Rails app
|
24
24
|
|
25
|
+
Unless you plan to overwrite the oauth callback controller (see further below), mount the Rails engine into your application by specifying the following in `config/routes.rb`
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
mount KeycloakOauth::Engine => "/keycloak_oauth"
|
29
|
+
```
|
30
|
+
|
25
31
|
The configuration must be defined in the app by initialising the relevant attributes within a configuration block. For example, you could add an initializer script called `keycloak_oauth.rb` holding the following code:
|
26
32
|
|
27
33
|
```ruby
|
@@ -36,13 +42,22 @@ end
|
|
36
42
|
This then allows you to access the `KeycloakOauth` APIs:
|
37
43
|
`KeycloakOauth.connection.authorization_endpoint`
|
38
44
|
|
39
|
-
|
45
|
+
Ensure you have `default_url_options` set. Here
|
46
|
+
is an example of `default_url_options` appropriate for a development environment
|
47
|
+
in `config/environments/development.rb`:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
51
|
+
```
|
52
|
+
|
53
|
+
You can allow the user to log in with Keycloak by adding a link that points to `KeycloakOauth.connection.authorization_endpoint`:
|
40
54
|
e.g.
|
41
|
-
`<%= link_to 'Login with Keycloak', KeycloakOauth.connection.authorization_endpoint %>`
|
55
|
+
`<%= link_to 'Login with Keycloak', KeycloakOauth.connection.authorization_endpoint(options: { redirect_uri: keycloak_oauth.oauth2_url }) %>`
|
56
|
+
|
57
|
+
Once authentication is performed, the access and refresh tokens are stored in the session and can be used in your app as wished. As the session can become larger than we can store in a cookie (`CookieOverflow` exception), we recommend to use [activerecord-session_store](https://github.com/rails/activerecord-session_store).
|
42
58
|
|
43
|
-
|
59
|
+
### Customising redirect URIs
|
44
60
|
|
45
|
-
***Customising redirect URIs***
|
46
61
|
There are situations where you would want to customise the oauth2 route (e.g. to use a localised version of the callback URL).
|
47
62
|
In this case, you can do the following:
|
48
63
|
- add a controller to your app: e.g. `CallbackOverrides`
|
@@ -12,7 +12,7 @@ module KeycloakOauth
|
|
12
12
|
authentication_service.authenticate
|
13
13
|
map_authenticatable_if_implemented(session)
|
14
14
|
|
15
|
-
redirect_to self.class.method_defined?(:after_sign_in_path) ? after_sign_in_path(request) :
|
15
|
+
redirect_to self.class.method_defined?(:after_sign_in_path) ? after_sign_in_path(request) : main_app.root_path
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
@@ -24,8 +24,6 @@ module KeycloakOauth
|
|
24
24
|
def map_authenticatable_if_implemented(request)
|
25
25
|
if self.class.method_defined?(:map_authenticatable)
|
26
26
|
map_authenticatable(request)
|
27
|
-
else
|
28
|
-
raise NotImplementedError.new('User mapping must be handled by the host app. See README for more information.')
|
29
27
|
end
|
30
28
|
end
|
31
29
|
|
@@ -36,7 +34,7 @@ module KeycloakOauth
|
|
36
34
|
main_app.url_for(only_path: false, overwrite_params: nil)
|
37
35
|
rescue ActionController::UrlGenerationError
|
38
36
|
# If the host app does not override the oauth2 path, use the engine's path.
|
39
|
-
|
37
|
+
oauth2_url
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
@@ -1,31 +1,24 @@
|
|
1
1
|
module KeycloakOauth
|
2
|
-
class AuthenticationService
|
3
|
-
ACCESS_TOKEN_KEY = 'access_token'.freeze
|
4
|
-
REFRESH_TOKEN_KEY = 'refresh_token'.freeze
|
2
|
+
class AuthenticationService < AuthenticationServiceBase
|
5
3
|
|
6
|
-
attr_reader :
|
4
|
+
attr_reader :authentication_params
|
7
5
|
|
8
|
-
def initialize(
|
6
|
+
def initialize(session:, authentication_params:)
|
9
7
|
@authentication_params = authentication_params
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def authenticate
|
14
|
-
post_token_service = KeycloakOauth::PostTokenService.new(
|
15
|
-
connection: KeycloakOauth.connection,
|
16
|
-
request_params: authentication_params
|
17
|
-
)
|
18
|
-
post_token_service.perform
|
19
|
-
store_credentials(post_token_service)
|
8
|
+
super session: session
|
20
9
|
end
|
21
10
|
|
22
11
|
private
|
23
12
|
|
24
|
-
def
|
25
|
-
|
13
|
+
def post_service_name
|
14
|
+
KeycloakOauth::PostAuthorizationCodeService
|
15
|
+
end
|
26
16
|
|
27
|
-
|
28
|
-
|
17
|
+
def post_service_arguments
|
18
|
+
{
|
19
|
+
connection: KeycloakOauth.connection,
|
20
|
+
request_params: authentication_params
|
21
|
+
}
|
29
22
|
end
|
30
23
|
end
|
31
24
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module KeycloakOauth
|
2
|
+
class AuthenticationServiceBase
|
3
|
+
ACCESS_TOKEN_KEY = 'access_token'.freeze
|
4
|
+
ACCESS_TOKEN_EXPIRES_IN = 'expires_in'.freeze
|
5
|
+
REFRESH_TOKEN_KEY = 'refresh_token'.freeze
|
6
|
+
REFRESH_TOKEN_EXPIRES_IN = 'refresh_expires_in'.freeze
|
7
|
+
|
8
|
+
attr_reader :session
|
9
|
+
|
10
|
+
def initialize(session:)
|
11
|
+
@session = session
|
12
|
+
end
|
13
|
+
|
14
|
+
def authenticate
|
15
|
+
request_time = Time.zone.now
|
16
|
+
post_token_service = post_service_name.new(**post_service_arguments)
|
17
|
+
post_token_service.perform
|
18
|
+
store_credentials_in_session(post_token_service, request_time)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def post_service_name
|
24
|
+
raise "Implement in subclass"
|
25
|
+
end
|
26
|
+
|
27
|
+
def post_service_arguments
|
28
|
+
raise "Implement in subclass"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def store_credentials_in_session(post_token_service, request_time)
|
33
|
+
response_hash = post_token_service.parsed_response_body
|
34
|
+
|
35
|
+
session[:access_token] = response_hash[ACCESS_TOKEN_KEY]
|
36
|
+
session[:refresh_token] = response_hash[REFRESH_TOKEN_KEY]
|
37
|
+
|
38
|
+
session[:access_token_expires_at] = request_time + response_hash[ACCESS_TOKEN_EXPIRES_IN].to_i.seconds
|
39
|
+
session[:refresh_token_expires_at] = request_time + response_hash[REFRESH_TOKEN_EXPIRES_IN].to_i.seconds
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/app/services/keycloak_oauth/{post_token_service.rb → post_authorization_code_service.rb}
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
|
3
3
|
module KeycloakOauth
|
4
|
-
class
|
4
|
+
class PostAuthorizationCodeService < KeycloakOauth::AuthorizableService
|
5
5
|
DEFAULT_GRANT_TYPE = 'authorization_code'.freeze
|
6
6
|
|
7
7
|
attr_reader :request_params, :connection
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module KeycloakOauth
|
4
|
+
class PostRefreshTokenService < KeycloakOauth::AuthorizableService
|
5
|
+
DEFAULT_GRANT_TYPE = 'refresh_token'.freeze
|
6
|
+
|
7
|
+
def initialize(connection:, refresh_token:)
|
8
|
+
@connection = connection
|
9
|
+
@refresh_token = refresh_token
|
10
|
+
end
|
11
|
+
|
12
|
+
def send_request
|
13
|
+
post_token
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :connection, :refresh_token
|
19
|
+
|
20
|
+
def post_token
|
21
|
+
uri = URI.parse(connection.authentication_endpoint)
|
22
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
23
|
+
request = Net::HTTP::Post.new(uri)
|
24
|
+
request.set_content_type(CONTENT_TYPE_X_WWW_FORM_URLENCODED)
|
25
|
+
request.set_form_data(token_request_params)
|
26
|
+
http.request(request)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def token_request_params
|
31
|
+
{
|
32
|
+
client_id: connection.client_id,
|
33
|
+
client_secret: connection.client_secret,
|
34
|
+
grant_type: DEFAULT_GRANT_TYPE,
|
35
|
+
refresh_token: refresh_token
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module KeycloakOauth
|
2
|
+
class RefreshAuthenticationService < AuthenticationServiceBase
|
3
|
+
|
4
|
+
def initialize(session:)
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def post_service_name
|
11
|
+
KeycloakOauth::PostRefreshTokenService
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_service_arguments
|
15
|
+
{
|
16
|
+
connection: KeycloakOauth.connection,
|
17
|
+
refresh_token: session[:refresh_token]
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keycloak_oauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- simplificator
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: timecop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
description:
|
98
112
|
email:
|
99
113
|
- dev@simplificator.com
|
@@ -105,12 +119,15 @@ files:
|
|
105
119
|
- Rakefile
|
106
120
|
- app/controllers/keycloak_oauth/callbacks_controller.rb
|
107
121
|
- app/services/keycloak_oauth/authentication_service.rb
|
122
|
+
- app/services/keycloak_oauth/authentication_service_base.rb
|
108
123
|
- app/services/keycloak_oauth/authorizable_service.rb
|
109
124
|
- app/services/keycloak_oauth/get_users_service.rb
|
110
125
|
- app/services/keycloak_oauth/logout_service.rb
|
111
|
-
- app/services/keycloak_oauth/
|
126
|
+
- app/services/keycloak_oauth/post_authorization_code_service.rb
|
127
|
+
- app/services/keycloak_oauth/post_refresh_token_service.rb
|
112
128
|
- app/services/keycloak_oauth/post_users_service.rb
|
113
129
|
- app/services/keycloak_oauth/put_execute_actions_email_service.rb
|
130
|
+
- app/services/keycloak_oauth/refresh_authentication_service.rb
|
114
131
|
- app/services/keycloak_oauth/user_info_retrieval_service.rb
|
115
132
|
- config/routes.rb
|
116
133
|
- lib/keycloak_oauth.rb
|