diff --git a/supabase/_async/client.py b/supabase/_async/client.py
index ad21c7cd..e2fec5b5 100644
--- a/supabase/_async/client.py
+++ b/supabase/_async/client.py
@@ -16,17 +16,11 @@
 from storage3.constants import DEFAULT_TIMEOUT as DEFAULT_STORAGE_CLIENT_TIMEOUT
 from supafunc import AsyncFunctionsClient
 
-from ..lib.client_options import AsyncClientOptions as ClientOptions
+from ..lib.client_options import ClientOptions
+from ..utils import AuthProxy, SupabaseException
 from .auth_client import AsyncSupabaseAuthClient
 
 
-# Create an exception class when user does not provide a valid url or key.
-class SupabaseException(Exception):
-    def __init__(self, message: str):
-        self.message = message
-        super().__init__(self.message)
-
-
 class AsyncClient:
     """Supabase client class."""
 
@@ -78,10 +72,15 @@ def __init__(
         self.functions_url = f"{supabase_url}/functions/v1"
 
         # Instantiate clients.
-        self.auth = self._init_supabase_auth_client(
-            auth_url=self.auth_url,
-            client_options=options,
-        )
+        if not options.access_token:
+            self.auth = self._init_supabase_auth_client(
+                auth_url=self.auth_url,
+                client_options=options,
+            )
+        else:
+            self.access_token = options.access_token
+            self.auth = AuthProxy()
+
         self.realtime = self._init_realtime_client(
             realtime_url=self.realtime_url,
             supabase_key=self.supabase_key,
@@ -90,7 +89,9 @@ def __init__(
         self._postgrest = None
         self._storage = None
         self._functions = None
-        self.auth.on_auth_state_change(self._listen_to_auth_events)
+
+        if not options.access_token:
+            self.auth.on_auth_state_change(self._listen_to_auth_events)
 
     @classmethod
     async def create(
@@ -104,8 +105,13 @@ async def create(
 
         if auth_header is None:
             try:
-                session = await client.auth.get_session()
-                session_access_token = client._create_auth_header(session.access_token)
+                if not options.access_token:
+                    session = await client.auth.get_session()
+                    session_access_token = client._create_auth_header(
+                        session.access_token
+                    )
+                else:
+                    session_access_token = options.access_token
             except Exception as err:
                 session_access_token = None
 
diff --git a/supabase/_sync/client.py b/supabase/_sync/client.py
index 680a7aea..c85e0fbb 100644
--- a/supabase/_sync/client.py
+++ b/supabase/_sync/client.py
@@ -15,17 +15,11 @@
 from storage3.constants import DEFAULT_TIMEOUT as DEFAULT_STORAGE_CLIENT_TIMEOUT
 from supafunc import SyncFunctionsClient
 
-from ..lib.client_options import SyncClientOptions as ClientOptions
+from ..lib.client_options import ClientOptions
+from ..utils import AuthProxy, SupabaseException
 from .auth_client import SyncSupabaseAuthClient
 
 
-# Create an exception class when user does not provide a valid url or key.
-class SupabaseException(Exception):
-    def __init__(self, message: str):
-        self.message = message
-        super().__init__(self.message)
-
-
 class SyncClient:
     """Supabase client class."""
 
@@ -77,10 +71,15 @@ def __init__(
         self.functions_url = f"{supabase_url}/functions/v1"
 
         # Instantiate clients.
-        self.auth = self._init_supabase_auth_client(
-            auth_url=self.auth_url,
-            client_options=options,
-        )
+        if not options.access_token:
+            self.auth = self._init_supabase_auth_client(
+                auth_url=self.auth_url,
+                client_options=options,
+            )
+        else:
+            self.access_token = options.access_token
+            self.auth = AuthProxy()
+
         self.realtime = self._init_realtime_client(
             realtime_url=self.realtime_url,
             supabase_key=self.supabase_key,
@@ -89,7 +88,9 @@ def __init__(
         self._postgrest = None
         self._storage = None
         self._functions = None
-        self.auth.on_auth_state_change(self._listen_to_auth_events)
+
+        if not options.access_token:
+            self.auth.on_auth_state_change(self._listen_to_auth_events)
 
     @classmethod
     def create(
@@ -103,8 +104,13 @@ def create(
 
         if auth_header is None:
             try:
-                session = client.auth.get_session()
-                session_access_token = client._create_auth_header(session.access_token)
+                if not options.access_token:
+                    session = client.auth.get_session()
+                    session_access_token = client._create_auth_header(
+                        session.access_token
+                    )
+                else:
+                    session_access_token = options.access_token
             except Exception as err:
                 session_access_token = None
 
diff --git a/supabase/lib/client_options.py b/supabase/lib/client_options.py
index 47498c13..31ea7c36 100644
--- a/supabase/lib/client_options.py
+++ b/supabase/lib/client_options.py
@@ -1,5 +1,5 @@
 from dataclasses import dataclass, field
-from typing import Dict, Optional, Union
+from typing import Awaitable, Callable, Dict, Optional, Union
 
 from gotrue import (
     AsyncMemoryStorage,
@@ -59,6 +59,15 @@ class ClientOptions:
     flow_type: AuthFlowType = "pkce"
     """flow type to use for authentication"""
 
+    access_token: Union[Callable[[], str], None] = None
+    """Optional function for using a third-party authentication system with Supabase.
+    The function should return an access token or ID token (JWT) by obtaining it from the third-party auth client library.
+    Note that this funciton may be called concurrently and many times.
+    Use memoization and locking techniques if this is not supported by the clinet libraries.
+
+    When set, the `auth` namespace of the Supabase client cannot be used.
+    Create another client if you wish to use Supabase Auth and third-party authentications concurrently in the same application."""
+
     def replace(
         self,
         schema: Optional[str] = None,
@@ -74,6 +83,7 @@ def replace(
             int, float, Timeout
         ] = DEFAULT_STORAGE_CLIENT_TIMEOUT,
         flow_type: Optional[AuthFlowType] = None,
+        access_token: Union[Callable[[], str], None] = None,
     ) -> "ClientOptions":
         """Create a new SupabaseClientOptions with changes"""
         client_options = ClientOptions()
@@ -92,6 +102,7 @@ def replace(
             storage_client_timeout or self.storage_client_timeout
         )
         client_options.flow_type = flow_type or self.flow_type
+        client_options.access_token = access_token or self.access_token
         return client_options
 
 
@@ -100,6 +111,8 @@ class AsyncClientOptions(ClientOptions):
     storage: AsyncSupportedStorage = field(default_factory=AsyncMemoryStorage)
     """A storage provider. Used to store the logged in session."""
 
+    access_token: Union[Callable[[], Awaitable[str]], None] = None
+
     def replace(
         self,
         schema: Optional[str] = None,
@@ -115,6 +128,7 @@ def replace(
             int, float, Timeout
         ] = DEFAULT_STORAGE_CLIENT_TIMEOUT,
         flow_type: Optional[AuthFlowType] = None,
+        access_token: Union[Callable[[], Awaitable[str]], None] = None,
     ) -> "AsyncClientOptions":
         """Create a new SupabaseClientOptions with changes"""
         client_options = AsyncClientOptions()
@@ -133,6 +147,7 @@ def replace(
             storage_client_timeout or self.storage_client_timeout
         )
         client_options.flow_type = flow_type or self.flow_type
+        client_options.access_token = access_token or self.access_token
         return client_options
 
 
@@ -153,6 +168,7 @@ def replace(
             int, float, Timeout
         ] = DEFAULT_STORAGE_CLIENT_TIMEOUT,
         flow_type: Optional[AuthFlowType] = None,
+        access_token: Union[Callable[[], Awaitable[str]], None] = None,
     ) -> "SyncClientOptions":
         """Create a new SupabaseClientOptions with changes"""
         client_options = SyncClientOptions()
@@ -171,4 +187,5 @@ def replace(
             storage_client_timeout or self.storage_client_timeout
         )
         client_options.flow_type = flow_type or self.flow_type
+        client_options.access_token = access_token or self.access_token
         return client_options
diff --git a/supabase/utils.py b/supabase/utils.py
new file mode 100644
index 00000000..70410848
--- /dev/null
+++ b/supabase/utils.py
@@ -0,0 +1,12 @@
+# Create an exception class when user does not provide a valid url or key.
+class SupabaseException(Exception):
+    def __init__(self, message: str):
+        self.message = message
+        super().__init__(self.message)
+
+
+class AuthProxy:
+    def __getattr__(self, attr):
+        raise SupabaseException(
+            f"Supabase Client is configured with the access_token option, accessing supabase.auth.{attr} is not possible.",
+        )
diff --git a/tests/test_client.py b/tests/test_client.py
index d8f0be0c..93ca51f0 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -119,3 +119,21 @@ def test_updates_the_authorization_header_on_auth_events() -> None:
 
     assert client.storage.session.headers.get("apiKey") == key
     assert client.storage.session.headers.get("Authorization") == updated_authorization
+
+
+def test_init_client_with_access_token() -> None:
+    url = os.environ.get("SUPABASE_TEST_URL")
+    key = os.environ.get("SUPABASE_TEST_KEY")
+
+    client = create_client(
+        url, key, options=ClientOptions(access_token=lambda: "secretuserjwt")
+    )
+
+    assert client.access_token is not None
+
+    with pytest.raises(SupabaseException) as e:
+        client.auth.get_user()
+    assert (
+        str(e.value.message)
+        == "Supabase Client is configured with the access_token option, accessing supabase.auth.get_user is not possible."
+    )