Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SECURITY: Emails from microsoft are not verified (#72)
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
- Loading branch information
Showing
7 changed files
with
188 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# frozen_string_literal: true | ||
|
||
class MicrosoftAuthRevoker | ||
def self.revoke | ||
# Deactive users using microsoft as an authentication provider | ||
DB.exec <<~SQL | ||
UPDATE users SET active = false | ||
WHERE users.id IN (#{microsoft_user_associated_accounts_sql}) | ||
SQL | ||
|
||
# Log out all users using microsoft as an authentication provider | ||
log_out_users | ||
|
||
# Revoke user API keys for users using microsoft as an authentication provider | ||
DB.exec <<~SQL | ||
UPDATE user_api_keys | ||
SET revoked_at = NOW() | ||
WHERE user_id IN (#{microsoft_user_associated_accounts_sql}) | ||
SQL | ||
|
||
# Revoke API keys that are created by users using microsoft as an authentication provider | ||
DB.exec <<~SQL | ||
UPDATE api_keys | ||
SET revoked_at = NOW() | ||
WHERE created_by_id IN (#{microsoft_user_associated_accounts_sql}) | ||
SQL | ||
|
||
# Remove microsoft as an authentication provider for all users | ||
DB.exec <<~SQL | ||
DELETE FROM user_associated_accounts | ||
WHERE provider_name = 'microsoft_office365' | ||
SQL | ||
end | ||
|
||
def self.log_out_users | ||
DB.exec <<~SQL | ||
DELETE FROM user_auth_tokens | ||
WHERE user_id IN (#{microsoft_user_associated_accounts_sql}) | ||
SQL | ||
end | ||
|
||
def self.microsoft_user_associated_accounts_sql | ||
<<~SQL | ||
SELECT user_id | ||
FROM user_associated_accounts | ||
WHERE provider_name = 'microsoft_office365' | ||
SQL | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative "../microsoft_auth_revoker" | ||
|
||
desc <<~DESC | ||
A rake task to remove microsoft as an authentication provider, log out, deactivate and remove all API keys for all | ||
users accounts that have used Microsoft as an authentication provider. | ||
DESC | ||
task "microsoft_auth:revoke" => :environment do | ||
MicrosoftAuthRevoker.revoke | ||
end | ||
|
||
task "microsoft_auth:log_out_users" => :environment do | ||
MicrosoftAuthRevoker.log_out_users | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative "../../lib/microsoft_auth_revoker" | ||
|
||
RSpec.describe MicrosoftAuthRevoker do | ||
describe ".revoke" do | ||
fab!(:user_1) { Fabricate(:user).tap { |user| UserAuthToken.generate!(user_id: user.id) } } | ||
fab!(:user_2) { Fabricate(:user).tap { |user| UserAuthToken.generate!(user_id: user.id) } } | ||
fab!(:user_3) { Fabricate(:user).tap { |user| UserAuthToken.generate!(user_id: user.id) } } | ||
|
||
fab!(:microsoft_user_associated_account_for_user_1) do | ||
UserAssociatedAccount.create!( | ||
provider_name: "microsoft_office365", | ||
user_id: user_1.id, | ||
provider_uid: 100, | ||
info: { | ||
email: "someuser@somedomain.tld", | ||
}, | ||
) | ||
end | ||
|
||
fab!(:microsoft_user_associated_account_for_user_2) do | ||
UserAssociatedAccount.create!( | ||
provider_name: "microsoft_office365", | ||
user_id: user_2.id, | ||
provider_uid: 200, | ||
info: { | ||
email: "someuser@somedomain.tld", | ||
}, | ||
) | ||
end | ||
|
||
fab!(:facebook_user_associated_account_for_user_3) do | ||
UserAssociatedAccount.create!( | ||
provider_name: "facebook", | ||
user_id: user_1.id, | ||
provider_uid: 100, | ||
info: { | ||
email: "someuser@somedomain.tld", | ||
}, | ||
) | ||
end | ||
|
||
fab!(:user_api_key_for_user_1) { Fabricate(:user_api_key, user: user_1) } | ||
fab!(:user_api_key_for_user_2) { Fabricate(:user_api_key, user: user_2) } | ||
fab!(:user_api_key_for_user_3) { Fabricate(:user_api_key, user: user_3) } | ||
fab!(:api_key_for_user_1) { Fabricate(:api_key, created_by_id: user_1.id) } | ||
fab!(:api_key_for_user_2) { Fabricate(:api_key, created_by_id: user_2.id) } | ||
fab!(:api_key_for_user_3) { Fabricate(:api_key, created_by_id: user_3.id) } | ||
|
||
it "should delete all microsoft provider `UserAssociatedAccount` records" do | ||
expect do MicrosoftAuthRevoker.revoke end.to change { UserAssociatedAccount.count }.by(-2) | ||
expect(UserAssociatedAccount.where(provider_name: "microsoft_office365").count).to eq(0) | ||
end | ||
|
||
it "should deactivate all users with microsoft provider `UserAssociatedAccount` records" do | ||
expect do MicrosoftAuthRevoker.revoke end.to change { User.where(active: true).count }.by(-2) | ||
expect(user_1.reload.active).to eq(false) | ||
expect(user_2.reload.active).to eq(false) | ||
expect(user_3.reload.active).to eq(true) | ||
end | ||
|
||
it "should delete all `UserAuthToken` records for users with microsoft provider `UserAssociatedAccount` records" do | ||
expect do MicrosoftAuthRevoker.revoke end.to change { UserAuthToken.count }.by(-2) | ||
expect(UserAuthToken.where(user_id: user_1.id).count).to eq(0) | ||
expect(UserAuthToken.where(user_id: user_2.id).count).to eq(0) | ||
expect(UserAuthToken.where(user_id: user_3.id).count).to eq(1) | ||
end | ||
|
||
it "should revoke all `UserApiKey` records for users with microsoft provider `UserAssociatedAccount` records" do | ||
expect do MicrosoftAuthRevoker.revoke end.to change { | ||
UserApiKey.where(revoked_at: nil).count | ||
}.by(-2) | ||
|
||
expect(user_api_key_for_user_1.reload.revoked_at).to be_present | ||
expect(user_api_key_for_user_2.reload.revoked_at).to be_present | ||
expect(user_api_key_for_user_3.reload.revoked_at).to be_nil | ||
end | ||
|
||
it "should revoke all `ApiKey` records created by users with microsoft provider `UserAssociatedAccount` records" do | ||
expect do MicrosoftAuthRevoker.revoke end.to change { | ||
ApiKey.where(revoked_at: nil).count | ||
}.by(-2) | ||
|
||
expect(api_key_for_user_1.reload.revoked_at).to be_present | ||
expect(api_key_for_user_2.reload.revoked_at).to be_present | ||
expect(api_key_for_user_3.reload.revoked_at).to be_nil | ||
end | ||
end | ||
end |