first attempt at AAL compatibility
will block login of users if their AAL isn't sufficient, and kill sessions if they later require a higher AAL
This commit is contained in:
Родитель
c652048f2a
Коммит
a0a206b870
|
@ -31,6 +31,10 @@ module MozillaIAM
|
|||
log_off_user
|
||||
else
|
||||
refresh_iam_session
|
||||
unless Profile.for(current_user).is_aal_enough?(session[:mozilla_iam].try(:[], :aal))
|
||||
reset_session
|
||||
log_off_user
|
||||
end
|
||||
end
|
||||
rescue => e
|
||||
reset_session
|
||||
|
|
|
@ -18,8 +18,10 @@ module MozillaIAM
|
|||
::PluginStore.set('mozilla-iam', 'logout_delay', logout_delay)
|
||||
Rails.cache.write('mozilla-iam/logout_delay', logout_delay)
|
||||
|
||||
aal = payload['https://sso.mozilla.com/claim/AAL']
|
||||
auth_token[:session][:mozilla_iam] = {
|
||||
last_refresh: Time.now
|
||||
last_refresh: Time.now,
|
||||
aal: aal
|
||||
}
|
||||
|
||||
result = Auth::Result.new
|
||||
|
@ -35,7 +37,11 @@ module MozillaIAM
|
|||
result.extra_data = { uid: uid }
|
||||
|
||||
if user
|
||||
Profile.new(user, uid).force_refresh
|
||||
profile = Profile.new(user, uid)
|
||||
profile.force_refresh
|
||||
unless profile.is_aal_enough?(aal)
|
||||
raise "user logged in with too low an AAL"
|
||||
end
|
||||
end
|
||||
|
||||
result
|
||||
|
|
|
@ -102,3 +102,4 @@ end
|
|||
require_relative "profile/update_groups"
|
||||
require_relative "profile/update_emails"
|
||||
require_relative "profile/duplicate_accounts"
|
||||
require_relative "profile/is_aal_enough"
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
module MozillaIAM
|
||||
Profile.class_eval do
|
||||
def is_aal_enough?(aal)
|
||||
aal_levels = [
|
||||
"UNKNOWN",
|
||||
"LOW",
|
||||
"MEDIUM",
|
||||
"HIGH",
|
||||
"MAXIMUM"
|
||||
]
|
||||
level = aal_levels.index(aal)
|
||||
level = aal_levels.index("UNKNOWN") if !level
|
||||
|
||||
if get(:in_mapped_groups) == "t"
|
||||
level >= aal_levels.index("MEDIUM")
|
||||
elsif @user.moderator
|
||||
level >= aal_levels.index("MEDIUM")
|
||||
elsif @user.admin
|
||||
level >= aal_levels.index("MEDIUM")
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,13 +5,16 @@ module MozillaIAM
|
|||
private
|
||||
|
||||
def update_groups
|
||||
in_mapped_groups = false
|
||||
GroupMapping.all.each do |mapping|
|
||||
if attr(:groups).include?(mapping.iam_group_name)
|
||||
in_mapped_groups = true
|
||||
add_to_group(mapping.group)
|
||||
else
|
||||
remove_from_group(mapping.group)
|
||||
end
|
||||
end
|
||||
set(:in_mapped_groups, in_mapped_groups)
|
||||
end
|
||||
|
||||
def add_to_group(group)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# name: mozilla-iam
|
||||
# about: A plugin to integrate Discourse with Mozilla's Identity and Access Management (IAM) system
|
||||
# version: 0.2.11
|
||||
# version: 0.2.11-AAL-0
|
||||
# authors: Leo McArdle
|
||||
# url: https://github.com/mozilla/discourse-mozilla-iam
|
||||
|
||||
|
|
|
@ -125,6 +125,33 @@ describe MozillaIAM::Authenticator do
|
|||
|
||||
expect(result.failed).to eq true
|
||||
end
|
||||
|
||||
context "when the AAL" do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:id_token) { create_id_token(user, { "https://sso.mozilla.com/claim/AAL" => "LOW" }) }
|
||||
before do
|
||||
MozillaIAM::Profile.expects(:refresh_methods).returns([:update_groups])
|
||||
MozillaIAM::GroupMapping.create(iam_group_name: 'iam_group', group: Fabricate(:group))
|
||||
end
|
||||
|
||||
context "is high enough" do
|
||||
it "authenticates user" do
|
||||
MozillaIAM::Profile.any_instance.expects(:attr).with(:groups).returns([])
|
||||
result = authenticate_with_id_token(id_token)
|
||||
|
||||
expect(result.user.id).to eq user.id
|
||||
end
|
||||
end
|
||||
|
||||
context "is too low" do
|
||||
it "doesn't authenticate user" do
|
||||
MozillaIAM::Profile.any_instance.expects(:attr).with(:groups).returns(["iam_group"])
|
||||
result = authenticate_with_id_token(id_token)
|
||||
|
||||
expect(result.failed).to eq true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context '#after_create_account' do
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
require_relative '../../../iam_helper'
|
||||
|
||||
describe MozillaIAM::Profile do
|
||||
describe "#is_aal_enough?" do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:profile) { MozillaIAM::Profile.new(user, "uid") }
|
||||
|
||||
context "when a user is in no mapped groups" do
|
||||
before do
|
||||
profile.expects(:get).with(:in_mapped_groups).returns("f")
|
||||
end
|
||||
|
||||
it "returns true with nil" do
|
||||
expect(profile.is_aal_enough?(nil)).to eq true
|
||||
end
|
||||
|
||||
it "returns true with UNKNOWN" do
|
||||
expect(profile.is_aal_enough?("UNKNOWN")).to eq true
|
||||
end
|
||||
|
||||
it "returns true with LOW" do
|
||||
expect(profile.is_aal_enough?("LOW")).to eq true
|
||||
end
|
||||
|
||||
it "returns true with MEDIUM" do
|
||||
expect(profile.is_aal_enough?("MEDIUM")).to eq true
|
||||
end
|
||||
|
||||
it "returns true with HIGH" do
|
||||
expect(profile.is_aal_enough?("HIGH")).to eq true
|
||||
end
|
||||
|
||||
it "returns true with MAXIMUM" do
|
||||
expect(profile.is_aal_enough?("MAXIMUM")).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples "MEDIUM required" do
|
||||
it "returns false with nil" do
|
||||
expect(profile.is_aal_enough?(nil)).to eq false
|
||||
end
|
||||
|
||||
it "returns false with UNKNOWN" do
|
||||
expect(profile.is_aal_enough?("UNKNOWN")).to eq false
|
||||
end
|
||||
|
||||
it "returns false with LOW" do
|
||||
expect(profile.is_aal_enough?("LOW")).to eq false
|
||||
end
|
||||
|
||||
it "returns true with MEDIUM" do
|
||||
expect(profile.is_aal_enough?("MEDIUM")).to eq true
|
||||
end
|
||||
|
||||
it "returns true with HIGH" do
|
||||
expect(profile.is_aal_enough?("HIGH")).to eq true
|
||||
end
|
||||
|
||||
it "returns true with MAXIMUM" do
|
||||
expect(profile.is_aal_enough?("MAXIMUM")).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
context "when a user is in mapped groups" do
|
||||
before do
|
||||
profile.expects(:get).with(:in_mapped_groups).returns("t")
|
||||
end
|
||||
|
||||
include_examples "MEDIUM required"
|
||||
end
|
||||
|
||||
context "when a user is a moderator" do
|
||||
let(:user) { Fabricate(:moderator) }
|
||||
|
||||
include_examples "MEDIUM required"
|
||||
end
|
||||
|
||||
context "when a user is an admin" do
|
||||
let(:user) { Fabricate(:admin) }
|
||||
|
||||
include_examples "MEDIUM required"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -35,6 +35,22 @@ describe MozillaIAM::Profile do
|
|||
|
||||
expect(group.users.count).to eq 1
|
||||
end
|
||||
|
||||
context "when a user is in a mapped group" do
|
||||
it "sets in_mapped_groups to true" do
|
||||
profile.expects(:attr).with(:groups).returns(['iam_group'])
|
||||
profile.send(:update_groups)
|
||||
expect(profile.send(:get, :in_mapped_groups)).to eq "t"
|
||||
end
|
||||
end
|
||||
|
||||
context "when a user isn't in any mapped groups" do
|
||||
it "sets in_mapped_groups to false" do
|
||||
profile.expects(:attr).with(:groups).returns([])
|
||||
profile.send(:update_groups)
|
||||
expect(profile.send(:get, :in_mapped_groups)).to eq "f"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "#add_to_group" do
|
||||
|
|
|
@ -99,6 +99,20 @@ describe TopicsController do
|
|||
expect(session[:mozilla_iam][:no_refresh]).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
context "and when MEDIUM or above AAL required" do
|
||||
it "kills session" do
|
||||
MozillaIAM::Profile.any_instance.expects(:is_aal_enough?).with(nil).returns(true)
|
||||
|
||||
get :show, params: { id: 666 }, format: :json
|
||||
expect(session['current_user_id']).to be
|
||||
|
||||
MozillaIAM::Profile.any_instance.expects(:is_aal_enough?).with(nil).returns(false)
|
||||
|
||||
get :show, params: { id: 666 }, format: :json
|
||||
expect(session['current_user_id']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with session[:mozilla_iam][:no_refresh] set to true" do
|
||||
|
@ -134,5 +148,24 @@ describe TopicsController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when the AAL becomes too low" do
|
||||
it "kills session" do
|
||||
user = Fabricate(:user)
|
||||
authenticate_user(user)
|
||||
log_in_user(user)
|
||||
session[:mozilla_iam] = { aal: "LOW" }
|
||||
|
||||
MozillaIAM::Profile.any_instance.expects(:is_aal_enough?).with("LOW").returns(true)
|
||||
|
||||
get :show, params: { id: 666 }, format: :json
|
||||
expect(session['current_user_id']).to be
|
||||
|
||||
MozillaIAM::Profile.any_instance.expects(:is_aal_enough?).with("LOW").returns(false)
|
||||
|
||||
get :show, params: { id: 666 }, format: :json
|
||||
expect(session['current_user_id']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,7 +45,8 @@ module IAMHelpers
|
|||
iss: 'https://auth.mozilla.auth0.com/',
|
||||
aud: 'the_best_client_id',
|
||||
exp: Time.now.to_i + 7.days,
|
||||
iat: Time.now.to_i
|
||||
iat: Time.now.to_i,
|
||||
"https://sso.mozilla.com/claim/AAL": "UNKNOWN"
|
||||
}.merge(additional_payload)
|
||||
|
||||
header_fields = {
|
||||
|
@ -126,7 +127,7 @@ module IAMHelpers
|
|||
expect { parent.const_get(const) }.to raise_error(NameError)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def stub_apis_profile_request(uid, profile)
|
||||
stub_management_api_profile_request(uid, profile)
|
||||
stub_people_api_profile_request(uid, profile)
|
||||
|
|
Загрузка…
Ссылка в новой задаче