This commit is contained in:
Leo McArdle 2017-11-30 23:09:53 +00:00
Родитель 2b51508f64
Коммит c40b497a5d
8 изменённых файлов: 96 добавлений и 71 удалений

Просмотреть файл

@ -8,3 +8,10 @@ auth0:
auth0_client_secret:
default: ''
shadowed_by_global: true
mozilla_iam:
mozilla_iam_person_api_url:
default: 'https://uhbz4h3wa8.execute-api.us-west-2.amazonaws.com/prod'
shadowed_by_global: true
mozilla_iam_person_api_aud:
default: 'https://person-api.sso.mozilla.com'
shadowed_by_global: true

Просмотреть файл

@ -1,6 +1,7 @@
require_relative 'mozilla_iam/engine'
require_relative 'mozilla_iam/api'
require_relative 'mozilla_iam/person_api'
require_relative 'mozilla_iam/application_extensions'
require_relative 'mozilla_iam/authenticator'
require_relative 'mozilla_iam/jwks'

Просмотреть файл

@ -1,74 +1,73 @@
module MozillaIAM
class API
class << self
def initialize(config)
@client_id = config[:client_id] || SiteSetting.auth0_client_id
@client_secret = config[:client_secret] || SiteSetting.auth0_client_secret
@token_endpoint = config[:token_endpoint] || "https://#{SiteSetting.auth0_domain}/oauth/token"
@url = config[:url]
@aud = config[:aud]
end
def user(uid)
Rails.logger.info("Auth0 API query for user_id: #{uid}")
profile = get("users/#{uid}", fields: 'app_metadata')
{ app_metadata: {} }.merge(profile)[:app_metadata]
private
def get(path, params = false)
path = URI.encode(path)
uri = URI("#{@url}/#{path}")
uri.query = URI.encode_www_form(params) if params
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Bearer #{access_token}"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
private
def get(path, params = false)
path = URI.encode(path)
uri = URI("https://#{SiteSetting.auth0_domain}/api/v2/#{path}")
uri.query = URI.encode_www_form(params) if params
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Bearer #{access_token}"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
if res.code == '200'
MultiJson.load(res.body, symbolize_keys: true)
else
{}
end
if res.code == '200'
MultiJson.load(res.body, symbolize_keys: true)
else
{}
end
end
def access_token
api_creds = ::PluginStore.get('mozilla-iam', 'api_creds')
if api_creds.nil? || api_creds[:exp] < Time.now.to_i + 60
refresh_token
else
api_creds[:access_token]
end
def access_token
api_token = ::PluginStore.get('mozilla-iam', "#{@aud}_token")
if api_token.nil? || api_token[:exp] < Time.now.to_i + 60
refresh_token
else
api_token[:access_token]
end
end
def refresh_token
token = fetch_token
payload = verify_token(token)
::PluginStore.set('mozilla-iam', 'api_creds', { access_token: token, exp: payload['exp'] })
token
end
def refresh_token
token = fetch_token
payload = verify_token(token)
::PluginStore.set('mozilla-iam', "#{@aud}_token", { access_token: token, exp: payload['exp'] })
token
end
def fetch_token
response =
Faraday.post(
'https://' + SiteSetting.auth0_domain + '/oauth/token',
{
grant_type: 'client_credentials',
client_id: SiteSetting.auth0_client_id,
client_secret: SiteSetting.auth0_client_secret,
audience: 'https://' + SiteSetting.auth0_domain + '/api/v2/'
}
)
MultiJson.load(response.body)['access_token']
end
def fetch_token
response =
Faraday.post(
@token_endpoint,
{
grant_type: 'client_credentials',
client_id: @client_id,
client_secret: @client_secret,
audience: @aud
}
)
MultiJson.load(response.body)['access_token']
end
def verify_token(token)
payload, header =
JWT.decode(
token,
aud: 'https://' + SiteSetting.auth0_domain + '/api/v2/',
sub: SiteSetting.auth0_client_id + '@clients',
verify_sub: true
)
payload
end
def verify_token(token)
payload, header =
JWT.decode(
token,
aud: @aud,
sub: @client_id + '@clients',
verify_sub: true
)
payload
end
end
end

Просмотреть файл

@ -0,0 +1,18 @@
module MozillaIAM
class PersonAPI < API
def initialize(config={})
config = {
url: SiteSetting.mozilla_iam_person_api_url,
aud: SiteSetting.mozilla_iam_person_api_aud
}.merge(config)
super(config)
end
def profile(uid)
profile = get("profile/#{uid}")
MultiJson.load(profile[:body], symbolize_keys: true)
end
end
end

Просмотреть файл

@ -26,7 +26,7 @@ module MozillaIAM
private
def profile
@profile ||= API.user(@uid)
@profile ||= PersonAPI.new.profile(@uid)
end
def last_refresh

Просмотреть файл

@ -42,7 +42,7 @@ describe MozillaIAM::Profile do
expect(group.users.count).to eq 1
stub_api_users_request(uid, groups: [])
stub_people_api_profile_request(uid, groups: [])
MozillaIAM::Profile.new(user, uid).refresh
expect(group.users.count).to eq 0
@ -58,7 +58,7 @@ describe MozillaIAM::Profile do
expect(group.users.count).to eq 0
stub_api_users_request(uid, groups: ['iam_group'])
stub_people_api_profile_request(uid, groups: ['iam_group'])
MozillaIAM::Profile.new(user, uid).refresh
expect(group.users.count).to eq 1

Просмотреть файл

@ -24,7 +24,7 @@ describe MozillaIAM do
end
context 'when user in correct IAM group' do
before { stub_api_users_request(uid, groups: ['iam_group']) }
before { stub_people_api_profile_request(uid, groups: ['iam_group']) }
it 'refreshes the user profile' do
PostAlerter.post_created(reply)
@ -52,7 +52,7 @@ describe MozillaIAM do
end
context 'when user removed from IAM group' do
before { stub_api_users_request(uid, groups: []) }
before { stub_people_api_profile_request(uid, groups: []) }
it 'refreshes the user profile' do
PostAlerter.post_created(reply)

Просмотреть файл

@ -71,13 +71,13 @@ module IAMHelpers
authenticate_with_id_token create_id_token(user)
end
def stub_oauth_token_request
def stub_oauth_token_request(aud)
stub_jwks_request
payload = {
sub: 'the_best_client_id@clients',
iss: 'https://auth.mozilla.auth0.com/',
aud: 'https://auth.mozilla.auth0.com/api/v2/',
aud: aud,
exp: Time.now.to_i + 7.days,
iat: Time.now.to_i
}
@ -93,10 +93,10 @@ module IAMHelpers
.to_return(status: 200, body: body)
end
def stub_api_users_request(uid, app_metadata)
stub_oauth_token_request
def stub_people_api_profile_request(uid, profile)
stub_oauth_token_request('https://person-api.sso.mozilla.com')
stub_request(:get, "https://auth.mozilla.auth0.com/api/v2/users/#{uid}?fields=app_metadata")
.to_return(status: 200, body: MultiJson.dump(app_metadata: app_metadata))
stub_request(:get, "https://uhbz4h3wa8.execute-api.us-west-2.amazonaws.com/prod/profile/#{uid}")
.to_return(status: 200, body: MultiJson.dump(body: MultiJson.dump(profile)))
end
end