Compare commits
18 Commits
97a822ae15
...
main
Author | SHA1 | Date | |
---|---|---|---|
ed83e8b3a0 | |||
872b706e0f | |||
54f0c3d78a | |||
17688f63d3 | |||
f0163ce5d2 | |||
1082a61c14 | |||
7226bf0b9a | |||
9edabc2a3a | |||
48d1e343b7 | |||
a208b368d2 | |||
a0fc5fe00b | |||
785a12f222 | |||
4472e9b0e3 | |||
ccc85e3856 | |||
bea57091b2 | |||
260a545369 | |||
4dc121eb76 | |||
7445bd8f06 |
@ -1,2 +1,2 @@
|
||||
A plugin to authenticate users with MD5 passwords from legacy systems
|
||||
A custom Federated Computer plugin to authenticate users with MD5 passwords from legacy systems
|
||||
|
||||
|
313
plugin.rb
313
plugin.rb
@ -4,57 +4,300 @@
|
||||
|
||||
# name: discourse-md5_authentication
|
||||
# about: A plugin to authenticate users with MD5 passwords from legacy systems
|
||||
# version: 0.5
|
||||
# authors: saint
|
||||
# version: 0.22
|
||||
# authors: saint@federated.computer
|
||||
# url: https://gitea.federated.computer/saint/discourse-md5_authentication.git
|
||||
|
||||
# This block will run after Discourse has initialized
|
||||
# require 'digest'
|
||||
|
||||
# enabled_site_setting :legacymd5password_auth_enabled
|
||||
|
||||
after_initialize do
|
||||
# Define a module to contain the MD5 authentication logic
|
||||
# Define a module to hold the legacy MD5 authentication logic
|
||||
module LegacyMd5Authentication
|
||||
# Override the current_user method to include MD5 authentication
|
||||
def current_user
|
||||
# Attempt to find the current user using the standard Discourse method
|
||||
user = super
|
||||
return user if user
|
||||
|
||||
# Check for MD5 authentication if no user is found by the standard method
|
||||
email_or_username = @request.params[:login]
|
||||
password = @request.params[:password]
|
||||
# Constants
|
||||
ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
if email_or_username && password
|
||||
# Log the start of the MD5 authentication attempt
|
||||
Rails.logger.info("MD5 Auth: Attempting to authenticate #{email_or_username}")
|
||||
# Override the create method to add our custom authentication checks
|
||||
def create
|
||||
Rails.logger.warn "MD5 -- AA -- start create"
|
||||
# Ensure required parameters are present
|
||||
params.require(:login)
|
||||
params.require(:password)
|
||||
|
||||
# Find the user by username or email, ignoring case
|
||||
user = User.find_by_username_or_email(email_or_username.downcase.strip)
|
||||
# Validate the length of the password
|
||||
return invalid_credentials if params[:password].length > User.max_password_length
|
||||
|
||||
# Log if a user with an MD5 password is found
|
||||
if user && user.custom_fields['md5_password']
|
||||
Rails.logger.info("MD5 Auth: User found with MD5 password - #{user.username}")
|
||||
# Find the user by username or email
|
||||
user = User.find_by_username_or_email(normalized_login_param)
|
||||
|
||||
# Check if the provided password matches the stored MD5 password
|
||||
if user.custom_fields['md5_password'] == Digest::MD5.hexdigest(password)
|
||||
# Log the successful MD5 password match
|
||||
Rails.logger.info("MD5 Auth: MD5 password match for user #{user.username}")
|
||||
Rails.logger.warn "MD5 -- BB -- second"
|
||||
# Check if site is in staff writes-only mode and ensure user is staff if true
|
||||
raise Discourse::ReadOnly if staff_writes_only_mode? && !user&.staff?
|
||||
|
||||
# Update the user to use the new password and clear the MD5 password
|
||||
user.update!(password: password)
|
||||
user.custom_fields['md5_password'] = nil
|
||||
user.save_custom_fields
|
||||
# Apply rate limiting for second factor authentication
|
||||
rate_limit_second_factor!(user)
|
||||
|
||||
# Set the current user in the environment
|
||||
@env[CURRENT_USER_KEY] = user
|
||||
return user
|
||||
if user.present?
|
||||
Rails.logger.warn "MD5 -- CC -- user.present"
|
||||
# Retrieve the provided password and custom MD5 password hash from user custom fields
|
||||
password = params[:password]
|
||||
custom_password_md5 = user.custom_fields['md5_password']
|
||||
|
||||
# Log the presence of custom MD5 hash for debugging
|
||||
Rails.logger.warn "MD5 -- Check for MD5 password in custom field"
|
||||
if custom_password_md5.present?
|
||||
|
||||
# SCENARIO 1. : LEGACY MD5 HASH EXISTS
|
||||
Rails.logger.warn "MD5 -- 1. MD5 password is present custom_password_md5: #{custom_password_md5} password: #{password}"
|
||||
|
||||
# Verify the provided password against the stored MD5 hash
|
||||
if verify_gossamer_password(password, custom_password_md5)
|
||||
|
||||
# SCENARIO 1.1. : LEGACY MD5 HAS EXISTS AND MATCHES
|
||||
# If MD5 hash matches, update the user's password and other attributes
|
||||
Rails.logger.warn "MD5 -- 1.1. MD5 matches"
|
||||
|
||||
# Set the user's password to the provided one and update other attributes
|
||||
begin
|
||||
user.active = true
|
||||
user.approved = true
|
||||
user.approved_at = Time.now
|
||||
user.approved_by_id = 1
|
||||
user.custom_fields['md5_password'] = nil # Clear the custom MD5 field
|
||||
user.password = password
|
||||
user.save!
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
if e.message.include?("Password is the same as your current password")
|
||||
Rails.logger.warn "MD5 -- Skipping password update because the new password is the same as the current password."
|
||||
user.active = true
|
||||
user.approved = true
|
||||
user.approved_at = Time.now
|
||||
user.approved_by_id = 1
|
||||
user.custom_fields['md5_password'] = nil # Clear the custom MD5 field
|
||||
user.save!(validate: false) # Skip validations as password is unchanged
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
Rails.logger.warn "MD5 -- DD -- User attributes updated"
|
||||
|
||||
# Generate a new token and hash it
|
||||
token = SecureRandom.hex(20)
|
||||
token_hash = EmailToken.hash_token(token)
|
||||
|
||||
# Create a confirmed email token for the user
|
||||
EmailToken.create!(
|
||||
user_id: user.id,
|
||||
email: user.email,
|
||||
token_hash: token_hash,
|
||||
confirmed: true
|
||||
)
|
||||
Rails.logger.warn("MD5 -- Generated token for user #{user.username}: #{token}")
|
||||
|
||||
Rails.logger.warn "MD5 -- Updated user: #{user.id}"
|
||||
|
||||
else
|
||||
# SCENARIO 1.2. : LEGACY MD5 HASH EXISTS BUT DOES NOT MATCH
|
||||
|
||||
# Log the failed login attempt
|
||||
Rails.logger.warn "MD5 -- 1.2. MD5 Password (hash) exists but fails / incorrect for user: #{user.id}"
|
||||
|
||||
if user.confirm_password?(password)
|
||||
# SCENARIO 1.2.1 : LEGACY MD5 HASH EXISTS BUT DOES NOT MATCH, BUT REAL PASSWORD WORKS -- NEW SUPPORT in v0.21
|
||||
|
||||
Rails.logger.warn "MD5 -- 1.2.1. Real Password Works for username: #{user.username} user: #{user.id}"
|
||||
|
||||
# Update other attributes (other than password which is already correct)
|
||||
user.active = true
|
||||
user.approved = true
|
||||
user.approved_at = Time.now
|
||||
user.approved_by_id = 1
|
||||
user.custom_fields['md5_password'] = nil # Clear the custom MD5 field
|
||||
user.save!
|
||||
Rails.logger.warn "MD5 -- DD -- user.present, cleared legacy MD5 field!"
|
||||
|
||||
# Generate a new token and hash it
|
||||
token = SecureRandom.hex(20)
|
||||
token_hash = EmailToken.hash_token(token)
|
||||
|
||||
# Create a confirmed email token for the user
|
||||
EmailToken.create!(
|
||||
user_id: user.id,
|
||||
email: user.email,
|
||||
token_hash: token_hash,
|
||||
confirmed: true
|
||||
)
|
||||
Rails.logger.warn("MD5 -- Generated token for user #{user.username}: #{token}")
|
||||
|
||||
Rails.logger.warn "MD5 -- Updated user: #{user.id}"
|
||||
|
||||
else
|
||||
# SCENARIO 1.2.2 : LEGACY MD5 HASH EXISTS BUT DOES NOT MATCH, AND REAL PASSWORD DOES NOT MATCH OR IS NOT PRESENT
|
||||
Rails.logger.warn("MD5 -- 1.2.2. -- MD5 Password (hash) incorrect and no matching real password for username: #{user.username} user: #{user.id}")
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
elsif !user.confirm_password?(password)
|
||||
# SCENARIO 2. : NO lEGACY MD5 HASH EXISTS AND REAL PASSWORD DOES NOT MATCH OR IS NOT PRESENT
|
||||
# If no MD5 hash is present and the provided password is incorrect
|
||||
Rails.logger.warn "MD5 -- 2. Password incorrect for user: #{user.id}"
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
# If the site requires user approval and the user is not yet approved
|
||||
if login_not_approved_for?(user)
|
||||
render json: login_not_approved
|
||||
return
|
||||
end
|
||||
|
||||
# Invalidate any invite link for the user
|
||||
Invite.invalidate_for_email(user.email)
|
||||
|
||||
# 3.3.0 # Check if the user's password has expired
|
||||
# if user.password_expired?(password)
|
||||
# render json: { error: "expired", reason: "expired" }
|
||||
# return
|
||||
# end
|
||||
else
|
||||
# No user is found with the provided credentials
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
|
||||
# Fallback to the original current_user method
|
||||
nil
|
||||
# Check for any login errors
|
||||
if payload = login_error_check(user)
|
||||
return render json: payload
|
||||
end
|
||||
|
||||
# Authenticate second factor if required
|
||||
second_factor_auth_result = authenticate_second_factor(user)
|
||||
return render(json: @second_factor_failure_payload) unless second_factor_auth_result.ok
|
||||
|
||||
# If user is active and email is confirmed, proceed with login
|
||||
if user.active && user.email_confirmed?
|
||||
login(user, second_factor_auth_result)
|
||||
else
|
||||
not_activated(user)
|
||||
end
|
||||
end
|
||||
|
||||
# Helper methods to handle MD5 password verification
|
||||
|
||||
def to64(value, length)
|
||||
# Convert a value to a base64-like representation
|
||||
result = String.new
|
||||
length.times do
|
||||
result << ITOA64[value & 0x3f]
|
||||
value >>= 6
|
||||
Rails.logger.warn "MD5 -- to64 result: #{result}"
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def gossamer_md5_crypt(password, legacy_hash)
|
||||
# Extract the salt from the legacy hash
|
||||
parts = legacy_hash.split('$')
|
||||
salt = parts[2]
|
||||
|
||||
# Limit the salt to 8 characters
|
||||
salt = salt[0, 8]
|
||||
|
||||
magic = "$GT$"
|
||||
Rails.logger.warn "MD5 -- MD5 magic: #{magic}"
|
||||
|
||||
ctx = Digest::MD5.new
|
||||
ctx.update(password)
|
||||
ctx.update(magic)
|
||||
ctx.update(salt)
|
||||
|
||||
final = Digest::MD5.new
|
||||
final.update(password)
|
||||
final.update(salt)
|
||||
final.update(password)
|
||||
final_digest = final.digest
|
||||
|
||||
password_length = password.length
|
||||
|
||||
# Process the password with various hashing operations
|
||||
while password_length > 0
|
||||
ctx.update(final_digest[0, [password_length, 16].min])
|
||||
password_length -= 16
|
||||
end
|
||||
|
||||
password_length = password.length
|
||||
while password_length > 0
|
||||
if password_length & 1 != 0
|
||||
ctx.update("\x00")
|
||||
else
|
||||
ctx.update(password[0, 1])
|
||||
end
|
||||
password_length >>= 1
|
||||
end
|
||||
|
||||
final_digest = ctx.digest
|
||||
Rails.logger.debug "MD5 -- MD5 final_digest: #{final_digest}"
|
||||
|
||||
1000.times do |i|
|
||||
ctx1 = Digest::MD5.new
|
||||
if i & 1 != 0
|
||||
Rails.logger.warn "MD5 -- AAA"
|
||||
ctx1.update(password)
|
||||
else
|
||||
Rails.logger.warn "MD5 -- BBB"
|
||||
ctx1.update(final_digest)
|
||||
end
|
||||
ctx1.update(salt) if i % 3 != 0
|
||||
ctx1.update(password) if i % 7 != 0
|
||||
if i & 1 != 0
|
||||
Rails.logger.warn "MD5 -- CCC"
|
||||
ctx1.update(final_digest)
|
||||
else
|
||||
Rails.logger.warn "MD5 -- DDD"
|
||||
ctx1.update(password)
|
||||
end
|
||||
final_digest = ctx1.digest
|
||||
end
|
||||
|
||||
Rails.logger.warn "MD5 -- MD5++ final_digest: #{final_digest}"
|
||||
|
||||
result = String.new
|
||||
Rails.logger.warn "MD5 -- A result: #{result}"
|
||||
result << to64((final_digest[0].ord << 16) | (final_digest[6].ord << 8) | final_digest[12].ord, 4)
|
||||
Rails.logger.warn "MD5 -- B result: #{result}"
|
||||
result << to64((final_digest[1].ord << 16) | (final_digest[7].ord << 8) | final_digest[13].ord, 4)
|
||||
Rails.logger.warn "MD5 -- C result: #{result}"
|
||||
result << to64((final_digest[2].ord << 16) | (final_digest[8].ord << 8) | final_digest[14].ord, 4)
|
||||
Rails.logger.warn "MD5 -- D result: #{result}"
|
||||
result << to64((final_digest[3].ord << 16) | (final_digest[9].ord << 8) | final_digest[15].ord, 4)
|
||||
Rails.logger.warn "MD5 -- E result: #{result}"
|
||||
result << to64((final_digest[4].ord << 16) | (final_digest[10].ord << 8) | final_digest[5].ord, 4)
|
||||
Rails.logger.warn "MD5 -- F result: #{result}"
|
||||
result << to64(final_digest[11].ord, 2)
|
||||
Rails.logger.warn "MD5 -- G result: #{result}"
|
||||
|
||||
Rails.logger.warn "MD5 -- Magic Salt Result #{magic}#{salt}$#{result}"
|
||||
"#{magic}#{salt}$#{result}"
|
||||
end
|
||||
|
||||
def verify_gossamer_password(password, legacy_hash)
|
||||
# Verify the provided password against the stored MD5 hash
|
||||
generated_hash = gossamer_md5_crypt(password, legacy_hash)
|
||||
generated_hash == legacy_hash
|
||||
end
|
||||
end
|
||||
|
||||
# Prepend our module to the DefaultCurrentUserProvider class
|
||||
Auth::DefaultCurrentUserProvider.prepend LegacyMd5Authentication
|
||||
# Extend the SessionController class to include the LegacyMd5Authentication module
|
||||
|
||||
# 3.3.0 class ::SessionController < ApplicationController
|
||||
class ::SessionController
|
||||
prepend LegacyMd5Authentication
|
||||
end
|
||||
end
|
||||
|
||||
|
250
plugin.rb.bck
Normal file
250
plugin.rb.bck
Normal file
@ -0,0 +1,250 @@
|
||||
# plugins/discourse-md5_authentication/plugin.rb
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
# name: discourse-md5_authentication
|
||||
# about: A plugin to authenticate users with MD5 passwords from legacy systems
|
||||
# version: 0.13
|
||||
# authors: saint
|
||||
# url: https://gitea.federated.computer/saint/discourse-md5_authentication.git
|
||||
|
||||
# require 'digest'
|
||||
|
||||
after_initialize do
|
||||
# Define a module to contain the MD5 authentication logic
|
||||
module LegacyMd5Authentication
|
||||
|
||||
# Constants
|
||||
ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
def to64(value, length)
|
||||
result = String.new
|
||||
length.times do
|
||||
result << ITOA64[value & 0x3f]
|
||||
value >>= 6
|
||||
Rails.logger.warn "to64 result: #{result}"
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def gossamer_md5_crypt(password, legacy_hash)
|
||||
# Extract the salt from the legacy hash
|
||||
parts = legacy_hash.split('$')
|
||||
salt = parts[2]
|
||||
|
||||
# Limit the salt to 8 characters
|
||||
salt = salt[0, 8]
|
||||
|
||||
magic = "$GT$"
|
||||
Rails.logger.warn "MD5 magic: #{magic}"
|
||||
|
||||
ctx = Digest::MD5.new
|
||||
ctx.update(password)
|
||||
ctx.update(magic)
|
||||
ctx.update(salt)
|
||||
|
||||
final = Digest::MD5.new
|
||||
final.update(password)
|
||||
final.update(salt)
|
||||
final.update(password)
|
||||
final_digest = final.digest
|
||||
|
||||
password_length = password.length
|
||||
|
||||
while password_length > 0
|
||||
ctx.update(final_digest[0, [password_length, 16].min])
|
||||
password_length -= 16
|
||||
end
|
||||
|
||||
password_length = password.length
|
||||
while password_length > 0
|
||||
if password_length & 1 != 0
|
||||
ctx.update("\x00")
|
||||
else
|
||||
ctx.update(password[0, 1])
|
||||
end
|
||||
password_length >>= 1
|
||||
end
|
||||
|
||||
final_digest = ctx.digest
|
||||
Rails.logger.warn "MD5 final_digest: #{final_digest}"
|
||||
|
||||
1000.times do |i|
|
||||
ctx1 = Digest::MD5.new
|
||||
if i & 1 != 0
|
||||
Rails.logger.warn "AAA"
|
||||
ctx1.update(password)
|
||||
else
|
||||
Rails.logger.warn "BBB"
|
||||
ctx1.update(final_digest)
|
||||
end
|
||||
ctx1.update(salt) if i % 3 != 0
|
||||
ctx1.update(password) if i % 7 != 0
|
||||
if i & 1 != 0
|
||||
Rails.logger.warn "CCC"
|
||||
ctx1.update(final_digest)
|
||||
else
|
||||
Rails.logger.warn "DDD"
|
||||
ctx1.update(password)
|
||||
end
|
||||
final_digest = ctx1.digest
|
||||
end
|
||||
Rails.logger.warn "MD6 final_digest: #{final_digest}"
|
||||
|
||||
result = String.new
|
||||
Rails.logger.warn "A result: #{result}"
|
||||
result << to64((final_digest[0].ord << 16) | (final_digest[6].ord << 8) | final_digest[12].ord, 4)
|
||||
Rails.logger.warn "B result: #{result}"
|
||||
result << to64((final_digest[1].ord << 16) | (final_digest[7].ord << 8) | final_digest[13].ord, 4)
|
||||
Rails.logger.warn "C result: #{result}"
|
||||
result << to64((final_digest[2].ord << 16) | (final_digest[8].ord << 8) | final_digest[14].ord, 4)
|
||||
Rails.logger.warn "D result: #{result}"
|
||||
result << to64((final_digest[3].ord << 16) | (final_digest[9].ord << 8) | final_digest[15].ord, 4)
|
||||
Rails.logger.warn "E result: #{result}"
|
||||
result << to64((final_digest[4].ord << 16) | (final_digest[10].ord << 8) | final_digest[5].ord, 4)
|
||||
Rails.logger.warn "F result: #{result}"
|
||||
result << to64(final_digest[11].ord, 2)
|
||||
Rails.logger.warn "G result: #{result}"
|
||||
|
||||
Rails.logger.warn "magic salt result #{magic}#{salt}$#{result}"
|
||||
"#{magic}#{salt}$#{result}"
|
||||
end
|
||||
|
||||
def verify_gossamer_password(password, legacy_hash)
|
||||
generated_hash = gossamer_md5_crypt(password, legacy_hash)
|
||||
generated_hash == legacy_hash
|
||||
end
|
||||
end
|
||||
|
||||
# Extend the SessionController create method to include our MD5 authentication logic
|
||||
class ::SessionController < ApplicationController
|
||||
prepend LegacyMd5Authentication
|
||||
|
||||
def create
|
||||
params.require(:login)
|
||||
params.require(:password)
|
||||
|
||||
return invalid_credentials if params[:password].length > User.max_password_length
|
||||
|
||||
user = User.find_by_username_or_email(normalized_login_param)
|
||||
|
||||
raise Discourse::ReadOnly if staff_writes_only_mode? && !user&.staff?
|
||||
|
||||
rate_limit_second_factor!(user)
|
||||
|
||||
if user.present?
|
||||
password = params[:password]
|
||||
custom_password_md5 = user.custom_fields['custom_password_md5']
|
||||
|
||||
# Check for MD5 password in custom field
|
||||
Rails.logger.warn "Check for MD5 password in custom field"
|
||||
if custom_password_md5.present?
|
||||
# MD5 password is present
|
||||
Rails.logger.warn "MD5 password is present custom_password_md5: #{custom_password_md5} password: #{password}"
|
||||
|
||||
if verify_gossamer_password(password, custom_password_md5)
|
||||
# MD5 matches, so update the user's password to the new one, remove the custom field and ensure user is set to active and approved
|
||||
Rails.logger.warn "MD5 matches"
|
||||
|
||||
# Set password using Discourse's current standards, ensuring correct hashing, with exception check for the same password as that alaedy stored in Discourse
|
||||
user.password = password
|
||||
|
||||
# Set other attributes
|
||||
user.active = true
|
||||
user.approved = true
|
||||
# user.email_confirmed = true
|
||||
user.approved_at = Time.now
|
||||
user.approved_by_id = 1
|
||||
user.custom_fields['custom_password_md5'] = nil
|
||||
user.save!
|
||||
|
||||
# Generate a new token and hash it
|
||||
token = SecureRandom.hex(20)
|
||||
token_hash = EmailToken.hash_token(token)
|
||||
|
||||
# Create a confirmed e-mail token
|
||||
EmailToken.create!(
|
||||
user_id: user.id,
|
||||
email: user.email,
|
||||
token_hash: token_hash,
|
||||
confirmed: true
|
||||
)
|
||||
Rails.logger.warn("Generated token for user #{user.username}: #{token}")
|
||||
|
||||
|
||||
# # Initialize UserAuthenticator with user and session
|
||||
# authenticator = UserAuthenticator.new(user, session)
|
||||
# # Generate a salted password hash for the new password
|
||||
# hashed_password = authenticator.password_digest(password)
|
||||
# Rails.logger.warn "NEW hashed_password #{hashed_password}"
|
||||
# # Update the user object with all changes
|
||||
# user.assign_attributes(
|
||||
# password_hash: hashed_password,
|
||||
# # salt: authenticator.salt,
|
||||
# # password_algorithm: authenticator.algorithm_name,
|
||||
# active: true,
|
||||
# approved: true,
|
||||
# custom_fields: { 'custom_password_md5' => nil }
|
||||
# )
|
||||
|
||||
|
||||
# if user.save
|
||||
# Rails.logger.warn "User changes saved: #{user.username}"
|
||||
# else
|
||||
# Rails.logger.warn "User changes FAILED: #{user.errors.full_messages}"
|
||||
# invalid_credentials
|
||||
# return
|
||||
# end
|
||||
|
||||
|
||||
Rails.logger.warn "Updated user: #{user.id}"
|
||||
else
|
||||
# MD5 doesn't match, so we have a failed login attempt.
|
||||
Rails.logger.warn "MD5 Password incorrect for user: #{user.id}"
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
|
||||
elsif !user.confirm_password?(password)
|
||||
# There is no MD5 password and the password was incorrect.
|
||||
Rails.logger.warn "Password incorrect for user: #{user.id}"
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
|
||||
# If the site requires user approval and the user is not approved yet
|
||||
if login_not_approved_for?(user)
|
||||
render json: login_not_approved
|
||||
return
|
||||
end
|
||||
|
||||
# User signed on with username and password, so let's prevent the invite link
|
||||
# from being used to log in (if one exists).
|
||||
Invite.invalidate_for_email(user.email)
|
||||
|
||||
# User's password has expired so they need to reset it
|
||||
if user.password_expired?(password)
|
||||
render json: { error: "expired", reason: "expired" }
|
||||
return
|
||||
end
|
||||
else
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
|
||||
if payload = login_error_check(user)
|
||||
return render json: payload
|
||||
end
|
||||
|
||||
second_factor_auth_result = authenticate_second_factor(user)
|
||||
return render(json: @second_factor_failure_payload) unless second_factor_auth_result.ok
|
||||
|
||||
if user.active && user.email_confirmed?
|
||||
login(user, second_factor_auth_result)
|
||||
else
|
||||
not_activated(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user