From c7e88e20866be0358ac6c13c735ab1734191f01c Mon Sep 17 00:00:00 2001 From: Nat Date: Wed, 31 Jan 2024 12:43:28 +0800 Subject: [PATCH] FEATURE: Allow specifiying required paths when retrieving userinfo --- plugin.rb | 15 ++++++++++++++ spec/plugin_spec.rb | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/plugin.rb b/plugin.rb index 3dc8f72..811f0fc 100644 --- a/plugin.rb +++ b/plugin.rb @@ -78,6 +78,12 @@ end # We'll store the value in the user associated account's extra attribute hash using the full path as the key. DiscoursePluginRegistry.define_filtered_register :oauth2_basic_additional_json_paths +# After authentication, we'll use this to confirm that the registered json paths are fulfilled, +# or display an error message to the user. +# This requires SiteSetting.oauth2_fetch_user_details? to be true, and can be used with +# DiscoursePluginRegistry.oauth2_basic_additional_json_paths. +DiscoursePluginRegistry.define_filtered_register :oauth2_basic_required_json_paths + class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator def name "oauth2_basic" @@ -312,6 +318,15 @@ class ::OAuth2BasicAuthenticator < Auth::ManagedAuthenticator DiscoursePluginRegistry.oauth2_basic_additional_json_paths.each do |detail| auth["extra"][detail] = fetched_user_details["extra:#{detail}"] end + + DiscoursePluginRegistry.oauth2_basic_required_json_paths.each do |x| + if fetched_user_details[x[:path]] != x[:required_value] + result = Auth::Result.new + result.failed = true + result.failed_reason = x[:error_message] + return result + end + end else result = Auth::Result.new result.failed = true diff --git a/spec/plugin_spec.rb b/spec/plugin_spec.rb index 640b6b9..1b60523 100644 --- a/spec/plugin_spec.rb +++ b/spec/plugin_spec.rb @@ -122,6 +122,54 @@ describe OAuth2BasicAuthenticator do expect(associated_account.extra[custom_path]).to eq("received") end end + + describe "required attributes" do + after { DiscoursePluginRegistry.reset_register!(:oauth2_basic_required_json_paths) } + + it "'authenticates' successfully if required json path is fulfilled" do + DiscoursePluginRegistry.register_oauth2_basic_additional_json_path( + "account.is_legit", + Plugin::Instance.new, + ) + DiscoursePluginRegistry.register_oauth2_basic_required_json_path( + { path: "extra:account.is_legit", required_value: true }, + Plugin::Instance.new, + ) + + response = { + status: 200, + body: '{"account":{"email":"newemail@example.com","is_legit":true}}', + } + stub_request(:get, SiteSetting.oauth2_user_json_url).to_return(response) + + result = authenticator.after_authenticate(auth) + expect(result.failed).to eq(false) + end + + it "fails 'authentication' if required json path is unfulfilled" do + DiscoursePluginRegistry.register_oauth2_basic_additional_json_path( + "account.is_legit", + Plugin::Instance.new, + ) + DiscoursePluginRegistry.register_oauth2_basic_required_json_path( + { + path: "extra:account.is_legit", + required_value: true, + error_message: "You're not legit", + }, + Plugin::Instance.new, + ) + response = { + status: 200, + body: '{"account":{"email":"newemail@example.com","is_legit":false}}', + } + stub_request(:get, SiteSetting.oauth2_user_json_url).to_return(response) + + result = authenticator.after_authenticate(auth) + expect(result.failed).to eq(true) + expect(result.failed_reason).to eq("You're not legit") + end + end end describe "avatar downloading" do