diff --git a/app/assets/locales/en.json b/app/assets/locales/en.json
index 2fec3e4d1ba2c654ac79668939e0d9b50523a26f..8d58b358fb08e337267d6c3c1d561bdc1341708f 100644
--- a/app/assets/locales/en.json
+++ b/app/assets/locales/en.json
@@ -81,6 +81,7 @@
       "account_info": "Account Info",
       "delete_account": "Delete Account",
       "change_password": "Change Password",
+      "set_password": "Set Your New Password",
       "reset_password": "Reset Password",
       "update_account_info": "Update Account Info",
       "current_password": "Current Password",
@@ -358,6 +359,7 @@
         "user_updated": "The user has been updated.",
         "user_deleted": "The user has been deleted.",
         "avatar_updated": "The avatar has been updated.",
+        "password_changed": "Successfully updated your password. Please sign in again.",
         "password_updated": "The password has been updated.",
         "account_activated": "Your account has been activated.",
         "activation_email_sent": "An email that contains the instructions to activate your account has been sent.",
diff --git a/app/controllers/api/v1/api_controller.rb b/app/controllers/api/v1/api_controller.rb
index 92b27351bf055a2950028e5609f9491d0503c2ff..0ebbe53fa198c389075bfaafd7b62ac3bb5ae4c4 100644
--- a/app/controllers/api/v1/api_controller.rb
+++ b/app/controllers/api/v1/api_controller.rb
@@ -90,8 +90,10 @@ module Api
       end
 
       # Checks if external authentication is enabled (currently only OIDC is implemented)
-      def external_authn_enabled?
-        ENV['OPENID_CONNECT_ISSUER'].present?
+      def external_auth?
+        return ENV['OPENID_CONNECT_ISSUER'].present? if ENV['LOADBALANCER_ENDPOINT'].blank?
+
+        !Tenant.exists?(name: current_provider, client_secret: 'local')
       end
     end
   end
