diff --git a/app/controllers/api/v1/accounts/google/authorizations_controller.rb b/app/controllers/api/v1/accounts/google/authorizations_controller.rb index 1140a214b..ccd3655fb 100644 --- a/app/controllers/api/v1/accounts/google/authorizations_controller.rb +++ b/app/controllers/api/v1/accounts/google/authorizations_controller.rb @@ -3,7 +3,6 @@ class Api::V1::Accounts::Google::AuthorizationsController < Api::V1::Accounts::B before_action :check_authorization def create - email = params[:authorization][:email] redirect_url = google_client.auth_code.authorize_url( { redirect_uri: "#{base_url}/google/callback", @@ -11,19 +10,24 @@ class Api::V1::Accounts::Google::AuthorizationsController < Api::V1::Accounts::B response_type: 'code', prompt: 'consent', # the oauth flow does not return a refresh token, this is supposed to fix it access_type: 'offline', # the default is 'online' + state: state, client_id: GlobalConfigService.load('GOOGLE_OAUTH_CLIENT_ID', nil) } ) if redirect_url - cache_key = "google::#{email.downcase}" - ::Redis::Alfred.setex(cache_key, Current.account.id, 5.minutes) render json: { success: true, url: redirect_url } else render json: { success: false }, status: :unprocessable_entity end end + def state + # return a signed id for the current account + # this is cryptographically verifyable + Current.account.to_sgid(expires_in: 15.minutes).to_s + end + private def check_authorization diff --git a/app/controllers/api/v1/accounts/microsoft/authorizations_controller.rb b/app/controllers/api/v1/accounts/microsoft/authorizations_controller.rb index df563094a..9eb4ffd5a 100644 --- a/app/controllers/api/v1/accounts/microsoft/authorizations_controller.rb +++ b/app/controllers/api/v1/accounts/microsoft/authorizations_controller.rb @@ -3,23 +3,27 @@ class Api::V1::Accounts::Microsoft::AuthorizationsController < Api::V1::Accounts before_action :check_authorization def create - email = params[:authorization][:email] redirect_url = microsoft_client.auth_code.authorize_url( { redirect_uri: "#{base_url}/microsoft/callback", scope: 'offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send openid profile', + state: state, prompt: 'consent' } ) if redirect_url - cache_key = "microsoft::#{email.downcase}" - ::Redis::Alfred.setex(cache_key, Current.account.id, 5.minutes) render json: { success: true, url: redirect_url } else render json: { success: false }, status: :unprocessable_entity end end + def state + # return a signed id for the current account + # this is cryptographically verifyable + Current.account.to_sgid(expires_in: 15.minutes).to_s + end + private def check_authorization diff --git a/app/controllers/oauth_callback_controller.rb b/app/controllers/oauth_callback_controller.rb index 4cb02d266..d4f4d53e7 100644 --- a/app/controllers/oauth_callback_controller.rb +++ b/app/controllers/oauth_callback_controller.rb @@ -6,7 +6,6 @@ class OauthCallbackController < ApplicationController ) handle_response - ::Redis::Alfred.delete(cache_key) rescue StandardError => e ChatwootExceptionTracker.new(e).capture_exception redirect_to '/' @@ -64,10 +63,6 @@ class OauthCallbackController < ApplicationController raise NotImplementedError end - def cache_key - "#{provider_name}::#{users_data['email'].downcase}" - end - def create_channel_with_inbox ActiveRecord::Base.transaction do channel_email = Channel::Email.create!(email: users_data['email'], account: account) @@ -85,12 +80,14 @@ class OauthCallbackController < ApplicationController decoded_token[0] end - def account_id - ::Redis::Alfred.get(cache_key) + def account_from_signed_id + raise 'Missing state variable' if params[:state].blank? + + GlobalID::Locator.locate_signed(params[:state]) end def account - @account ||= Account.find(account_id) + @account ||= account_from_signed_id end # Fallback name, for when name field is missing from users_data diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Google.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Google.vue index 1628d3e62..a5c16fa57 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Google.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Google.vue @@ -12,7 +12,6 @@ defineOptions({ provider="google" :title="$t('INBOX_MGMT.ADD.GOOGLE.TITLE')" :description="$t('INBOX_MGMT.ADD.GOOGLE.DESCRIPTION')" - :input-placeholder="$t('INBOX_MGMT.ADD.GOOGLE.EMAIL_PLACEHOLDER')" :submit-button-text="$t('INBOX_MGMT.ADD.GOOGLE.SIGN_IN')" :error-message="$t('INBOX_MGMT.ADD.GOOGLE.ERROR_MESSAGE')" /> diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Microsoft.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Microsoft.vue index 1e3706297..53cf5ccc7 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Microsoft.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Microsoft.vue @@ -12,7 +12,6 @@ defineOptions({ provider="microsoft" :title="$t('INBOX_MGMT.ADD.MICROSOFT.TITLE')" :description="$t('INBOX_MGMT.ADD.MICROSOFT.DESCRIPTION')" - :input-placeholder="$t('INBOX_MGMT.ADD.MICROSOFT.EMAIL_PLACEHOLDER')" :submit-button-text="$t('INBOX_MGMT.ADD.MICROSOFT.SIGN_IN')" :error-message="$t('INBOX_MGMT.ADD.MICROSOFT.ERROR_MESSAGE')" /> diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/OAuthChannel.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/OAuthChannel.vue index eb109c6f2..f2bfb63f3 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/OAuthChannel.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/OAuthChannel.vue @@ -30,14 +30,9 @@ const props = defineProps({ type: String, required: true, }, - inputPlaceholder: { - type: String, - required: true, - }, }); const isRequestingAuthorization = ref(false); -const email = ref(''); const client = computed(() => { if (props.provider === 'microsoft') { @@ -50,9 +45,7 @@ const client = computed(() => { async function requestAuthorization() { try { isRequestingAuthorization.value = true; - const response = await client.value.generateAuthorization({ - email: email.value, - }); + const response = await client.value.generateAuthorization(); const { data: { url }, } = response; @@ -75,11 +68,6 @@ async function requestAuthorization() { :header-content="description" />
-