mirror of
https://github.com/we-promise/sure.git
synced 2026-07-16 14:55:23 +00:00
91 lines
2.9 KiB
Ruby
91 lines
2.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Oidc
|
|
class ProviderOptionsBuilder
|
|
DEFAULT_SCOPES = %i[openid email profile].freeze
|
|
|
|
class << self
|
|
def call(raw_cfg, env: ENV, rails_env: Rails.env, ssl_config: Rails.configuration.x.ssl)
|
|
cfg = raw_cfg.deep_symbolize_keys
|
|
issuer = cfg[:issuer].presence || env["OIDC_ISSUER"].presence
|
|
client_id = cfg[:client_id].presence || env["OIDC_CLIENT_ID"].presence
|
|
client_secret = cfg[:client_secret].presence || env["OIDC_CLIENT_SECRET"].presence
|
|
redirect_uri = cfg[:redirect_uri].presence || env["OIDC_REDIRECT_URI"].presence
|
|
|
|
if rails_env.test?
|
|
issuer ||= "https://test.example.com"
|
|
client_id ||= "test_client_id"
|
|
client_secret ||= "test_client_secret"
|
|
redirect_uri ||= "http://test.example.com/callback"
|
|
end
|
|
|
|
return nil unless issuer.present? && client_id.present? && client_secret.present? && redirect_uri.present?
|
|
|
|
scopes = oidc_scopes(cfg)
|
|
options = {
|
|
name: provider_name(cfg).to_sym,
|
|
scope: scopes,
|
|
response_type: :code,
|
|
issuer: issuer.to_s.strip,
|
|
discovery: true,
|
|
pkce: true,
|
|
client_options: {
|
|
identifier: client_id,
|
|
secret: client_secret,
|
|
redirect_uri: redirect_uri,
|
|
ssl: ssl_options(ssl_config)
|
|
}
|
|
}
|
|
|
|
prompt = cfg.dig(:settings, :prompt).presence
|
|
options[:prompt] = prompt if prompt.present?
|
|
|
|
extra_authorize_params = oidc_extra_authorize_params(cfg, scopes)
|
|
options[:extra_authorize_params] = extra_authorize_params if extra_authorize_params.present?
|
|
|
|
options
|
|
end
|
|
|
|
def oidc_scopes(cfg)
|
|
custom_scopes = cfg.dig(:settings, :scopes).presence
|
|
return DEFAULT_SCOPES unless custom_scopes.present?
|
|
|
|
custom_scopes.to_s.split.map(&:to_sym)
|
|
end
|
|
|
|
private
|
|
def provider_name(cfg)
|
|
(cfg[:name] || cfg[:id]).to_s
|
|
end
|
|
|
|
def oidc_extra_authorize_params(cfg, scopes)
|
|
return {} unless request_groups_claim?(cfg, scopes)
|
|
|
|
# Best-effort OIDC Core claims request. Some IdPs still require
|
|
# provider-side scope/audience mapping before they emit groups.
|
|
{
|
|
claims: JSON.generate(
|
|
id_token: { groups: nil },
|
|
userinfo: { groups: nil }
|
|
)
|
|
}
|
|
end
|
|
|
|
def request_groups_claim?(cfg, scopes)
|
|
scopes.map(&:to_s).include?("groups") || role_mapping(cfg).present?
|
|
end
|
|
|
|
def role_mapping(cfg)
|
|
cfg.dig(:settings, :role_mapping).presence
|
|
end
|
|
|
|
def ssl_options(ssl_config)
|
|
ssl_opts = {}
|
|
ssl_opts[:ca_file] = ssl_config.ca_file if ssl_config&.ca_file.present?
|
|
ssl_opts[:verify] = false if ssl_config&.verify == false
|
|
ssl_opts
|
|
end
|
|
end
|
|
end
|
|
end
|