Closed almathie closed 2 years ago
Haven't tried it myself, but noticed this solution in one of the closed issues: https://github.com/omniauth/omniauth-okta/issues/19#issuecomment-851922139
Indeed I have been able to solve this using a setup_proc
Code looks like this :
require "omniauth-okta"
# Dynamically load the correct Okta provider configuration based on the request data contained in the request
# This proc is executed by Omniauth only on routes registered by the okta strategy middleware
# See: https://github.com/omniauth/omniauth/wiki/Setup-Phase
okta_setup_proc = proc do |env|
request = Rack::Request.new(env)
# If the proc is executed during the request phase -> Look for tenant name in a `tenant` params
# If the proc is executed during the callback phase -> Extract tenant name from the `state` params
tenant = if request.params["tenant"]
tenant = request.params["tenant"]
elsif request.params["state"]
tenant = request.params["state"].split("|").first # See state setting below
end
tenant = Rails.application.config_for("sso")[:okta_providers].find { |provider| provider[:name] == tenant }
return [404, { "Content-Type" => "text/html" }, ["Okta tenant not found"]] unless tenant
# Override omniauth strategy config by tenant config
env["omniauth.strategy"].options[:client_id] = tenant[:client_id]
env["omniauth.strategy"].options[:client_secret] = tenant[:client_secret]
env["omniauth.strategy"].options[:client_options] = {
site: tenant[:site],
authorize_url: tenant[:authorize_url] || "#{tenant[:site]}/oauth2/v1/authorize",
token_url: tenant[:token_url] || "#{tenant[:site]}/oauth2/v1/token",
user_info_url: tenant[:user_info_url] || "#{tenant[:site]}/oauth2/v1/userinfo"
}
env["omniauth.strategy"].options[:state] = "#{tenant[:name]}|#{SecureRandom.hex(16)}"
end
# Load the okta strategy middleware
config.omniauth(:okta, nil, nil, scope: "openid profile email",
fields: %w[profile email],
strategy_class: OmniAuth::Strategies::Okta,
setup: okta_setup_proc)
Okta is quite explicit about their view on multi-tenancy (See: https://developer.okta.com/docs/guides/build-sso-integration/openidconnect/main/#multi-tenancy). They mandate full support of multi-tenancy to be added in the approved list of integration (the OIN network).
A typical SAAS service that serves B2B customers - who might be using Okta as their identity provider - will have to manage many
client_id
,secret
, andsite
. Typically, one per customer using Okta, or even more than one according to the doc above.As far as I can see, the config needs to be set in an initialiser, making it impossible to support multi-tenancy with this library. Is there something I am missing in this strategy that would allow for the config to be dynamically loaded on a customer-per-customer basis ?