fix: create email inbox when Microsoft id_token has no email claim
This commit is contained in:
@@ -21,4 +21,11 @@ class Microsoft::CallbacksController < OauthCallbackController
|
||||
def imap_login_identity
|
||||
users_data['preferred_username'] || users_data['upn'] || super
|
||||
end
|
||||
|
||||
# Prefer the actual `email` claim. Microsoft work/school accounts without a mailbox
|
||||
# omit it, returning only `preferred_username`/`upn`; fall back to those so inbox
|
||||
# creation does not fail on a null email.
|
||||
def email_address
|
||||
super || users_data['preferred_username'] || users_data['upn']
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,7 +41,7 @@ class OauthCallbackController < ApplicationController
|
||||
end
|
||||
|
||||
def find_channel_by_email
|
||||
Channel::Email.find_by(email: users_data['email'], account: account)
|
||||
Channel::Email.find_by(email: email_address, account: account)
|
||||
end
|
||||
|
||||
def update_channel(channel_email)
|
||||
@@ -64,6 +64,13 @@ class OauthCallbackController < ApplicationController
|
||||
users_data['email']
|
||||
end
|
||||
|
||||
# Email address stored on the Channel::Email record and used to match an existing
|
||||
# channel. Defaults to the id_token's `email` claim; providers override when that
|
||||
# claim can be absent and a different one carries the address.
|
||||
def email_address
|
||||
users_data['email']
|
||||
end
|
||||
|
||||
def provider_name
|
||||
raise NotImplementedError
|
||||
end
|
||||
@@ -74,7 +81,7 @@ class OauthCallbackController < ApplicationController
|
||||
|
||||
def create_channel_with_inbox
|
||||
ActiveRecord::Base.transaction do
|
||||
channel_email = Channel::Email.create!(email: users_data['email'], account: account)
|
||||
channel_email = Channel::Email.create!(email: email_address, account: account)
|
||||
|
||||
account.inboxes.create!(
|
||||
account: account,
|
||||
@@ -119,7 +126,7 @@ class OauthCallbackController < ApplicationController
|
||||
|
||||
# Fallback name, for when name field is missing from users_data
|
||||
def fallback_name
|
||||
users_data['email'].split('@').first.parameterize.titleize
|
||||
email_address.to_s.split('@').first.parameterize.titleize
|
||||
end
|
||||
|
||||
def oauth_code
|
||||
|
||||
@@ -53,6 +53,26 @@ RSpec.describe 'Microsoft::CallbacksController', type: :request do
|
||||
expect(channel.email).to eq mailbox
|
||||
end
|
||||
|
||||
it 'falls back to preferred_username for the channel email when the id_token has no email claim' do
|
||||
upn = 'testaccount@primary-domain.example'
|
||||
response_body = {
|
||||
id_token: JWT.encode({ preferred_username: upn, name: 'test' }, nil, 'none'),
|
||||
access_token: SecureRandom.hex(10), token_type: 'Bearer', refresh_token: SecureRandom.hex(10)
|
||||
}
|
||||
stub_request(:post, 'https://login.microsoftonline.com/common/oauth2/v2.0/token')
|
||||
.with(body: { 'code' => code, 'grant_type' => 'authorization_code',
|
||||
'redirect_uri' => "#{ENV.fetch('FRONTEND_URL', 'http://localhost:3000')}/microsoft/callback" })
|
||||
.to_return(status: 200, body: response_body.to_json, headers: { 'Content-Type' => 'application/json' })
|
||||
|
||||
get microsoft_callback_url, params: { code: code, state: state }
|
||||
|
||||
expect(response).to redirect_to app_email_inbox_agents_url(account_id: account.id, inbox_id: account.inboxes.last.id)
|
||||
expect(account.inboxes.count).to be 1
|
||||
channel = account.inboxes.last.channel
|
||||
expect(channel.email).to eq upn
|
||||
expect(channel.imap_login).to eq upn
|
||||
end
|
||||
|
||||
it 'creates updates inbox channel config if inbox exists and authentication is successful' do
|
||||
inbox = create(:channel_email, account: account, email: email)&.inbox
|
||||
expect(inbox.channel.provider_config).to eq({})
|
||||
|
||||
Reference in New Issue
Block a user