124 lines
4.1 KiB
Ruby
124 lines
4.1 KiB
Ruby
require 'omniauth-oauth2'
|
|
|
|
# This file is from omniauth-microsoft_graph lib (not installed)
|
|
# It is modified to make auth work
|
|
|
|
module OmniAuth
|
|
module Strategies
|
|
class AzureAd < 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
|
|
|
|
option :name, :azure_ad
|
|
|
|
option :client_options,
|
|
site: 'https://login.microsoftonline.com/'
|
|
|
|
option :authorize_options, %i[state callback_url scope response_mode]
|
|
|
|
option :token_params, {}
|
|
|
|
option :scope, DEFAULT_SCOPE
|
|
option :authorized_client_ids, []
|
|
|
|
uid { raw_info["id"] }
|
|
|
|
info do
|
|
{
|
|
# 'email' => raw_info["mail"],
|
|
# 'first_name' => raw_info["givenName"],
|
|
# 'last_name' => raw_info["surname"],
|
|
# 'name' => [raw_info["givenName"], raw_info["surname"]].join(' '),
|
|
# 'nickname' => raw_info["displayName"],
|
|
}
|
|
end
|
|
|
|
extra do
|
|
{
|
|
# 'raw_info' => raw_info,
|
|
# 'params' => access_token.params,
|
|
# 'aud' => options.client_id
|
|
}
|
|
end
|
|
|
|
def authorize_params
|
|
super.tap do |params|
|
|
options[:authorize_options].each do |k|
|
|
params[k] = request.params[k.to_s] unless [nil, ''].include?(request.params[k.to_s])
|
|
end
|
|
|
|
params[:scope] = get_scope(params)
|
|
|
|
session['omniauth.state'] = params[:state] if params[:state]
|
|
end
|
|
end
|
|
|
|
def raw_info
|
|
@raw_info ||= access_token.get('https://graph.microsoft.com/v1.0/me').parsed
|
|
end
|
|
|
|
def callback_url
|
|
options[:callback_url] || full_host + script_name + callback_path
|
|
end
|
|
|
|
def custom_build_access_token
|
|
token_response = get_access_token(request)
|
|
session[:microsoft_graph_api_token] = token_response.token
|
|
token_response
|
|
end
|
|
|
|
alias build_access_token custom_build_access_token
|
|
|
|
private
|
|
|
|
def get_access_token(request)
|
|
verifier = request.params['code']
|
|
redirect_uri = request.params['redirect_uri'] || request.params['callback_url']
|
|
if verifier && request.xhr?
|
|
client_get_token(verifier, redirect_uri || '/auth/azure_ad/callback')
|
|
elsif verifier
|
|
client_get_token(verifier, redirect_uri || callback_url)
|
|
elsif verify_token(request.params['access_token'])
|
|
::OAuth2::AccessToken.from_hash(client, request.params.dup)
|
|
elsif request.content_type =~ /json/i
|
|
begin
|
|
body = JSON.parse(request.body.read)
|
|
request.body.rewind # rewind request body for downstream middlewares
|
|
verifier = body && body['code']
|
|
client_get_token(verifier, '/auth/azure_ad/callback') if verifier
|
|
rescue JSON::ParserError => e
|
|
warn "[omniauth google-oauth2] JSON parse error=#{e}"
|
|
end
|
|
end
|
|
end
|
|
|
|
def client_get_token(verifier, redirect_uri)
|
|
client.auth_code.get_token(verifier, get_token_options(redirect_uri), get_token_params)
|
|
end
|
|
|
|
def get_token_params
|
|
deep_symbolize(options.auth_token_params || {})
|
|
end
|
|
|
|
def get_token_options(redirect_uri = '')
|
|
{ redirect_uri: redirect_uri }.merge(token_params.to_hash(symbolize_keys: true))
|
|
end
|
|
|
|
def get_scope(params)
|
|
raw_scope = params[:scope] || DEFAULT_SCOPE
|
|
scope_list = raw_scope.split(' ').map { |item| item.split(',') }.flatten
|
|
scope_list.map! { |s| s =~ %r{^https?://} || BASE_SCOPES.include?(s) ? s : "#{BASE_SCOPE_URL}#{s}" }
|
|
scope_list.join(' ')
|
|
end
|
|
|
|
def verify_token(access_token)
|
|
return false unless access_token
|
|
# access_token.get('https://graph.microsoft.com/v1.0/me').parsed
|
|
raw_response = client.request(:get, 'https://graph.microsoft.com/v1.0/me',
|
|
params: { access_token: access_token }).parsed
|
|
(raw_response['aud'] == options.client_id) || options.authorized_client_ids.include?(raw_response['aud'])
|
|
end
|
|
end
|
|
end
|
|
end |