diff --git a/modules/openid_connect/app/components/openid_connect/providers/client_details_form.rb b/modules/openid_connect/app/components/openid_connect/providers/client_details_form.rb index 8c945ac679aa..609c3304381f 100644 --- a/modules/openid_connect/app/components/openid_connect/providers/client_details_form.rb +++ b/modules/openid_connect/app/components/openid_connect/providers/client_details_form.rb @@ -29,6 +29,8 @@ module OpenIDConnect module Providers class ClientDetailsForm < BaseForm + include Redmine::I18n + form do |f| %i[client_id client_secret].each do |attr| f.text_field( @@ -48,6 +50,20 @@ class ClientDetailsForm < BaseForm required: false, input_width: :large ) + f.text_field( + name: :scope, + label: I18n.t("activemodel.attributes.openid_connect/provider.scope"), + placeholder: "openid email profile", + caption: link_translate( + "openid_connect.instructions.scope", + links: { + docs_url: "https://openid.net/specs/openid-connect-basic-1_0.html#Scopes" + } + ), + disabled: provider.seeded_from_env?, + required: false, + input_width: :large + ) f.check_box( name: :limit_self_registration, label: I18n.t("activemodel.attributes.openid_connect/provider.limit_self_registration"), diff --git a/modules/openid_connect/app/models/openid_connect/provider.rb b/modules/openid_connect/app/models/openid_connect/provider.rb index 18fa645b5150..c61e5b04589a 100644 --- a/modules/openid_connect/app/models/openid_connect/provider.rb +++ b/modules/openid_connect/app/models/openid_connect/provider.rb @@ -31,6 +31,7 @@ class Provider < AuthProvider store_attribute :options, :scheme, :string store_attribute :options, :port, :string + store_attribute :options, :scope, :string store_attribute :options, :claims, :string store_attribute :options, :acr_values, :string diff --git a/modules/openid_connect/app/models/openid_connect/provider/hash_builder.rb b/modules/openid_connect/app/models/openid_connect/provider/hash_builder.rb index 601867a80d1c..0beea596b22e 100644 --- a/modules/openid_connect/app/models/openid_connect/provider/hash_builder.rb +++ b/modules/openid_connect/app/models/openid_connect/provider/hash_builder.rb @@ -19,6 +19,7 @@ def to_h # rubocop:disable Metrics/AbcSize authorization_endpoint:, jwks_uri:, issuer:, + scope:, identifier: client_id, secret: client_secret, token_endpoint:, diff --git a/modules/openid_connect/app/services/openid_connect/configuration_mapper.rb b/modules/openid_connect/app/services/openid_connect/configuration_mapper.rb index 5ee45847c192..bd9f5247febe 100644 --- a/modules/openid_connect/app/services/openid_connect/configuration_mapper.rb +++ b/modules/openid_connect/app/services/openid_connect/configuration_mapper.rb @@ -53,6 +53,7 @@ def call! # rubocop:disable Metrics/AbcSize "limit_self_registration" => options["limit_self_registration"], "use_graph_api" => options["use_graph_api"], "acr_values" => options["acr_values"], + "scope" => extract_scope(options["scope"]), "authorization_endpoint" => extract_url(options, "authorization_endpoint"), "token_endpoint" => extract_url(options, "token_endpoint"), "userinfo_endpoint" => extract_url(options, "userinfo_endpoint"), @@ -68,6 +69,17 @@ def call! # rubocop:disable Metrics/AbcSize private + def extract_scope(value) + return if value.blank? + + case value + when Array + value.join(" ") + else + value + end + end + def oidc_provider(options) case options["name"] when /azure/ diff --git a/modules/openid_connect/config/locales/en.yml b/modules/openid_connect/config/locales/en.yml index ed720f91b4bb..03d0ab584753 100644 --- a/modules/openid_connect/config/locales/en.yml +++ b/modules/openid_connect/config/locales/en.yml @@ -66,6 +66,7 @@ en: limit_self_registration: If enabled, users can only register using this provider if configuration on the provider's end allows it. display_name: The name of the provider. This will be displayed as the login button and in the list of providers. tenant: Please replace the default tenant with your own if applicable. See this. + scope: If you want to request custom scopes, you can add one or multiple scope values separated by spaces here. For more information, see the [OpenID Connect documentation](docs_url). post_logout_redirect_uri: The URL the OpenID Connect provider should redirect to after a logout request. claims: > You can request additional claims for the userinfo and id token endpoints. Please see [our OpenID connect documentation](docs_url) for more information. diff --git a/modules/openid_connect/spec/features/administration/oidc_custom_crud_spec.rb b/modules/openid_connect/spec/features/administration/oidc_custom_crud_spec.rb index 714723041076..ab1f0cd42cac 100644 --- a/modules/openid_connect/spec/features/administration/oidc_custom_crud_spec.rb +++ b/modules/openid_connect/spec/features/administration/oidc_custom_crud_spec.rb @@ -64,6 +64,9 @@ fill_in "Client ID", with: "client_id" fill_in "Client secret", with: "client secret" + # Scope + fill_in "Scope", with: "custom_scope another_scope" + click_link_or_button "Continue" # Mapping form diff --git a/modules/openid_connect/spec/migration/migrate_oidc_settings_to_providers_spec.rb b/modules/openid_connect/spec/migration/migrate_oidc_settings_to_providers_spec.rb index 045779278060..2938dbb23c3c 100644 --- a/modules/openid_connect/spec/migration/migrate_oidc_settings_to_providers_spec.rb +++ b/modules/openid_connect/spec/migration/migrate_oidc_settings_to_providers_spec.rb @@ -107,6 +107,7 @@ class TestOpenIDConnectProvider < OpenIDConnect::Provider host: "localhost", port: "8080", scheme: "http", + scope: ["foo", "bar"], identifier: "http://localhost:3000", secret: "IVl6GxxujAQ3mt6thAXKxyYYvmyRr8jw", issuer: "http://localhost:8080/realms/test", @@ -129,6 +130,7 @@ class TestOpenIDConnectProvider < OpenIDConnect::Provider expect(provider.host).to eq "localhost" expect(provider.port).to eq "8080" expect(provider.scheme).to eq "http" + expect(provider.scope).to eq "foo bar" expect(provider.client_id).to eq "http://localhost:3000" expect(provider.client_secret).to eq "IVl6GxxujAQ3mt6thAXKxyYYvmyRr8jw" expect(provider.issuer).to eq "http://localhost:8080/realms/test" diff --git a/modules/openid_connect/spec/services/openid_connect/configuration_mapper_spec.rb b/modules/openid_connect/spec/services/openid_connect/configuration_mapper_spec.rb index e5dd3128f681..e8daef6db17e 100644 --- a/modules/openid_connect/spec/services/openid_connect/configuration_mapper_spec.rb +++ b/modules/openid_connect/spec/services/openid_connect/configuration_mapper_spec.rb @@ -98,6 +98,28 @@ end end + describe "scope" do + subject { result } + + context "when provided" do + let(:configuration) { { scope: "custom" } } + + it { is_expected.to include("scope" => "custom") } + end + + context "when provided as array" do + let(:configuration) { { scope: ["foo", "bar"] } } + + it { is_expected.to include("scope" => "foo bar") } + end + + context "when not provided" do + let(:configuration) { { foo: "bar" } } + + it { is_expected.not_to have_key("scope") } + end + end + describe "issuer" do subject { result }