mirror of
https://github.com/discourse/discourse.git
synced 2025-03-24 12:55:54 +08:00
FEATURE: Disallow login via omniauth when user has 2FA enabled.
This commit is contained in:
parent
0fabf80dca
commit
fb75f188ba
app
assets/javascripts/discourse
controllers/users
config/locales
lib/auth
spec/requests
@ -27,16 +27,20 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
loggingIn: false,
|
||||
loggedIn: false,
|
||||
processingEmailLink: false,
|
||||
showLoginButtons: true,
|
||||
|
||||
canLoginLocal: setting('enable_local_logins'),
|
||||
canLoginLocalWithEmail: setting('enable_local_logins_via_email'),
|
||||
loginRequired: Em.computed.alias('application.loginRequired'),
|
||||
|
||||
resetForm: function() {
|
||||
this.set('authenticate', null);
|
||||
this.set('loggingIn', false);
|
||||
this.set('loggedIn', false);
|
||||
this.set('secondFactorRequired', false);
|
||||
this.setProperties({
|
||||
'authenticate': null,
|
||||
'loggingIn': false,
|
||||
'loggedIn': false,
|
||||
'secondFactorRequired': false,
|
||||
'showLoginButtons': true,
|
||||
});
|
||||
$("#credentials").show();
|
||||
$("#second-factor").hide();
|
||||
},
|
||||
@ -250,16 +254,28 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
}).property('authenticate'),
|
||||
|
||||
authenticationComplete(options) {
|
||||
|
||||
const self = this;
|
||||
function loginError(errorMsg, className) {
|
||||
function loginError(errorMsg, className, callback) {
|
||||
showModal('login');
|
||||
Ember.run.next(function() {
|
||||
|
||||
Ember.run.next(() => {
|
||||
callback();
|
||||
self.flash(errorMsg, className || 'success');
|
||||
self.set('authenticate', null);
|
||||
});
|
||||
}
|
||||
|
||||
if (options.omniauth_disallow_totp) {
|
||||
return loginError(I18n.t('login.omniauth_disallow_totp'), 'error', () => {
|
||||
this.setProperties({
|
||||
'loginName': options.email,
|
||||
'showLoginButtons': false,
|
||||
});
|
||||
|
||||
$('#login-account-password').focus();
|
||||
});
|
||||
}
|
||||
|
||||
for (let i=0; i<AuthErrors.length; i++) {
|
||||
const cond = AuthErrors[i];
|
||||
if (options[cond]) {
|
||||
|
@ -1,10 +1,12 @@
|
||||
{{#login-modal screenX=lastX screenY=lastY loginName=loginName loginPassword=loginPassword loginSecondFactor=loginSecondFactor action="login"}}
|
||||
{{#d-modal-body title="login.title" class="login-modal"}}
|
||||
{{login-buttons
|
||||
canLoginLocalWithEmail=canLoginLocalWithEmail
|
||||
processingEmailLink=processingEmailLink
|
||||
emailLogin='emailLogin'
|
||||
externalLogin='externalLogin'}}
|
||||
{{#if showLoginButtons}}
|
||||
{{login-buttons
|
||||
canLoginLocalWithEmail=canLoginLocalWithEmail
|
||||
processingEmailLink=processingEmailLink
|
||||
emailLogin='emailLogin'
|
||||
externalLogin='externalLogin'}}
|
||||
{{/if}}
|
||||
|
||||
{{#if canLoginLocal}}
|
||||
<form id='login-form' method='post'>
|
||||
|
@ -1,10 +1,12 @@
|
||||
{{#login-modal screenX=lastX screenY=lastY loginName=loginName loginPassword=loginPassword loginSecondFactor=loginSecondFactor action="login"}}
|
||||
{{#d-modal-body title="login.title" class="login-modal"}}
|
||||
{{login-buttons
|
||||
canLoginLocalWithEmail=canLoginLocalWithEmail
|
||||
processingEmailLink=processingEmailLink
|
||||
emailLogin='emailLogin'
|
||||
externalLogin='externalLogin'}}
|
||||
{{#if showLoginButtons}}
|
||||
{{login-buttons
|
||||
canLoginLocalWithEmail=canLoginLocalWithEmail
|
||||
processingEmailLink=processingEmailLink
|
||||
emailLogin='emailLogin'
|
||||
externalLogin='externalLogin'}}
|
||||
{{/if}}
|
||||
|
||||
{{#if canLoginLocal}}
|
||||
<form id='login-form' method='post'>
|
||||
|
@ -114,6 +114,11 @@ class Users::OmniauthCallbacksController < ApplicationController
|
||||
end
|
||||
|
||||
def user_found(user)
|
||||
if user.totp_enabled?
|
||||
@auth_result.omniauth_disallow_totp = true
|
||||
return
|
||||
end
|
||||
|
||||
# automatically activate/unstage any account if a provider marked the email valid
|
||||
if @auth_result.email_valid && @auth_result.email == user.email
|
||||
user.update!(staged: false)
|
||||
|
@ -1140,6 +1140,7 @@ en:
|
||||
not_allowed_from_ip_address: "You can't login from that IP address."
|
||||
admin_not_allowed_from_ip_address: "You can't log in as admin from that IP address."
|
||||
resend_activation_email: "Click here to send the activation email again."
|
||||
omniauth_disallow_totp: "Your account has 2FA enabled. Please login with your password."
|
||||
|
||||
resend_title: "Resend Activation Email"
|
||||
change_email: "Change Email Address"
|
||||
|
@ -4,7 +4,7 @@ class Auth::Result
|
||||
:awaiting_approval, :authenticated, :authenticator_name,
|
||||
:requires_invite, :not_allowed_from_ip_address,
|
||||
:admin_not_allowed_from_ip_address, :omit_username,
|
||||
:skip_email_validation, :destination_url
|
||||
:skip_email_validation, :destination_url, :omniauth_disallow_totp
|
||||
|
||||
attr_accessor(
|
||||
:failed,
|
||||
@ -42,13 +42,22 @@ class Auth::Result
|
||||
date: I18n.l(user.suspended_till, format: :date_only), reason: user.suspend_reason)
|
||||
}
|
||||
else
|
||||
result = {
|
||||
authenticated: !!authenticated,
|
||||
awaiting_activation: !!awaiting_activation,
|
||||
awaiting_approval: !!awaiting_approval,
|
||||
not_allowed_from_ip_address: !!not_allowed_from_ip_address,
|
||||
admin_not_allowed_from_ip_address: !!admin_not_allowed_from_ip_address
|
||||
}
|
||||
result =
|
||||
if omniauth_disallow_totp
|
||||
{
|
||||
omniauth_disallow_totp: !!omniauth_disallow_totp,
|
||||
email: email
|
||||
}
|
||||
else
|
||||
{
|
||||
authenticated: !!authenticated,
|
||||
awaiting_activation: !!awaiting_activation,
|
||||
awaiting_approval: !!awaiting_approval,
|
||||
not_allowed_from_ip_address: !!not_allowed_from_ip_address,
|
||||
admin_not_allowed_from_ip_address: !!admin_not_allowed_from_ip_address
|
||||
}
|
||||
end
|
||||
|
||||
result[:destination_url] = destination_url if authenticated && destination_url.present?
|
||||
result
|
||||
end
|
||||
|
@ -132,6 +132,23 @@ RSpec.describe Users::OmniauthCallbacksController do
|
||||
expect(user.registration_ip_address).to be_present
|
||||
end
|
||||
|
||||
context 'when user has second factor enabled' do
|
||||
before do
|
||||
user.create_totp(enabled: true)
|
||||
end
|
||||
|
||||
it 'should return the right response' do
|
||||
get "/auth/google_oauth2/callback.json"
|
||||
|
||||
expect(response).to be_success
|
||||
|
||||
response_body = JSON.parse(response.body)
|
||||
|
||||
expect(response_body["email"]).to eq(user.email)
|
||||
expect(response_body["omniauth_disallow_totp"]).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user has not verified his email' do
|
||||
before do
|
||||
GoogleUserInfo.create!(google_user_id: '12345', user: user)
|
||||
|
Loading…
x
Reference in New Issue
Block a user