Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion lib/omniauth/strategies/microsoft_graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class MicrosoftGraph < OmniAuth::Strategies::OAuth2
BASE_SCOPE_URL = 'https://graph.microsoft.com/'
BASE_SCOPES = %w[offline_access openid email profile].freeze
DEFAULT_SCOPE = 'offline_access openid email profile User.Read'.freeze
YAMMER_PROFILE_URL = 'https://www.yammer.com/api/v1/users/current.json'
MICROSOFT_GRAPH_PROFILE_URL = 'https://graph.microsoft.com/v1.0/me'

option :name, :microsoft_graph

Expand Down Expand Up @@ -64,7 +66,7 @@ def authorize_params
end

def raw_info
@raw_info ||= access_token.get('https://graph.microsoft.com/v1.0/me').parsed
@raw_info ||= access_token.get(profile_endpoint).parsed
end

def callback_url
Expand All @@ -73,11 +75,27 @@ def callback_url

def custom_build_access_token
access_token = get_access_token(request)
# Get the profile(microsoft graph / yammer) endpoint choice based on returned bearer token
@profile_endpoint = determine_profile_endpoint(request)
access_token
end

alias build_access_token custom_build_access_token

def profile_endpoint
@profile_endpoint ||= MICROSOFT_GRAPH_PROFILE_URL
end

def determine_profile_endpoint(request)
scope = request&.env&.dig('omniauth.params', 'scope')

if scope&.include?('yammer')
YAMMER_PROFILE_URL
else
MICROSOFT_GRAPH_PROFILE_URL
end
end

private

def get_access_token(request)
Expand Down
78 changes: 78 additions & 0 deletions spec/omniauth/strategies/microsoft_graph_oauth2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -457,4 +457,82 @@
end.to raise_error(OAuth2::Error)
end
end

describe 'Yammer profile endpoint support' do
describe '#profile_endpoint' do
context 'when no profile endpoint is determined' do
it 'defaults to Microsoft Graph profile URL' do
expect(subject.profile_endpoint).to eq('https://graph.microsoft.com/v1.0/me')
end
end

context 'when profile endpoint is already set' do
before { subject.instance_variable_set(:@profile_endpoint, 'https://custom.endpoint.com') }

it 'returns the previously set endpoint' do
expect(subject.profile_endpoint).to eq('https://custom.endpoint.com')
end
end
end

describe '#determine_profile_endpoint' do
let(:request) { double('Request', env: request_env) }

context 'when scope includes Yammer access_as_user scope' do
let(:request_env) { { 'omniauth.params' => { 'scope' => 'https://api.yammer.com/access_as_user' } } }

it 'returns Yammer profile URL' do
expect(subject.determine_profile_endpoint(request)).to eq('https://www.yammer.com/api/v1/users/current.json')
end
end

context 'when scope includes Yammer user_impersonation scope' do
let(:request_env) { { 'omniauth.params' => { 'scope' => 'openid profile https://api.yammer.com/user_impersonation' } } }

it 'returns Yammer profile URL' do
expect(subject.determine_profile_endpoint(request)).to eq('https://www.yammer.com/api/v1/users/current.json')
end
end

context 'when scope includes Yammer scope among other scopes' do
let(:request_env) { { 'omniauth.params' => { 'scope' => 'offline_access openid email profile https://api.yammer.com/access_as_user User.Read' } } }

it 'returns Yammer profile URL' do
expect(subject.determine_profile_endpoint(request)).to eq('https://www.yammer.com/api/v1/users/current.json')
end
end

context 'when scope includes multiple Yammer scopes' do
let(:request_env) { { 'omniauth.params' => { 'scope' => 'openid profile https://api.yammer.com/access_as_user https://api.yammer.com/user_impersonation' } } }

it 'returns Yammer profile URL' do
expect(subject.determine_profile_endpoint(request)).to eq('https://www.yammer.com/api/v1/users/current.json')
end
end

context 'when scope does not include any Yammer scopes' do
let(:request_env) { { 'omniauth.params' => { 'scope' => 'openid profile User.Read' } } }

it 'returns Microsoft Graph profile URL' do
expect(subject.determine_profile_endpoint(request)).to eq('https://graph.microsoft.com/v1.0/me')
end
end

context 'when scope is nil' do
let(:request_env) { { 'omniauth.params' => { 'scope' => nil } } }

it 'returns Microsoft Graph profile URL' do
expect(subject.determine_profile_endpoint(request)).to eq('https://graph.microsoft.com/v1.0/me')
end
end

context 'when omniauth.params is nil' do
let(:request_env) { { 'omniauth.params' => nil } }

it 'returns Microsoft Graph profile URL' do
expect(subject.determine_profile_endpoint(request)).to eq('https://graph.microsoft.com/v1.0/me')
end
end
end
end
end