rails_keycloak_authorization 0.0.1 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 473a44e0abf7c0db82ad24417b0e20a546219e28967dc41cdee8753a954b0c3a
4
- data.tar.gz: d2d21f2d7c7c291fcfc267ed9e7b83c66684714d952341b875d46ac2db2bdad8
3
+ metadata.gz: 8124610067e4109acd7ffb0921aeb2aa24493a0ce221048ffe2bec0ca5858a1f
4
+ data.tar.gz: 6984ea42b2cc5992825a5ed8dadacf2c39edcb18c14a5937911f42e7514bbd26
5
5
  SHA512:
6
- metadata.gz: dccfd5e98b565f2c1da1911ab0d588b08a96a15790b0c6147e868c57b7f4f4e7fd444a9a1fa2280ccb4ca1d303d6a4601db8475931e511e2d6bcd8a0170417a7
7
- data.tar.gz: f8175f8a52eb1e2bac762fe7e3ba4e2cac8ffdc322291e667901f958781c551d06920e3f80bcdb4c25f2430069e6e50f1a13f3153b5c9681117aef07d9e1a817
6
+ metadata.gz: 91ecddf3280a977f7f0833b19eb200faa5b611353cae969cbb48742f2b6d5c80ee86e3d94f5566a97cd0871b797325b68813033a0436da6428eb489bdd72b245
7
+ data.tar.gz: 89c50534873d123a6942b868118ec805b33ac16d9ce7430a5879e266945d6907a1910e1ec73d183343316588325d93a78c390bd0de745902f783c5daeceb1aa9
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Rails Keycloak Authorization
2
2
 
3
+ ![Github Actions CI workflow](https://github.com/tillawy/rails_keycloak_authorization/actions/workflows/ruby.yml/badge.svg)
4
+
5
+
3
6
  Rails middleware to authorize requests using [Keycloak](https://www.keycloak.org) and gem [keycloak-admin-ruby](https://github.com/looorent/keycloak-admin-ruby).
4
7
 
5
8
  This gem uses JWT token to authorize requests.
@@ -50,20 +53,28 @@ sequenceDiagram
50
53
  In order to use this gem, you need to configure it in an initializer file. You can create a new file in `config/initializers/rails_keycloak_authorization.rb` with the following content:
51
54
 
52
55
  ```ruby
53
- # The Keycloak realm
54
- RailsKeycloakAuthorization.keycloak_realm = ENV.fetch("KEYCLOAK_AUTH_CLIENT_REALM_NAME", "dummy")
55
- # The client id in the realm
56
- RailsKeycloakAuthorization.client_id = ENV.fetch("KEYCLOAK_AUTH_CLIENT_ID", "dummy-client")
57
- # Keycloak server url
58
- RailsKeycloakAuthorization.keycloak_server_url = ENV.fetch("KEYCLOAK_SERVER_URL", "http://localhost:8080")
59
- # Patterns that are protected by the middleware, Array of regular-expressions.
60
- RailsKeycloakAuthorization.match_patterns = [
56
+ RailsKeycloakAuthorization.keycloak_auth_client_realm_name = ENV.fetch("KEYCLOAK_AUTH_CLIENT_REALM_NAME", "dummy")
57
+ RailsKeycloakAuthorization.keycloak_auth_client_id = ENV.fetch("KEYCLOAK_AUTH_CLIENT_ID", "dummy-client")
58
+ RailsKeycloakAuthorization.keycloak_server_url = ENV.fetch("KEYCLOAK_SERVER_URL", "http://localhost:8080")
59
+ RailsKeycloakAuthorization.keycloak_server_domain = ENV.fetch("KEYCLOAK_ADMIN_SERVER_DOMAIN", "localhost")
60
+ RailsKeycloakAuthorization.keycloak_admin_realm_name = ENV.fetch("KEYCLOAK_ADMIN_REALM_NAME", "master")
61
+ RailsKeycloakAuthorization.keycloak_admin_client_id = ENV.fetch("KEYCLOAK_ADMIN_CLIENT_ID", "keycloak-admin")
62
+ RailsKeycloakAuthorization.keycloak_admin_client_secret = ENV.fetch("KEYCLOAK_ADMIN_CLIENT_SECRET", "keycloak-admin-client-secret-xxx")
63
+ RailsKeycloakAuthorization.match_patterns = [
61
64
  /^\/organizations(\.json)?/,
62
65
  /^\/api/,
63
66
  /internal/
64
67
  ]
65
68
  ```
66
69
 
70
+ Add the route to the UI helper `config/routes.rb`:
71
+
72
+ ```
73
+ # make sure to change the constraint to suite your security
74
+ mount RailsKeycloakAuthorization::Engine, at: "/rka", constraints: lambda { |request| request.remote_ip == "127.0.0.1" }
75
+ ```
76
+
77
+
67
78
  ## How to easily test it?
68
79
 
69
80
  Create development environment with Keycloak and Tofu:
@@ -5,28 +5,25 @@ module RailsKeycloakAuthorization
5
5
  before_action :keycloak_admin_configure
6
6
  end
7
7
 
8
- private
9
-
10
-
11
-
12
-
13
-
8
+
14
9
  def realm_name
15
- ENV.fetch('KEYCLOAK_AUTH_CLIENT_REALM_NAME')
10
+ RailsKeycloakAuthorization.keycloak_auth_client_realm_name
16
11
  end
12
+ private
13
+
17
14
 
18
15
  def openid_client
19
- KeycloakAdmin.realm(realm_name).clients.find_by_client_id(ENV["KEYCLOAK_AUTH_CLIENT_ID"])
16
+ KeycloakAdmin.realm(realm_name).clients.find_by_client_id(RailsKeycloakAuthorization.keycloak_auth_client_id)
20
17
  end
21
18
 
22
19
  def keycloak_admin_configure
23
20
  KeycloakAdmin.configure do |config|
24
21
  config.use_service_account = true
25
- config.server_url = ENV["KEYCLOAK_SERVER_URL"]
26
- config.server_domain = ENV["KEYCLOAK_SERVER_DOMAIN"]
27
- config.client_id = ENV["KEYCLOAK_ADMIN_CLIENT_ID"]
28
- config.client_realm_name = ENV["KEYCLOAK_ADMIN_REALM_NAME"]
29
- config.client_secret = ENV["KEYCLOAK_ADMIN_CLIENT_SECRET"]
22
+ config.server_url = RailsKeycloakAuthorization.keycloak_server_url
23
+ config.server_domain = RailsKeycloakAuthorization.keycloak_server_domain
24
+ config.client_realm_name = RailsKeycloakAuthorization.keycloak_admin_realm_name
25
+ config.client_id = RailsKeycloakAuthorization.keycloak_admin_client_id
26
+ config.client_secret = RailsKeycloakAuthorization.keycloak_admin_client_secret
30
27
  config.logger = Rails.logger
31
28
  config.rest_client_options = { timeout: 3, verify_ssl: Rails.env.production? }
32
29
  end
@@ -12,7 +12,7 @@ module RailsKeycloakAuthorization
12
12
  end
13
13
 
14
14
  def create
15
- KeycloakAdminRubyAgent.create_keycloak_policy(params[:keycloak_realm_role_id])
15
+ KeycloakAdminRubyAgent.create_keycloak_policy(params[:keycloak_realm_role_id], params[:keycloak_policy_name])
16
16
  redirect_to policies_path
17
17
  end
18
18
  end
@@ -35,11 +35,11 @@ module RailsKeycloakAuthorization
35
35
  .find_by(POLICY_NAME, "role")
36
36
  end
37
37
 
38
- def create_keycloak_policy(keycloak_realm_role_id)
38
+ def create_keycloak_policy(keycloak_realm_role_id, policy_name)
39
39
  KeycloakAdmin
40
40
  .realm(realm_name)
41
41
  .authz_policies(openid_client.id, 'role')
42
- .create!("#{POLICY_NAME}",
42
+ .create!(policy_name,
43
43
  "#{POLICY_NAME} default policy",
44
44
  "role",
45
45
  "POSITIVE",
@@ -124,13 +124,13 @@ module RailsKeycloakAuthorization
124
124
  def keycloak_admin_configure
125
125
  KeycloakAdmin.configure do |config|
126
126
  config.use_service_account = true
127
- config.server_url = ENV.fetch("KEYCLOAK_SERVER_URL")
128
- config.server_domain = ENV.fetch("KEYCLOAK_SERVER_DOMAIN")
129
- config.client_id = ENV.fetch("KEYCLOAK_ADMIN_CLIENT_ID")
130
- config.client_realm_name = ENV.fetch("KEYCLOAK_ADMIN_REALM_NAME")
131
- config.client_secret = ENV.fetch("KEYCLOAK_ADMIN_CLIENT_SECRET")
132
- config.logger = Rails.logger
133
- config.rest_client_options = { timeout: 5, verify_ssl: Rails.env.production? }
127
+ config.server_url = RailsKeycloakAuthorization.keycloak_server_url
128
+ config.server_domain = RailsKeycloakAuthorization.keycloak_server_domain
129
+ config.client_realm_name = RailsKeycloakAuthorization.keycloak_admin_realm_name
130
+ config.client_id = RailsKeycloakAuthorization.keycloak_admin_client_id
131
+ config.client_secret = RailsKeycloakAuthorization.keycloak_admin_client_secret
132
+ config.logger = Rails.logger
133
+ config.rest_client_options = { timeout: 3, verify_ssl: Rails.env.production? }
134
134
  end
135
135
  end
136
136
  end
@@ -1,23 +1,34 @@
1
- <h1 class="text-center text-gray-500">Policies</h1>
2
- <% if @policies.empty? %>
3
- <p class="inline">Default Policy for </p>
4
- <form class="inline" hx-post="<%= policies_path %>">
1
+ <div id="policies">
2
+ <h1 class="text-center text-gray-500">Policies</h1>
3
+
4
+ <% @policies.map do |policy| %>
5
+ <div class="mt-2">
6
+ <p>Policy Name: <%= policy.name %></p>
7
+ <p>Policy Roles:</p>
8
+ <% policy.roles.map do |role| %>
9
+ <% realm_role = @realm_roles.first{|rr| rr.id == rold.id } %>
10
+ <ul class="list-disc list-inside">
11
+ <li><%= realm_role.name %></li>
12
+ </ul>
13
+ <% end %>
14
+ </div>
15
+ <% end %>
16
+
17
+ <hr class="mb-6 mt-6"/>
18
+
19
+ <form class="inline" hx-post="<%= policies_path %>" hx-target="#policies">
20
+ <label for="keycloak_policy_name">Name</label>
5
21
  <input id="keycloak_policy_name" name="keycloak_policy_name" value="<%= @default_policy_name %>" type="text">
6
22
  <label for="keycloak_realm_role">Role</label>
7
23
  <select name="keycloak_realm_role_id" hx-indicator=".htmx-indicator">
8
24
  <% @realm_roles.map do |role| %>
9
25
  <option value="<%= role.id %>" <%= role.name.include?("default") ? "selected=selected" : "" %>>
10
- <%= role.name %>
26
+ <%= role.name %>
11
27
  </option>
12
28
  <% end %>
13
29
  </select>
14
30
  <button
15
- class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
16
- type="submit">Create</button>
31
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
32
+ type="submit">Create</button>
17
33
  </form>
18
- <% else %>
19
- <div class="text-gray-500">Current Policy</div>
20
- <% @policies.map do |policy| %>
21
- <p><%= policy.name %></p>
22
- <% end %>
23
- <% end %>
34
+ </div>
@@ -1,8 +1,12 @@
1
1
  module RailsKeycloakAuthorization
2
2
  class Engine < ::Rails::Engine
3
+ require 'keycloak-admin'
3
4
  isolate_namespace RailsKeycloakAuthorization
4
5
  initializer "rails_keycloak_authorization.middleware" do |app|
5
6
  app.middleware.use RailsKeycloakAuthorization::Middleware
6
7
  end
8
+ initializer "rails_keycloak_authorization.assets.precompile" do |app|
9
+ app.config.assets.precompile += %w( rails_keycloak_authorization/application.css )
10
+ end
7
11
  end
8
12
  end
@@ -1,3 +1,3 @@
1
1
  module RailsKeycloakAuthorization
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -2,12 +2,14 @@ require "rails_keycloak_authorization/version"
2
2
  require "rails_keycloak_authorization/engine"
3
3
 
4
4
  module RailsKeycloakAuthorization
5
- mattr_accessor :keycloak_realm
6
5
  mattr_accessor :keycloak_server_url
7
- mattr_accessor :keycloak_admin_username
8
- mattr_accessor :keycloak_admin_password
6
+ mattr_accessor :keycloak_server_domain
7
+ mattr_accessor :keycloak_admin_realm_name
8
+ mattr_accessor :keycloak_admin_client_id
9
+ mattr_accessor :keycloak_admin_client_secret
10
+ mattr_accessor :keycloak_auth_client_id
11
+ mattr_accessor :keycloak_auth_client_realm_name
9
12
  mattr_accessor :match_patterns
10
- mattr_accessor :client_id
11
13
 
12
14
  class Middleware
13
15
  def initialize(app)
@@ -36,7 +38,7 @@ module RailsKeycloakAuthorization
36
38
 
37
39
  def authorize!(request_uri, http_authorization)
38
40
  route = Rails.application.routes.recognize_path(request_uri)
39
- uri = uri(RailsKeycloakAuthorization.keycloak_server_url, RailsKeycloakAuthorization.keycloak_realm)
41
+ uri = uri(RailsKeycloakAuthorization.keycloak_server_url, RailsKeycloakAuthorization.keycloak_auth_client_realm_name)
40
42
  request = http_request(uri, http_authorization, route)
41
43
  response = http_client(uri).request(request)
42
44
  response.is_a?(Net::HTTPSuccess)
@@ -49,7 +51,7 @@ module RailsKeycloakAuthorization
49
51
  })
50
52
  permission = "#{route[:controller]}_controller##{route[:action]}"
51
53
  request.body = URI.encode_www_form({
52
- audience: "#{RailsKeycloakAuthorization.client_id}",
54
+ audience: "#{RailsKeycloakAuthorization.keycloak_auth_client_id}",
53
55
  grant_type: grant_type,
54
56
  permission: permission,
55
57
  response_mode: "permissions",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_keycloak_authorization
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mohammed O. Tillawy
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 1980-01-01 00:00:00.000000000 Z
11
+ date: 2024-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -106,7 +106,7 @@ metadata:
106
106
  homepage_uri: https://github.com/tillawy/rails_keycloak_authorization.git
107
107
  source_code_uri: https://github.com/tillawy/rails_keycloak_authorization.git
108
108
  changelog_uri: https://github.com/tillawy/rails_keycloak_authorization.git
109
- post_install_message:
109
+ post_install_message:
110
110
  rdoc_options: []
111
111
  require_paths:
112
112
  - lib
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
122
  version: '0'
123
123
  requirements: []
124
124
  rubygems_version: 3.5.11
125
- signing_key:
125
+ signing_key:
126
126
  specification_version: 4
127
127
  summary: RailsKeycloakAuthorization, Rack Based, Policy Enforcement Point (PEP) implementation
128
128
  test_files: []