diff --git a/web/config.py b/web/config.py
index c23c5a56c..309415129 100644
--- a/web/config.py
+++ b/web/config.py
@@ -690,6 +690,12 @@ KRB_AUTO_CREATE_USER = True
 
 KERBEROS_CCACHE_DIR = os.path.join(DATA_DIR, 'krbccache')
 
+#############################################################################
+# Create local directory to store azure credential cache
+#############################################################################
+
+AZURE_CREDENTIAL_CACHE_DIR = os.path.join(DATA_DIR, 'azurecredentialcache')
+
 ##########################################################################
 # OAuth2 Configuration
 ##########################################################################
diff --git a/web/pgacloud/providers/azure.py b/web/pgacloud/providers/azure.py
index ba1a109e6..fbfae9ded 100644
--- a/web/pgacloud/providers/azure.py
+++ b/web/pgacloud/providers/azure.py
@@ -14,13 +14,15 @@ from azure.mgmt.rdbms.postgresql_flexibleservers import \
 from azure.mgmt.rdbms.postgresql_flexibleservers.models import Sku, SkuTier, \
     CreateMode, Storage, Server, FirewallRule, HighAvailability
 from azure.identity import AzureCliCredential, InteractiveBrowserCredential, \
-    AuthenticationRecord, TokenCachePersistenceOptions
+    AuthenticationRecord
 from azure.mgmt.resource import ResourceManagementClient
 from azure.core.exceptions import ResourceNotFoundError
 from providers._abstract import AbsProvider
 import os
 from utils.io import debug, error, output
 from utils.misc import get_my_ip, get_random_id
+from pgadmin.misc.cloud.azure.azure_cache import load_persistent_cache, \
+    TokenCachePersistenceOptions
 
 
 class AzureProvider(AbsProvider):
@@ -36,6 +38,7 @@ class AzureProvider(AbsProvider):
         self._credentials = None
         self._authentication_record_json = None
         self._cli_credentials = None
+        self.azure_cred_cache_name = None
 
         # Get the credentials
         if 'AUTHENTICATION_RECORD_JSON' in os.environ:
@@ -55,6 +58,9 @@ class AzureProvider(AbsProvider):
         if 'AZURE_DATABASE_PASSWORD' in os.environ:
             self._database_pass = os.environ['AZURE_DATABASE_PASSWORD']
 
+        if 'AZURE_CRED_CACHE_NAME' in os.environ:
+            self.azure_cred_cache_name = os.environ['AZURE_CRED_CACHE_NAME']
+
     def init_args(self, parsers):
         """ Create the command line parser for this provider """
         self.parser = parsers. \
@@ -162,16 +168,19 @@ class AzureProvider(AbsProvider):
             _credential = InteractiveBrowserCredential(
                 tenant_id=self._tenant_id,
                 timeout=180,
-                cache_persistence_options=TokenCachePersistenceOptions(
-                    allow_unencrypted_storage=True
-                ),
+                _cache=load_persistent_cache(
+                    TokenCachePersistenceOptions(
+                        name=self.azure_cred_cache_name,
+                        allow_unencrypted_storage=True)),
                 authentication_record=deserialized_auth_record)
         else:
             _credential = InteractiveBrowserCredential(
                 tenant_id=self._tenant_id,
                 timeout=180,
-                cache_persistence_options=TokenCachePersistenceOptions(
-                    allow_unencrypted_storage=True)
+                _cache=load_persistent_cache(
+                    TokenCachePersistenceOptions(
+                        name=self.azure_cred_cache_name,
+                        allow_unencrypted_storage=True))
             )
         return _credential
 
@@ -185,14 +194,10 @@ class AzureProvider(AbsProvider):
         if type in self._clients:
             return self._clients[type]
 
