From f4b8760e0084f2aa5b487e0b83fbbca6107541d5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 2 Jun 2025 20:17:54 +0530 Subject: [PATCH] feat: handle oauth scope verification and errors --- app/controllers/concerns/google_concern.rb | 2 +- .../google/callbacks_controller.rb | 20 +++++ app/controllers/oauth_callback_controller.rb | 17 ++++- .../settings/inbox/channels/Email.vue | 15 +++- config/locales/en.yml | 5 ++ lib/custom_exceptions/oauth.rb | 74 +++++++++++++++++++ 6 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 lib/custom_exceptions/oauth.rb diff --git a/app/controllers/concerns/google_concern.rb b/app/controllers/concerns/google_concern.rb index 13de7ced3..8b55bc642 100644 --- a/app/controllers/concerns/google_concern.rb +++ b/app/controllers/concerns/google_concern.rb @@ -15,6 +15,6 @@ module GoogleConcern private def scope - 'email profile https://mail.google.com/' + 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://mail.google.com/' end end diff --git a/app/controllers/google/callbacks_controller.rb b/app/controllers/google/callbacks_controller.rb index 766d984df..fd785cb84 100644 --- a/app/controllers/google/callbacks_controller.rb +++ b/app/controllers/google/callbacks_controller.rb @@ -12,6 +12,16 @@ class Google::CallbacksController < OauthCallbackController private + def verify_scopes + granted_scopes = parsed_body['scope']&.split || [] + required_scopes = scope.split + + missing_scopes = required_scopes - granted_scopes + return if missing_scopes.empty? + + raise CustomExceptions::OAuth::InsufficientScopes.new({ missing_scopes: missing_scopes }) + end + def provider_name 'google' end @@ -24,4 +34,14 @@ class Google::CallbacksController < OauthCallbackController # from GoogleConcern google_client end + + def handle_error(exception) + ChatwootExceptionTracker.new(exception).capture_exception + + error_code = exception.respond_to?(:code) ? exception.code : 'OAUTH_ERR' + error_message = exception.message || 'OAuth authorization failed' + + redirect_url = "#{ENV.fetch('FRONTEND_URL', 'http://localhost:3000')}/app/accounts/#{account.id}/settings/inboxes/new/email" + redirect_to "#{redirect_url}?error=#{CGI.escape(error_message)}&code=#{error_code}" + end end diff --git a/app/controllers/oauth_callback_controller.rb b/app/controllers/oauth_callback_controller.rb index e9c327109..75d818efa 100644 --- a/app/controllers/oauth_callback_controller.rb +++ b/app/controllers/oauth_callback_controller.rb @@ -5,10 +5,10 @@ class OauthCallbackController < ApplicationController redirect_uri: "#{base_url}/#{provider_name}/callback" ) + verify_scopes handle_response rescue StandardError => e - ChatwootExceptionTracker.new(e).capture_exception - redirect_to '/' + handle_error(e) end private @@ -63,6 +63,19 @@ class OauthCallbackController < ApplicationController raise NotImplementedError end + def verify_scopes + true + end + + def failure_redirect_url + '/' + end + + def handle_error(exception) + ChatwootExceptionTracker.new(exception).capture_exception + redirect_to failure_redirect_url + end + def create_channel_with_inbox ActiveRecord::Base.transaction do channel_email = Channel::Email.create!(email: users_data['email'], account: account) diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Email.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Email.vue index fe4d7acf3..f60e35f14 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Email.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Email.vue @@ -1,17 +1,21 @@