Skip to content

Commit 7549432

Browse files
committed
feat: remove unused components
initial implementation of openid connect
1 parent 078749c commit 7549432

11 files changed

Lines changed: 181 additions & 13 deletions

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ gem "redis"
1919

2020
# Authentication
2121
gem "doorkeeper", "~> 5.8"
22+
gem "doorkeeper-openid_connect"
2223
gem "doorkeeper-jwt"
2324
gem "jwt"
2425
gem "nkf" # required for omniauth-oauth2 in Ruby 3.4

Gemfile.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ GEM
105105
railties (>= 5)
106106
doorkeeper-jwt (0.4.2)
107107
jwt (>= 2.1)
108+
doorkeeper-openid_connect (1.8.11)
109+
doorkeeper (>= 5.5, < 5.9)
110+
jwt (>= 2.5)
111+
ostruct (>= 0.5)
108112
drb (2.2.3)
109113
email_validator (2.2.4)
110114
activemodel
@@ -322,6 +326,7 @@ DEPENDENCIES
322326
debug
323327
doorkeeper (~> 5.8)
324328
doorkeeper-jwt
329+
doorkeeper-openid_connect
325330
email_validator
326331
jwt
327332
lograge

config/application.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
require_relative "boot"
22

3-
require "rails/all"
3+
require "rails"
4+
# Pick the frameworks you want:
5+
require "active_model/railtie"
6+
require "active_job/railtie"
7+
require "active_record/railtie"
8+
# require "active_storage/engine"
9+
require "action_controller/railtie"
10+
require "action_mailer/railtie"
11+
# require "action_mailbox/engine"
12+
# require "action_text/engine"
13+
require "action_view/railtie"
14+
require "action_cable/engine"
15+
# require "rails/test_unit/railtie"
416

517
# Require the gems listed in Gemfile, including any gems
618
# you've limited to :test, :development, or :production.

config/environments/development.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@
2828
# Change to :null_store to avoid any caching.
2929
config.cache_store = :null_store
3030

31-
# Store uploaded files on the local file system (see config/storage.yml for options).
32-
config.active_storage.service = :local
33-
3431
# Don't care if the mailer can't send.
3532
config.action_mailer.raise_delivery_errors = false
3633

config/environments/production.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,6 @@ def initialize(*targets)
5656
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
5757
# config.asset_host = "http://assets.example.com"
5858

59-
# Store uploaded files on the local file system (see config/storage.yml for options).
60-
config.active_storage.service = :local
61-
6259
# Assume all access to the app is happening through a SSL-terminating reverse proxy.
6360
# config.assume_ssl = true
6461

config/environments/test.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@
2828
# Disable request forgery protection in test environment.
2929
config.action_controller.allow_forgery_protection = false
3030

31-
# Store uploaded files on the local file system in a temporary directory.
32-
config.active_storage.service = :test
33-
3431
# Tell Action Mailer not to deliver emails to the real world.
3532
# The :test delivery method accumulates sent emails in the
3633
# ActionMailer::Base.deliveries array.

config/initializers/doorkeeper.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,20 @@
7979
"public",
8080

8181
# these can be found via: GET /api/engine/v2/scopes
82+
"alert_dashboards",
83+
"alerts",
8284
"api_keys",
85+
"asset_categories",
86+
"asset_purchase_orders",
87+
"asset_types",
8388
"asset_instances",
8489
"assets",
8590
"ldap_authentications",
8691
"saml_authentications",
8792
"o_auth_authentications",
8893
"brokers",
94+
"build_monitor",
95+
"chat_gpt",
8996
"cluster",
9097
"domains",
9198
"drivers",
@@ -95,20 +102,24 @@
95102
"guest",
96103
"control",
97104
"edges",
105+
"edge-control",
98106
"metadata",
99107
"mqtt",
100108
"flux",
101109
"o_auth_applications",
102-
"repositories"
103-
].map { |scope| [scope, "#{scope}.read", "#{scope}.write"] }.flatten
110+
"repositories",
111+
].map { |scope| [scope, "#{scope}.read", "#{scope}.write"] }.flatten + [
112+
# this is required for OpenID connect
113+
"openid"
114+
]
104115

105116
default_scopes :public
106117
optional_scopes(*all_scopes)
107118

108119
access_token_generator "::Doorkeeper::JWT"
109120

110121
force_ssl_in_redirect_uri false
111-
grant_flows %w[authorization_code client_credentials implicit password]
122+
grant_flows %w[authorization_code client_credentials implicit password implicit_oidc]
112123
end
113124

114125
Doorkeeper::JWT.configure do
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# frozen_string_literal: true
2+
3+
require "uri"
4+
5+
Doorkeeper::OpenidConnect.configure do
6+
issuer do |resource_owner, application|
7+
"https://#{URI.parse(application.redirect_uri).host}"
8+
end
9+
10+
# Set the encryption secret. This would be shared with any other applications
11+
# that should be able to read the payload of the token. Defaults to "secret".
12+
key = ENV["JWT_SECRET"]
13+
key = key.try { |k| Base64.decode64(k) } || DEV_KEY
14+
signing_key key
15+
16+
subject_types_supported [:public]
17+
18+
resource_owner_from_access_token do |access_token|
19+
User.find_by(id: access_token.resource_owner_id)
20+
end
21+
22+
auth_time_from_resource_owner do |resource_owner|
23+
resource_owner.last_login
24+
end
25+
26+
reauthenticate_resource_owner do |resource_owner, return_to|
27+
# Example implementation:
28+
# store_location_for resource_owner, return_to
29+
# sign_out resource_owner
30+
# redirect_to new_user_session_url
31+
domain = "https://#{request.host}"
32+
authority = Authority.find_by_domain(request.host)
33+
url = authority.login_url.gsub("{{url}}", URI.encode_uri_component(return_to))
34+
35+
redirect_to "#{domain}#{url}"
36+
end
37+
38+
# Depending on your configuration, a DoubleRenderError could be raised
39+
# if render/redirect_to is called at some point before this callback is executed.
40+
# To avoid the DoubleRenderError, you could add these two lines at the beginning
41+
# of this callback: (Reference: https://github.com/rails/rails/issues/25106)
42+
# self.response_body = nil
43+
# @_response_body = nil
44+
select_account_for_resource_owner do |resource_owner, return_to|
45+
self.response_body = nil
46+
@_response_body = nil
47+
48+
# there is no account selection in PlaceOS
49+
redirect_to return_to
50+
end
51+
52+
subject do |resource_owner, application|
53+
# Example implementation:
54+
# resource_owner.id
55+
56+
# or if you need pairwise subject identifier, implement like below:
57+
# Digest::SHA256.hexdigest("#{resource_owner.id}#{URI.parse(application.redirect_uri).host}#{'your_secret_salt'}")
58+
59+
resource_owner.id
60+
end
61+
62+
end_session_endpoint do
63+
authority = Authority.find_by_domain(request.host)
64+
authority.logout_url
65+
end
66+
67+
# Protocol to use when generating URIs for the discovery endpoint,
68+
# for example if you also use HTTPS in development
69+
# protocol do
70+
# :https
71+
# end
72+
73+
# Expiration time on or after which the ID Token MUST NOT be accepted for processing. (default 120 seconds).
74+
# expiration 600
75+
76+
claims do
77+
claim :sub do |resource_owner|
78+
resource_owner.id
79+
end
80+
81+
claim :email do |resource_owner|
82+
resource_owner.email
83+
end
84+
85+
claim :full_name do |resource_owner|
86+
resource_owner.name
87+
end
88+
89+
claim :given_name do |resource_owner|
90+
resource_owner.first_name
91+
end
92+
93+
claim :family_name do |resource_owner|
94+
resource_owner.last_name
95+
end
96+
97+
claim :nickname do |resource_owner|
98+
resource_owner.nickname
99+
end
100+
101+
claim :phone_number do |resource_owner|
102+
resource_owner.phone
103+
end
104+
105+
claim :preferred_username do |resource_owner|
106+
resource_owner.login_name || resource_owner.email
107+
end
108+
end
109+
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
en:
2+
doorkeeper:
3+
scopes:
4+
openid: 'Authenticate your account'
5+
profile: 'View your profile information'
6+
email: 'View your email address'
7+
address: 'View your physical address'
8+
phone: 'View your phone number'
9+
errors:
10+
messages:
11+
login_required: 'The authorization server requires end-user authentication'
12+
consent_required: 'The authorization server requires end-user consent'
13+
interaction_required: 'The authorization server requires end-user interaction'
14+
account_selection_required: 'The authorization server requires end-user account selection'
15+
openid_connect:
16+
errors:
17+
messages:
18+
# Configuration error messages
19+
resource_owner_from_access_token_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.resource_owner_from_access_token missing configuration.'
20+
auth_time_from_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.auth_time_from_resource_owner missing configuration.'
21+
reauthenticate_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.reauthenticate_resource_owner missing configuration.'
22+
select_account_for_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.select_account_for_resource_owner missing configuration.'
23+
subject_not_configured: 'ID Token generation failed due to Doorkeeper::OpenidConnect.configure.subject missing configuration.'

config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
scope :auth do
55
use_doorkeeper
6+
use_doorkeeper_openid_connect
67

78
get "/login", to: "auth/sessions#new" # for defining continue
89
get "/logout", to: "auth/sessions#destroy" # deletes the session

0 commit comments

Comments
 (0)