-        if type == 'postgresql':
-            client = PostgreSQLManagementClient(self._credentials,
-                                                self._subscription_id)
-        elif type == 'resource':
-            client = ResourceManagementClient(self._credentials,
-                                              self._subscription_id)
-
-        self._clients[type] = client
+        self._clients['postgresql'] = PostgreSQLManagementClient(
+            self._credentials, self._subscription_id)
+        self._clients['resource'] = ResourceManagementClient(
+            self._credentials, self._subscription_id)
 
         return self._clients[type]
 
diff --git a/web/pgadmin/misc/cloud/azure/__init__.py b/web/pgadmin/misc/cloud/azure/__init__.py
index 693caa48c..0d49cd666 100644
--- a/web/pgadmin/misc/cloud/azure/__init__.py
+++ b/web/pgadmin/misc/cloud/azure/__init__.py
@@ -8,6 +8,9 @@
 # ##########################################################################
 
 # Azure implementation
+import random
+
+import config
 from pgadmin.misc.cloud.utils import _create_server, CloudProcessDesc
 from pgadmin.misc.bgprocess.processes import BatchProcess
 from pgadmin import make_json_response
@@ -15,12 +18,16 @@ from pgadmin.utils import PgAdminModule
 from flask_security import login_required
 import simplejson as json
 from flask import session, current_app, request
+from flask_login import current_user
 from config import root
+from .azure_cache import load_persistent_cache, TokenCachePersistenceOptions
+import os
+
 
 from azure.mgmt.rdbms.postgresql_flexibleservers import \
     PostgreSQLManagementClient
-from azure.identity import AzureCliCredential, InteractiveBrowserCredential, \
-    TokenCachePersistenceOptions, AuthenticationRecord
+from azure.identity import AzureCliCredential, InteractiveBrowserCredential,\
+    AuthenticationRecord
 from azure.mgmt.resource import ResourceManagementClient
 from azure.mgmt.subscription import SubscriptionClient
 from azure.mgmt.rdbms.postgresql_flexibleservers.models import \
@@ -239,6 +246,8 @@ class Azure:
         self.subscription_id = None
         self._availability_zone = None
         self._available_capabilities_list = []
+        self.cache_name = None
+        self.cache_name = current_user.username + "_msal.cache"
 
     ##########################################################################
     # Azure Helper functions