diff --git a/app/controllers/api/v1/env_controller.rb b/app/controllers/api/v1/env_controller.rb
index 946e261c2f4510629dd09bf2a59dd0c9c32b86b4..4982b208e08f269136efceb4faf8f393f8848809 100644
--- a/app/controllers/api/v1/env_controller.rb
+++ b/app/controllers/api/v1/env_controller.rb
@@ -25,7 +25,7 @@ module Api
       # Returns basic NON-CONFIDENTIAL information on the environment variables
       def index
         render_data data: {
-          EXTERNAL_AUTH: ENV['OPENID_CONNECT_ISSUER'].present?, # currently only OIDC is implemented
+          EXTERNAL_AUTH: external_auth?,
           HCAPTCHA_KEY: ENV.fetch('HCAPTCHA_SITE_KEY', nil),
           VERSION_TAG: ENV.fetch('VERSION_TAG', ''),
           CURRENT_PROVIDER: current_provider,
diff --git a/app/controllers/api/v1/sessions_controller.rb b/app/controllers/api/v1/sessions_controller.rb
index 65a07e91255214f90cb513560989018c507307da..41eb19cbe6d249a5e6ea9d8c9cadb072f012c738 100644
--- a/app/controllers/api/v1/sessions_controller.rb
+++ b/app/controllers/api/v1/sessions_controller.rb
@@ -45,6 +45,12 @@ module Api
         # Will return an error if the user is NOT from the current provider and if the user is NOT a super admin
         return render_error if user.provider != current_provider && !user.super_admin?
 
+        # Password is not set (local user migrated from v2)
+        if user.external_id.blank? && user.password_digest.blank?
+          token = user.generate_reset_token!
+          return render_error data: token, errors: 'PasswordNotSet'
+        end
+
         # TODO: Add proper error logging for non-verified token hcaptcha
         if user.authenticate(session_params[:password])
           return render_error data: user.id, errors: Rails.configuration.custom_error_msgs[:unverified_user] unless user.verified?
diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb
index f00dd0e31dd16b4f9ce85958593b9657cca9fa03..98b5202494f5dff432c68afd80689f552797d0ab 100644
--- a/app/controllers/api/v1/users_controller.rb
+++ b/app/controllers/api/v1/users_controller.rb
@@ -39,7 +39,7 @@ module Api
       # POST /api/v1/users.json
       # Creates and saves a new user record in the database with the provided parameters
       def create
-        return render_error status: :forbidden if external_authn_enabled?
+        return render_error status: :forbidden if external_auth?
 
         # Check if this is an admin creating a user
         admin_create = current_user && PermissionsChecker.new(current_user:, permission_names: 'ManageUsers', current_provider:).call
diff --git a/app/javascript/components/users/password_management/ResetPassword.jsx b/app/javascript/components/users/password_management/ResetPassword.jsx
index b3ace1a9e25ec71bf9ac857ca0f205304bf3a4d0..56c35ab543a645ebfc7ae06122c2962e39eb799f 100644
--- a/app/javascript/components/users/password_management/ResetPassword.jsx
+++ b/app/javascript/components/users/password_management/ResetPassword.jsx
@@ -17,11 +17,13 @@
 import React, { useEffect } from 'react';
 import Card from 'react-bootstrap/Card';
 import { useParams } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
 import useVerifyToken from '../../../hooks/mutations/users/useVerifyToken';
 import ResetPwdForm from './forms/ResetPwdForm';
 import Logo from '../../shared_components/Logo';
 
 export default function ResetPassword() {
+  const { t } = useTranslation();
   const { token } = useParams();
   const verifyTokenAPI = useVerifyToken(token);
 
@@ -37,6 +39,7 @@ export default function ResetPassword() {
         <Logo />
       </div>
       <Card className="col-xl-5 col-lg-6 col-md-8 col-10 mx-auto p-4 border-0 card-shadow">
+        <Card.Title className="text-center pb-2"> { t('user.account.set_password') } </Card.Title>
         <ResetPwdForm token={token} />
       </Card>
     </div>
diff --git a/app/javascript/hooks/mutations/sessions/useCreateSession.jsx b/app/javascript/hooks/mutations/sessions/useCreateSession.jsx
index 801865491655f0c8b8c76fd18ef1c5742e27e896..10fef82ec0856eaf50649fc9059a675269bdefc1 100644
--- a/app/javascript/hooks/mutations/sessions/useCreateSession.jsx
+++ b/app/javascript/hooks/mutations/sessions/useCreateSession.jsx
@@ -49,6 +49,8 @@ export default function useCreateSession() {
           toast.error(t('toast.error.users.banned'));
         } else if (err.response.data.errors === 'UnverifiedUser') {
           navigate(`/verify?id=${err.response.data.data}`);
+        } else if (err.response.data.errors === 'PasswordNotSet') {
+          navigate(`/reset_password/${err.response.data.data}`);
         } else {
           toast.error(t('toast.error.session.invalid_credentials'));
         }
diff --git a/app/javascript/hooks/mutations/users/useResetPwd.jsx b/app/javascript/hooks/mutations/users/useResetPwd.jsx
index d2aae133492e49434afcc6198b7c7740393b2570..8ff67d4684492a148e7057e74ea4c5ce2ed59572 100644
--- a/app/javascript/hooks/mutations/users/useResetPwd.jsx
+++ b/app/javascript/hooks/mutations/users/useResetPwd.jsx
@@ -28,7 +28,7 @@ export default function useResetPwd() {
     (user) => axios.post('/reset_password/reset.json', { user }),
     {
       onSuccess: () => {
-        toast.success(t('toast.success.user.password_updated'));
+        toast.success(t('toast.success.user.password_changed'));
         navigate('/signin');
       },
       onError: () => {
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index 7c61036e82baa83ae9f4c6756b6e9640b63270bc..e7f59cde50153a031ed84efb86fd5bb5447a27ab 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Api::V1::UsersController, type: :controller do
 
   before do
     ENV['SMTP_SERVER'] = 'test.com'
-    allow(controller).to receive(:external_authn_enabled?).and_return(false)
+    allow(controller).to receive(:external_auth?).and_return(false)
     request.headers['ACCEPT'] = 'application/json'
   end
 
@@ -280,7 +280,7 @@ RSpec.describe Api::V1::UsersController, type: :controller do
 
     context 'External AuthN enabled' do
       before do
-        allow(controller).to receive(:external_authn_enabled?).and_return(true)
+        allow(controller).to receive(:external_auth?).and_return(true)
       end
 
       it 'returns :forbidden without creating the user account' do
@@ -472,9 +472,9 @@ RSpec.describe Api::V1::UsersController, type: :controller do
   end
 
   context 'private methods' do
-    describe '#external_authn_enabled?' do
+    describe '#external_auth??' do
       before do
-        allow(controller).to receive(:external_authn_enabled?).and_call_original
+        allow(controller).to receive(:external_auth?).and_call_original
       end
 
       context 'OPENID_CONNECT_ISSUER is present?' do
@@ -483,7 +483,7 @@ RSpec.describe Api::V1::UsersController, type: :controller do
         end
 
         it 'returns true' do
-          expect(controller).to be_external_authn_enabled
+          expect(controller).to be_external_auth
         end
       end
 
@@ -493,7 +493,7 @@ RSpec.describe Api::V1::UsersController, type: :controller do
         end
 
         it 'returns false' do
-          expect(controller).not_to be_external_authn_enabled
+          expect(controller).not_to be_external_auth
         end
       end
     end