@@ -250,6 +259,7 @@ class Azure:
         :return: True if valid credentials else false
         """
         status, identity = self._get_azure_credentials()
+        session['azure']['azure_cache_file_name'] = self.cache_name
         error = ''
         if not status:
             error = identity
@@ -288,16 +298,18 @@ class Azure:
             _credential = InteractiveBrowserCredential(
                 tenant_id=self._tenant_id,
                 timeout=180,
-                cache_persistence_options=TokenCachePersistenceOptions(
-                    allow_unencrypted_storage=True
-                ),
+                _cache=load_persistent_cache(
+                    TokenCachePersistenceOptions(
+                        name=self.cache_name,
+                        allow_unencrypted_storage=True)),
                 authentication_record=deserialized_auth_record)
         else:
             _credential = InteractiveBrowserCredential(
                 tenant_id=self._tenant_id,
                 timeout=180,
-                cache_persistence_options=TokenCachePersistenceOptions(
-                    allow_unencrypted_storage=True)
+                _cache=load_persistent_cache(TokenCachePersistenceOptions(
+                    name=self.cache_name,
+                    allow_unencrypted_storage=True))
             )
         return _credential
 
@@ -672,6 +684,7 @@ def deploy_on_azure(data):
         azure = session['azure']['azure_obj']
         env['AZURE_SUBSCRIPTION_ID'] = azure.subscription_id
         env['AUTH_TYPE'] = data['secret']['auth_type']
+        env['AZURE_CRED_CACHE_NAME'] = azure.cache_name
         if azure.authentication_record_json is not None:
             env['AUTHENTICATION_RECORD_JSON'] = \
                 azure.authentication_record_json
@@ -684,14 +697,20 @@ def deploy_on_azure(data):
         p.set_env_variables(None, env=env)
         p.update_server_id(p.id, sid)
         p.start()
-        del session['azure']['azure_obj']
         return True, {'label': _label, 'sid': sid}
     except Exception as e:
         current_app.logger.exception(e)
         return False, str(e)
+    finally:
+        del session['azure']['azure_obj']
 
 
 def clear_azure_session():
     """Clear session data."""
     if 'azure' in session:
+        file_name = session['azure']['azure_cache_file_name']
+        file = config.AZURE_CREDENTIAL_CACHE_DIR + '/' + file_name
+        # Delete cache file if exists
+        if os.path.exists(file):
+            os.remove(file)
         session.pop('azure')
diff --git a/web/pgadmin/misc/cloud/azure/azure_cache.py b/web/pgadmin/misc/cloud/azure/azure_cache.py
new file mode 100644
index 000000000..5b0eb9255
--- /dev/null
+++ b/web/pgadmin/misc/cloud/azure/azure_cache.py
@@ -0,0 +1,136 @@
+# ------------------------------------
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+# ------------------------------------
+import logging
+import os
+import sys
+from typing import TYPE_CHECKING
+import config
+
+
+import six
+
+if TYPE_CHECKING:
+    from typing import Any
+    import msal_extensions
+
+_LOGGER = logging.getLogger(__name__)
+
+
+class TokenCachePersistenceOptions(object):
+    """Options for persistent token caching.
+
+    Most credentials accept an instance of this class to configure persistent
+    token caching. The default values configure a credential to use a cache
+    shared with Microsoft developer tools and
+    :class:`~azure.identity.SharedTokenCacheCredential`.
+    To isolate a credential's data from other applications,
+    specify a `name` for the cache.
+
+    By default, the cache is encrypted with the current platform's user data
+    protection API, and will raise an error when this is not available.
+    To configure the cache to fall back to an unencrypted file instead
+    of raising an error, specify `allow_unencrypted_storage=True`.
+
+    .. warning:: The cache contains authentication secrets. If the cache is
+     not encrypted, protecting it is the application's responsibility.
+     A breach of its contents will fully compromise accounts.
+
+        .. literalinclude:: ../tests/test_persistent_cache.py
+            :start-after: [START snippet]
+            :end-before: [END snippet]
+            :language: python
+            :caption: Configuring a credential for persistent caching
+            :dedent: 8
+
+    :keyword str name: name of the cache, used to isolate its data from other
+        applications. Defaults to the name of the cache shared by Microsoft
+        dev tools and :class:`~azure.identity.SharedTokenCacheCredential`.
+    :keyword bool allow_unencrypted_storage: whether the cache should fall
+        back to storing its data in plain text when
+        encryption isn't possible. False by default. Setting this to
+        True does not disable encryption. The cache will
+        always try to encrypt its data.
+    """
+
+    def __init__(self, **kwargs):
+        # type: (**Any) -> None
+        self.allow_unencrypted_storage = \
+            kwargs.get("allow_unencrypted_storage", False)
+        self.name = kwargs.get("name", "msal.cache")
+
+
+def load_persistent_cache(options):
+    # type:
+    # (TokenCachePersistenceOptions) -> msal_extensions.PersistedTokenCache
+    import msal_extensions
+    persistence = _get_persistence(
+        allow_unencrypted=options.allow_unencrypted_storage,
+        account_name="MSALCache",
+        cache_name=options.name
+    )
+    return msal_extensions.PersistedTokenCache(persistence)
+
+
+def _get_persistence(allow_unencrypted, account_name, cache_name):
+    # type: (bool, str, str) -> msal_extensions.persistence.BasePersistence
+    """Get an msal_extensions persistence instance for the current platform.
+
+    On Windows the cache is a file protected by the Data Protection API.
+    On Linux and macOS the cache is stored by
+    libsecret and Keychain, respectively. On those platforms the cache uses
+    the modified timestamp of a file on disk to
+    decide whether to reload the cache.
+
+    :param bool allow_unencrypted: when True, the cache will be kept in
+    plaintext should encryption be impossible in the
+        current environment
+    """
+    import msal_extensions
+    cache_location = \
+        os.path.join(config.AZURE_CREDENTIAL_CACHE_DIR, cache_name)
+
+    if sys.platform.startswith("win") and "LOCALAPPDATA" in os.environ:
+        return \
+            msal_extensions.FilePersistenceWithDataProtection(cache_location)
+
+    if sys.platform.startswith("darwin"):
+        # the cache uses this file's modified timestamp
+        # to decide whether to reload
+        return msal_extensions.KeychainPersistence(
+            cache_location,
+            "Microsoft.Developer.IdentityService",
+            account_name)
+
+    if sys.platform.startswith("linux"):
+        # The cache uses this file's modified timestamp to decide whether
+        # to reload. Note this path is the same as that of the plaintext
+        # fallback: a new encrypted cache will stomp an unencrypted cache.
+
+        try:
+            return msal_extensions.LibsecretPersistence(
+                cache_location, cache_name,
+                {"MsalClientID": "Microsoft.Developer.IdentityService"},
+                label=account_name
+            )
+        except Exception as ex:  # pylint:disable=broad-except
+            _LOGGER.debug(
+                'msal-extensions is unable to encrypt '
+                'a persistent cache: "%s"', ex, exc_info=True)
+            if not allow_unencrypted:
+                error = ValueError(
+                    "Cache encryption is impossible because libsecret "
+                    "dependencies are not installed or are unusable,"
+                    " for example because no display is available "
+                    "(as in an SSH session). The chained exception has"
+                    ' more information. Specify '
+                    '"allow_unencrypted_storage=True" to store'
+                    ' the cache unencrypted'
+                    " instead of raising this exception."
+                )
+                six.raise_from(error, ex)
+        return msal_extensions.FilePersistence(cache_location)
+
+    raise NotImplementedError("A persistent cache is not "
+                              "available in this environment.")
diff --git a/web/pgadmin/misc/cloud/static/js/cloud.js b/web/pgadmin/misc/cloud/static/js/cloud.js
index ac1711fd8..bf3f0e7b1 100644
--- a/web/pgadmin/misc/cloud/static/js/cloud.js
+++ b/web/pgadmin/misc/cloud/static/js/cloud.js
@@ -125,7 +125,7 @@ define('pgadmin.misc.cloud', [
             hooks: {
               // Triggered when the dialog is closed
               onclose: function () {
-                if(event.target instanceof Object){
+                if(event.target instanceof Object && event.target.className == 'ajs-close'){
                   const axiosApi = getApiInstance();
                   let _url = url_for('cloud.clear_cloud_session');
                   axiosApi.post(_url)
diff --git a/web/pgadmin/setup/data_directory.py b/web/pgadmin/setup/data_directory.py
index d73c9816f..c7c118c08 100644
--- a/web/pgadmin/setup/data_directory.py
+++ b/web/pgadmin/setup/data_directory.py
@@ -112,6 +112,22 @@ def create_app_data_directory(config):
                 config.APP_VERSION))
         exit(1)
 
+    # Create Azure Credential Cache directory (if not present).
+    try:
+        _create_directory_if_not_exists(config.AZURE_CREDENTIAL_CACHE_DIR)
+    except PermissionError as e:
+        print(FAILED_CREATE_DIR.format(config.AZURE_CREDENTIAL_CACHE_DIR, e))
+        print(
+            "HINT   : Create the directory {}, ensure it is writable by\n"
+            "'{}', and try again, or, create a config_local.py file\n"
+            " and override the AZURE_CREDENTIAL_CACHE_DIR setting per\n"
+            " https://www.pgadmin.org/docs/pgadmin4/{}/config_py.html".
+            format(
+                config.AZURE_CREDENTIAL_CACHE_DIR,
+                getpass.getuser(),
+                config.APP_VERSION))
+        exit(1)
+
     # Create Kerberos Credential Cache directory (if not present).
     if config.SERVER_MODE and KERBEROS in config.AUTHENTICATION_SOURCES:
         try:
