We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug: regression v2.0.0beta4 -> main@HEAD
### Description

There appears to be a regression between tag v2.0.0beta4 and the current (2.0.0rc1 PyPi release) (or if you prefer, also commit d257d099993179f1133a96441bf816e1de435007, which is the latest commit on main. This seems very likely related to #2160  which my guess would be only fixed the problem for JWT, not the SessionAuth middleware that I am using.

### URL to code causing the issue

https://github.com/Mattwmaster58/MacTrack/tree/broken-auth

### MCVE

```python
(working on this)
```


### Steps to reproduce

```bash
1. Clone repo, checkout `broken-auth` branch, poetry install, run, request to OPTIONS endpoint, observe:

`INFO:     127.0.0.1:55754 - "OPTIONS /api/filters/create HTTP/1.1" 401 Unauthorized`
```


### Screenshots

_No response_

### Logs

```bash
ERROR - 2023-08-19 18:27:03,266908605 - litestar - middleware - exception raised on http connection to route /api/filters/create

Traceback (most recent call last):
  File "/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py", line 191, in __call__
    await self.app(scope, receive, send)
  File "/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/middleware/authentication.py", line 87, in __call__
    auth_result = await self.authenticate_request(ASGIConnection(scope))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/security/session_auth/middleware.py", line 111, in authenticate_request
    raise NotAuthorizedException("no session data found")
litestar.exceptions.http_exceptions.NotAuthorizedException: 401: no session data found
Traceback (most recent call last):
  File "/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py", line 191, in __call__
    await self.app(scope, receive, send)
  File "/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/middleware/authentication.py", line 87, in __call__
    auth_result = await self.authenticate_request(ASGIConnection(scope))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/security/session_auth/middleware.py", line 111, in authenticate_request
    raise NotAuthorizedException("no session data found")
litestar.exceptions.http_exceptions.NotAuthorizedException: 401: no session data found
INFO:     127.0.0.1:55754 - "OPTIONS /api/filters/create HTTP/1.1" 401 Unauthorized
```


### Litestar Version

2.0.0rc1 as well as d257d099993179f1133a96441bf816e1de435007

### Platform

- [X] Linux
- [ ] Mac
- [ ] Windows
- [ ] Other (Please specify in the description above)

<!-- POLAR PLEDGE BADGE START -->
---

## Funding
* If you would like to see an issue prioritized, make a pledge towards it!
* We receive the pledge once the issue is completed & verified

<a href="https://polar.sh/litestar-org/litestar/issues/2181">
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/litestar-org/litestar/issues/2181/pledge.svg?darkmode=1">
  <img alt="Fund with Polar" src="https://polar.sh/api/github/litestar-org/litestar/issues/2181/pledge.svg">
</picture>
</a>
<!-- POLAR PLEDGE BADGE END -->

StaticFilesConfig and virtual directories
I'm trying to write a ``FileSystemProtocol`` to load files from the package data using [importlib_resources](https://importlib-resources.readthedocs.io/en/latest/using.html#). But because ``directories`` is defined as ``DirectoryPath``, pydantic checks if the given directories exist in the local filesystem. 

This is not generally true, especially in any kind of virtual filesystem (e.g. a zipped package). I think this condition should be relaxed to support virtual filesystems.

https://github.com/starlite-api/starlite/blob/9bb6dcd57c10a591377cf8e3a537e9292566d5b9/starlite/config/static_files.py#L32

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `litestar/security/session_auth/auth.py`
Content:
```
1 from __future__ import annotations
2 
3 from dataclasses import dataclass, field
4 from typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterable
5 
6 from litestar.middleware.base import DefineMiddleware
7 from litestar.middleware.session.base import BaseBackendConfig, BaseSessionBackendT
8 from litestar.openapi.spec import Components, SecurityRequirement, SecurityScheme
9 from litestar.security.base import AbstractSecurityConfig, UserType
10 from litestar.security.session_auth.middleware import MiddlewareWrapper, SessionAuthMiddleware
11 
12 __all__ = ("SessionAuth",)
13 
14 if TYPE_CHECKING:
15     from litestar.connection import ASGIConnection
16     from litestar.di import Provide
17     from litestar.types import ControllerRouterHandler, Guard, Scopes, SyncOrAsyncUnion, TypeEncodersMap
18 
19 
20 @dataclass
21 class SessionAuth(Generic[UserType, BaseSessionBackendT], AbstractSecurityConfig[UserType, Dict[str, Any]]):
22     """Session Based Security Backend."""
23 
24     session_backend_config: BaseBackendConfig[BaseSessionBackendT]
25     """A session backend config."""
26     retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]
27     """Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.
28 
29     Notes:
30         - User and Auth can be any arbitrary values specified by the security backend.
31         - The User and Auth values will be set by the middleware as ``scope["user"]`` and ``scope["auth"]`` respectively.
32           Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.
33         - The callable can be sync or async. If it is sync, it will be wrapped to support async.
34 
35     """
36 
37     authentication_middleware_class: type[SessionAuthMiddleware] = field(default=SessionAuthMiddleware)
38     """The authentication middleware class to use.
39 
40     Must inherit from :class:`SessionAuthMiddleware <litestar.security.session_auth.middleware.SessionAuthMiddleware>`
41     """
42 
43     guards: Iterable[Guard] | None = field(default=None)
44     """An iterable of guards to call for requests, providing authorization functionalities."""
45     exclude: str | list[str] | None = field(default=None)
46     """A pattern or list of patterns to skip in the authentication middleware."""
47     exclude_opt_key: str = field(default="exclude_from_auth")
48     """An identifier to use on routes to disable authentication and authorization checks for a particular route."""
49     scopes: Scopes | None = field(default=None)
50     """ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be
51     processed."""
52     route_handlers: Iterable[ControllerRouterHandler] | None = field(default=None)
53     """An optional iterable of route handlers to register."""
54     dependencies: dict[str, Provide] | None = field(default=None)
55     """An optional dictionary of dependency providers."""
56 
57     type_encoders: TypeEncodersMap | None = field(default=None)
58     """A mapping of types to callables that transform them into types supported for serialization."""
59 
60     @property
61     def middleware(self) -> DefineMiddleware:
62         """Use this property to insert the config into a middleware list on one of the application layers.
63 
64         Examples:
65             .. code-block: python
66 
67                 from typing import Any
68                 from os import urandom
69 
70                 from litestar import Litestar, Request, get
71                 from litestar_session import SessionAuth
72 
73 
74                 async def retrieve_user_from_session(session: dict[str, Any]) -> Any:
75                     # implement logic here to retrieve a ``user`` datum given the session dictionary
76                     ...
77 
78 
79                 session_auth_config = SessionAuth(
80                     secret=urandom(16), retrieve_user_handler=retrieve_user_from_session
81                 )
82 
83 
84                 @get("/")
85                 def my_handler(request: Request) -> None:
86                     ...
87 
88 
89                 app = Litestar(route_handlers=[my_handler], middleware=[session_auth_config.middleware])
90 
91 
92         Returns:
93             An instance of DefineMiddleware including ``self`` as the config kwarg value.
94         """
95         return DefineMiddleware(MiddlewareWrapper, config=self)
96 
97     @property
98     def session_backend(self) -> BaseSessionBackendT:
99         """Create a session backend.
100 
101         Returns:
102             A subclass of :class:`BaseSessionBackend <litestar.middleware.session.base.BaseSessionBackend>`
103         """
104         return self.session_backend_config._backend_class(config=self.session_backend_config)
105 
106     @property
107     def openapi_components(self) -> Components:
108         """Create OpenAPI documentation for the Session Authentication schema used.
109 
110         Returns:
111             An :class:`Components <litestar.openapi.spec.components.Components>` instance.
112         """
113         return Components(
114             security_schemes={
115                 "sessionCookie": SecurityScheme(
116                     type="apiKey",
117                     name=self.session_backend_config.key,
118                     security_scheme_in="cookie",  # pyright: ignore
119                     description="Session cookie authentication.",
120                 )
121             }
122         )
123 
124     @property
125     def security_requirement(self) -> SecurityRequirement:
126         """Return OpenAPI 3.1.
127 
128         :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for the auth
129         backend.
130 
131         Returns:
132             An OpenAPI 3.1 :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` dictionary.
133         """
134         return {"sessionCookie": []}
135
```

Path: `litestar/security/session_auth/middleware.py`
Content:
```
1 from __future__ import annotations
2 
3 from typing import TYPE_CHECKING, Any
4 
5 from litestar.exceptions import NotAuthorizedException
6 from litestar.middleware.authentication import (
7     AbstractAuthenticationMiddleware,
8     AuthenticationResult,
9 )
10 from litestar.middleware.exceptions import ExceptionHandlerMiddleware
11 from litestar.middleware.session.base import SessionMiddleware
12 from litestar.types import Empty, Scopes
13 
14 __all__ = ("MiddlewareWrapper", "SessionAuthMiddleware")
15 
16 
17 if TYPE_CHECKING:
18     from litestar.connection import ASGIConnection
19     from litestar.security.session_auth.auth import SessionAuth
20     from litestar.types import ASGIApp, Receive, Scope, Send
21     from litestar.utils import AsyncCallable
22 
23 
24 class MiddlewareWrapper:
25     """Wrapper class that serves as the middleware entry point."""
26 
27     def __init__(self, app: ASGIApp, config: SessionAuth[Any, Any]) -> None:
28         """Wrap the SessionAuthMiddleware inside ExceptionHandlerMiddleware, and it wraps this inside SessionMiddleware.
29         This allows the auth middleware to raise exceptions and still have the response handled, while having the
30         session cleared.
31 
32         Args:
33             app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
34             config: An instance of SessionAuth.
35         """
36         self.app = app
37         self.config = config
38         self.has_wrapped_middleware = False
39 
40     async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
41         """Handle creating a middleware stack and calling it.
42 
43         Args:
44             scope: The ASGI connection scope.
45             receive: The ASGI receive function.
46             send: The ASGI send function.
47 
48         Returns:
49             None
50         """
51         if not self.has_wrapped_middleware:
52             litestar_app = scope["app"]
53             auth_middleware = self.config.authentication_middleware_class(
54                 app=self.app,
55                 exclude=self.config.exclude,
56                 exclude_opt_key=self.config.exclude_opt_key,
57                 scopes=self.config.scopes,
58                 retrieve_user_handler=self.config.retrieve_user_handler,  # type: ignore
59             )
60             exception_middleware = ExceptionHandlerMiddleware(
61                 app=auth_middleware,
62                 exception_handlers=litestar_app.exception_handlers or {},  # pyright: ignore
63                 debug=litestar_app.debug,
64             )
65             self.app = SessionMiddleware(
66                 app=exception_middleware,
67                 backend=self.config.session_backend,
68             )
69             self.has_wrapped_middleware = True
70         await self.app(scope, receive, send)
71 
72 
73 class SessionAuthMiddleware(AbstractAuthenticationMiddleware):
74     """Session Authentication Middleware."""
75 
76     def __init__(
77         self,
78         app: ASGIApp,
79         exclude: str | list[str] | None,
80         exclude_opt_key: str,
81         scopes: Scopes | None,
82         retrieve_user_handler: AsyncCallable[[dict[str, Any], ASGIConnection[Any, Any, Any, Any]], Any],
83     ) -> None:
84         """Session based authentication middleware.
85 
86         Args:
87             app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
88             exclude: A pattern or list of patterns to skip in the authentication middleware.
89             exclude_opt_key: An identifier to use on routes to disable authentication and authorization checks for a particular route.
90             scopes: ASGI scopes processed by the authentication middleware.
91             retrieve_user_handler: Callable that receives the ``session`` value from the authentication middleware and returns a ``user`` value.
92         """
93         super().__init__(app=app, exclude=exclude, exclude_from_auth_key=exclude_opt_key, scopes=scopes)
94         self.retrieve_user_handler = retrieve_user_handler
95 
96     async def authenticate_request(self, connection: ASGIConnection[Any, Any, Any, Any]) -> AuthenticationResult:
97         """Authenticate an incoming connection.
98 
99         Args:
100             connection: An :class:`ASGIConnection <.connection.ASGIConnection>` instance.
101 
102         Raises:
103             NotAuthorizedException: if session data is empty or user is not found.
104 
105         Returns:
106             :class:`AuthenticationResult <.middleware.authentication.AuthenticationResult>`
107         """
108         if not connection.session or connection.session is Empty:
109             # the assignment of 'Empty' forces the session middleware to clear session data.
110             connection.scope["session"] = Empty
111             raise NotAuthorizedException("no session data found")
112 
113         user = await self.retrieve_user_handler(connection.session, connection)
114 
115         if not user:
116             connection.scope["session"] = Empty
117             raise NotAuthorizedException("no user correlating to session found")
118 
119         return AuthenticationResult(user=user, auth=connection.session)
120
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/litestar/security/session_auth/auth.py b/litestar/security/session_auth/auth.py
--- a/litestar/security/session_auth/auth.py
+++ b/litestar/security/session_auth/auth.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 
 from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterable
+from typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterable, Sequence, cast
 
 from litestar.middleware.base import DefineMiddleware
 from litestar.middleware.session.base import BaseBackendConfig, BaseSessionBackendT
@@ -14,7 +14,7 @@
 if TYPE_CHECKING:
     from litestar.connection import ASGIConnection
     from litestar.di import Provide
-    from litestar.types import ControllerRouterHandler, Guard, Scopes, SyncOrAsyncUnion, TypeEncodersMap
+    from litestar.types import ControllerRouterHandler, Guard, Method, Scopes, SyncOrAsyncUnion, TypeEncodersMap
 
 
 @dataclass
@@ -46,6 +46,10 @@
     """A pattern or list of patterns to skip in the authentication middleware."""
     exclude_opt_key: str = field(default="exclude_from_auth")
     """An identifier to use on routes to disable authentication and authorization checks for a particular route."""
+    exclude_http_methods: Sequence[Method] | None = field(
+        default_factory=lambda: cast("Sequence[Method]", ["OPTIONS", "HEAD"])
+    )
+    """A sequence of http methods that do not require authentication. Defaults to ['OPTIONS', 'HEAD']"""
     scopes: Scopes | None = field(default=None)
     """ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be
     processed."""
diff --git a/litestar/security/session_auth/middleware.py b/litestar/security/session_auth/middleware.py
--- a/litestar/security/session_auth/middleware.py
+++ b/litestar/security/session_auth/middleware.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, Any
+from typing import TYPE_CHECKING, Any, Sequence
 
 from litestar.exceptions import NotAuthorizedException
 from litestar.middleware.authentication import (
@@ -9,11 +9,10 @@
 )
 from litestar.middleware.exceptions import ExceptionHandlerMiddleware
 from litestar.middleware.session.base import SessionMiddleware
-from litestar.types import Empty, Scopes
+from litestar.types import Empty, Method, Scopes
 
 __all__ = ("MiddlewareWrapper", "SessionAuthMiddleware")
 
-
 if TYPE_CHECKING:
     from litestar.connection import ASGIConnection
     from litestar.security.session_auth.auth import SessionAuth
@@ -53,6 +52,7 @@
             auth_middleware = self.config.authentication_middleware_class(
                 app=self.app,
                 exclude=self.config.exclude,
+                exclude_http_methods=self.config.exclude_http_methods,
                 exclude_opt_key=self.config.exclude_opt_key,
                 scopes=self.config.scopes,
                 retrieve_user_handler=self.config.retrieve_user_handler,  # type: ignore
@@ -77,20 +77,28 @@
         self,
         app: ASGIApp,
         exclude: str | list[str] | None,
+        exclude_http_methods: Sequence[Method] | None,
         exclude_opt_key: str,
-        scopes: Scopes | None,
         retrieve_user_handler: AsyncCallable[[dict[str, Any], ASGIConnection[Any, Any, Any, Any]], Any],
+        scopes: Scopes | None,
     ) -> None:
         """Session based authentication middleware.
 
         Args:
             app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
             exclude: A pattern or list of patterns to skip in the authentication middleware.
+            exclude_http_methods: A sequence of http methods that do not require authentication.
             exclude_opt_key: An identifier to use on routes to disable authentication and authorization checks for a particular route.
             scopes: ASGI scopes processed by the authentication middleware.
             retrieve_user_handler: Callable that receives the ``session`` value from the authentication middleware and returns a ``user`` value.
         """
-        super().__init__(app=app, exclude=exclude, exclude_from_auth_key=exclude_opt_key, scopes=scopes)
+        super().__init__(
+            app=app,
+            exclude=exclude,
+            exclude_from_auth_key=exclude_opt_key,
+            exclude_http_methods=exclude_http_methods,
+            scopes=scopes,
+        )
         self.retrieve_user_handler = retrieve_user_handler
 
     async def authenticate_request(self, connection: ASGIConnection[Any, Any, Any, Any]) -> AuthenticationResult:

{"golden_diff": "diff --git a/litestar/security/session_auth/auth.py b/litestar/security/session_auth/auth.py\n--- a/litestar/security/session_auth/auth.py\n+++ b/litestar/security/session_auth/auth.py\n@@ -1,7 +1,7 @@\n from __future__ import annotations\n \n from dataclasses import dataclass, field\n-from typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterable\n+from typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterable, Sequence, cast\n \n from litestar.middleware.base import DefineMiddleware\n from litestar.middleware.session.base import BaseBackendConfig, BaseSessionBackendT\n@@ -14,7 +14,7 @@\n if TYPE_CHECKING:\n     from litestar.connection import ASGIConnection\n     from litestar.di import Provide\n-    from litestar.types import ControllerRouterHandler, Guard, Scopes, SyncOrAsyncUnion, TypeEncodersMap\n+    from litestar.types import ControllerRouterHandler, Guard, Method, Scopes, SyncOrAsyncUnion, TypeEncodersMap\n \n \n @dataclass\n@@ -46,6 +46,10 @@\n     \"\"\"A pattern or list of patterns to skip in the authentication middleware.\"\"\"\n     exclude_opt_key: str = field(default=\"exclude_from_auth\")\n     \"\"\"An identifier to use on routes to disable authentication and authorization checks for a particular route.\"\"\"\n+    exclude_http_methods: Sequence[Method] | None = field(\n+        default_factory=lambda: cast(\"Sequence[Method]\", [\"OPTIONS\", \"HEAD\"])\n+    )\n+    \"\"\"A sequence of http methods that do not require authentication. Defaults to ['OPTIONS', 'HEAD']\"\"\"\n     scopes: Scopes | None = field(default=None)\n     \"\"\"ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be\n     processed.\"\"\"\ndiff --git a/litestar/security/session_auth/middleware.py b/litestar/security/session_auth/middleware.py\n--- a/litestar/security/session_auth/middleware.py\n+++ b/litestar/security/session_auth/middleware.py\n@@ -1,6 +1,6 @@\n from __future__ import annotations\n \n-from typing import TYPE_CHECKING, Any\n+from typing import TYPE_CHECKING, Any, Sequence\n \n from litestar.exceptions import NotAuthorizedException\n from litestar.middleware.authentication import (\n@@ -9,11 +9,10 @@\n )\n from litestar.middleware.exceptions import ExceptionHandlerMiddleware\n from litestar.middleware.session.base import SessionMiddleware\n-from litestar.types import Empty, Scopes\n+from litestar.types import Empty, Method, Scopes\n \n __all__ = (\"MiddlewareWrapper\", \"SessionAuthMiddleware\")\n \n-\n if TYPE_CHECKING:\n     from litestar.connection import ASGIConnection\n     from litestar.security.session_auth.auth import SessionAuth\n@@ -53,6 +52,7 @@\n             auth_middleware = self.config.authentication_middleware_class(\n                 app=self.app,\n                 exclude=self.config.exclude,\n+                exclude_http_methods=self.config.exclude_http_methods,\n                 exclude_opt_key=self.config.exclude_opt_key,\n                 scopes=self.config.scopes,\n                 retrieve_user_handler=self.config.retrieve_user_handler,  # type: ignore\n@@ -77,20 +77,28 @@\n         self,\n         app: ASGIApp,\n         exclude: str | list[str] | None,\n+        exclude_http_methods: Sequence[Method] | None,\n         exclude_opt_key: str,\n-        scopes: Scopes | None,\n         retrieve_user_handler: AsyncCallable[[dict[str, Any], ASGIConnection[Any, Any, Any, Any]], Any],\n+        scopes: Scopes | None,\n     ) -> None:\n         \"\"\"Session based authentication middleware.\n \n         Args:\n             app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.\n             exclude: A pattern or list of patterns to skip in the authentication middleware.\n+            exclude_http_methods: A sequence of http methods that do not require authentication.\n             exclude_opt_key: An identifier to use on routes to disable authentication and authorization checks for a particular route.\n             scopes: ASGI scopes processed by the authentication middleware.\n             retrieve_user_handler: Callable that receives the ``session`` value from the authentication middleware and returns a ``user`` value.\n         \"\"\"\n-        super().__init__(app=app, exclude=exclude, exclude_from_auth_key=exclude_opt_key, scopes=scopes)\n+        super().__init__(\n+            app=app,\n+            exclude=exclude,\n+            exclude_from_auth_key=exclude_opt_key,\n+            exclude_http_methods=exclude_http_methods,\n+            scopes=scopes,\n+        )\n         self.retrieve_user_handler = retrieve_user_handler\n \n     async def authenticate_request(self, connection: ASGIConnection[Any, Any, Any, Any]) -> AuthenticationResult:\n", "issue": "Bug: regression v2.0.0beta4 -> main@HEAD\n### Description\n\nThere appears to be a regression between tag v2.0.0beta4 and the current (2.0.0rc1 PyPi release) (or if you prefer, also commit d257d099993179f1133a96441bf816e1de435007, which is the latest commit on main. This seems very likely related to #2160  which my guess would be only fixed the problem for JWT, not the SessionAuth middleware that I am using.\n\n### URL to code causing the issue\n\nhttps://github.com/Mattwmaster58/MacTrack/tree/broken-auth\n\n### MCVE\n\n```python\n(working on this)\n```\n\n\n### Steps to reproduce\n\n```bash\n1. Clone repo, checkout `broken-auth` branch, poetry install, run, request to OPTIONS endpoint, observe:\r\n\r\n`INFO:     127.0.0.1:55754 - \"OPTIONS /api/filters/create HTTP/1.1\" 401 Unauthorized`\n```\n\n\n### Screenshots\n\n_No response_\n\n### Logs\n\n```bash\nERROR - 2023-08-19 18:27:03,266908605 - litestar - middleware - exception raised on http connection to route /api/filters/create\r\n\r\nTraceback (most recent call last):\r\n  File \"/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py\", line 191, in __call__\r\n    await self.app(scope, receive, send)\r\n  File \"/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/middleware/authentication.py\", line 87, in __call__\r\n    auth_result = await self.authenticate_request(ASGIConnection(scope))\r\n                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n  File \"/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/security/session_auth/middleware.py\", line 111, in authenticate_request\r\n    raise NotAuthorizedException(\"no session data found\")\r\nlitestar.exceptions.http_exceptions.NotAuthorizedException: 401: no session data found\r\nTraceback (most recent call last):\r\n  File \"/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py\", line 191, in __call__\r\n    await self.app(scope, receive, send)\r\n  File \"/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/middleware/authentication.py\", line 87, in __call__\r\n    auth_result = await self.authenticate_request(ASGIConnection(scope))\r\n                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n  File \"/home/user/Documents/projects/mac-track/api/.venv/lib/python3.11/site-packages/litestar/security/session_auth/middleware.py\", line 111, in authenticate_request\r\n    raise NotAuthorizedException(\"no session data found\")\r\nlitestar.exceptions.http_exceptions.NotAuthorizedException: 401: no session data found\r\nINFO:     127.0.0.1:55754 - \"OPTIONS /api/filters/create HTTP/1.1\" 401 Unauthorized\n```\n\n\n### Litestar Version\n\n2.0.0rc1 as well as d257d099993179f1133a96441bf816e1de435007\n\n### Platform\n\n- [X] Linux\n- [ ] Mac\n- [ ] Windows\n- [ ] Other (Please specify in the description above)\n\n<!-- POLAR PLEDGE BADGE START -->\n---\n\n## Funding\n* If you would like to see an issue prioritized, make a pledge towards it!\n* We receive the pledge once the issue is completed & verified\n\n<a href=\"https://polar.sh/litestar-org/litestar/issues/2181\">\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://polar.sh/api/github/litestar-org/litestar/issues/2181/pledge.svg?darkmode=1\">\n  <img alt=\"Fund with Polar\" src=\"https://polar.sh/api/github/litestar-org/litestar/issues/2181/pledge.svg\">\n</picture>\n</a>\n<!-- POLAR PLEDGE BADGE END -->\n\nStaticFilesConfig and virtual directories\nI'm trying to write a ``FileSystemProtocol`` to load files from the package data using [importlib_resources](https://importlib-resources.readthedocs.io/en/latest/using.html#). But because ``directories`` is defined as ``DirectoryPath``, pydantic checks if the given directories exist in the local filesystem. \r\n\r\nThis is not generally true, especially in any kind of virtual filesystem (e.g. a zipped package). I think this condition should be relaxed to support virtual filesystems.\r\n\r\nhttps://github.com/starlite-api/starlite/blob/9bb6dcd57c10a591377cf8e3a537e9292566d5b9/starlite/config/static_files.py#L32\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom dataclasses import dataclass, field\nfrom typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterable\n\nfrom litestar.middleware.base import DefineMiddleware\nfrom litestar.middleware.session.base import BaseBackendConfig, BaseSessionBackendT\nfrom litestar.openapi.spec import Components, SecurityRequirement, SecurityScheme\nfrom litestar.security.base import AbstractSecurityConfig, UserType\nfrom litestar.security.session_auth.middleware import MiddlewareWrapper, SessionAuthMiddleware\n\n__all__ = (\"SessionAuth\",)\n\nif TYPE_CHECKING:\n    from litestar.connection import ASGIConnection\n    from litestar.di import Provide\n    from litestar.types import ControllerRouterHandler, Guard, Scopes, SyncOrAsyncUnion, TypeEncodersMap\n\n\n@dataclass\nclass SessionAuth(Generic[UserType, BaseSessionBackendT], AbstractSecurityConfig[UserType, Dict[str, Any]]):\n    \"\"\"Session Based Security Backend.\"\"\"\n\n    session_backend_config: BaseBackendConfig[BaseSessionBackendT]\n    \"\"\"A session backend config.\"\"\"\n    retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]\n    \"\"\"Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.\n\n    Notes:\n        - User and Auth can be any arbitrary values specified by the security backend.\n        - The User and Auth values will be set by the middleware as ``scope[\"user\"]`` and ``scope[\"auth\"]`` respectively.\n          Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.\n        - The callable can be sync or async. If it is sync, it will be wrapped to support async.\n\n    \"\"\"\n\n    authentication_middleware_class: type[SessionAuthMiddleware] = field(default=SessionAuthMiddleware)\n    \"\"\"The authentication middleware class to use.\n\n    Must inherit from :class:`SessionAuthMiddleware <litestar.security.session_auth.middleware.SessionAuthMiddleware>`\n    \"\"\"\n\n    guards: Iterable[Guard] | None = field(default=None)\n    \"\"\"An iterable of guards to call for requests, providing authorization functionalities.\"\"\"\n    exclude: str | list[str] | None = field(default=None)\n    \"\"\"A pattern or list of patterns to skip in the authentication middleware.\"\"\"\n    exclude_opt_key: str = field(default=\"exclude_from_auth\")\n    \"\"\"An identifier to use on routes to disable authentication and authorization checks for a particular route.\"\"\"\n    scopes: Scopes | None = field(default=None)\n    \"\"\"ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be\n    processed.\"\"\"\n    route_handlers: Iterable[ControllerRouterHandler] | None = field(default=None)\n    \"\"\"An optional iterable of route handlers to register.\"\"\"\n    dependencies: dict[str, Provide] | None = field(default=None)\n    \"\"\"An optional dictionary of dependency providers.\"\"\"\n\n    type_encoders: TypeEncodersMap | None = field(default=None)\n    \"\"\"A mapping of types to callables that transform them into types supported for serialization.\"\"\"\n\n    @property\n    def middleware(self) -> DefineMiddleware:\n        \"\"\"Use this property to insert the config into a middleware list on one of the application layers.\n\n        Examples:\n            .. code-block: python\n\n                from typing import Any\n                from os import urandom\n\n                from litestar import Litestar, Request, get\n                from litestar_session import SessionAuth\n\n\n                async def retrieve_user_from_session(session: dict[str, Any]) -> Any:\n                    # implement logic here to retrieve a ``user`` datum given the session dictionary\n                    ...\n\n\n                session_auth_config = SessionAuth(\n                    secret=urandom(16), retrieve_user_handler=retrieve_user_from_session\n                )\n\n\n                @get(\"/\")\n                def my_handler(request: Request) -> None:\n                    ...\n\n\n                app = Litestar(route_handlers=[my_handler], middleware=[session_auth_config.middleware])\n\n\n        Returns:\n            An instance of DefineMiddleware including ``self`` as the config kwarg value.\n        \"\"\"\n        return DefineMiddleware(MiddlewareWrapper, config=self)\n\n    @property\n    def session_backend(self) -> BaseSessionBackendT:\n        \"\"\"Create a session backend.\n\n        Returns:\n            A subclass of :class:`BaseSessionBackend <litestar.middleware.session.base.BaseSessionBackend>`\n        \"\"\"\n        return self.session_backend_config._backend_class(config=self.session_backend_config)\n\n    @property\n    def openapi_components(self) -> Components:\n        \"\"\"Create OpenAPI documentation for the Session Authentication schema used.\n\n        Returns:\n            An :class:`Components <litestar.openapi.spec.components.Components>` instance.\n        \"\"\"\n        return Components(\n            security_schemes={\n                \"sessionCookie\": SecurityScheme(\n                    type=\"apiKey\",\n                    name=self.session_backend_config.key,\n                    security_scheme_in=\"cookie\",  # pyright: ignore\n                    description=\"Session cookie authentication.\",\n                )\n            }\n        )\n\n    @property\n    def security_requirement(self) -> SecurityRequirement:\n        \"\"\"Return OpenAPI 3.1.\n\n        :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for the auth\n        backend.\n\n        Returns:\n            An OpenAPI 3.1 :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` dictionary.\n        \"\"\"\n        return {\"sessionCookie\": []}\n", "path": "litestar/security/session_auth/auth.py"}, {"content": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Any\n\nfrom litestar.exceptions import NotAuthorizedException\nfrom litestar.middleware.authentication import (\n    AbstractAuthenticationMiddleware,\n    AuthenticationResult,\n)\nfrom litestar.middleware.exceptions import ExceptionHandlerMiddleware\nfrom litestar.middleware.session.base import SessionMiddleware\nfrom litestar.types import Empty, Scopes\n\n__all__ = (\"MiddlewareWrapper\", \"SessionAuthMiddleware\")\n\n\nif TYPE_CHECKING:\n    from litestar.connection import ASGIConnection\n    from litestar.security.session_auth.auth import SessionAuth\n    from litestar.types import ASGIApp, Receive, Scope, Send\n    from litestar.utils import AsyncCallable\n\n\nclass MiddlewareWrapper:\n    \"\"\"Wrapper class that serves as the middleware entry point.\"\"\"\n\n    def __init__(self, app: ASGIApp, config: SessionAuth[Any, Any]) -> None:\n        \"\"\"Wrap the SessionAuthMiddleware inside ExceptionHandlerMiddleware, and it wraps this inside SessionMiddleware.\n        This allows the auth middleware to raise exceptions and still have the response handled, while having the\n        session cleared.\n\n        Args:\n            app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.\n            config: An instance of SessionAuth.\n        \"\"\"\n        self.app = app\n        self.config = config\n        self.has_wrapped_middleware = False\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        \"\"\"Handle creating a middleware stack and calling it.\n\n        Args:\n            scope: The ASGI connection scope.\n            receive: The ASGI receive function.\n            send: The ASGI send function.\n\n        Returns:\n            None\n        \"\"\"\n        if not self.has_wrapped_middleware:\n            litestar_app = scope[\"app\"]\n            auth_middleware = self.config.authentication_middleware_class(\n                app=self.app,\n                exclude=self.config.exclude,\n                exclude_opt_key=self.config.exclude_opt_key,\n                scopes=self.config.scopes,\n                retrieve_user_handler=self.config.retrieve_user_handler,  # type: ignore\n            )\n            exception_middleware = ExceptionHandlerMiddleware(\n                app=auth_middleware,\n                exception_handlers=litestar_app.exception_handlers or {},  # pyright: ignore\n                debug=litestar_app.debug,\n            )\n            self.app = SessionMiddleware(\n                app=exception_middleware,\n                backend=self.config.session_backend,\n            )\n            self.has_wrapped_middleware = True\n        await self.app(scope, receive, send)\n\n\nclass SessionAuthMiddleware(AbstractAuthenticationMiddleware):\n    \"\"\"Session Authentication Middleware.\"\"\"\n\n    def __init__(\n        self,\n        app: ASGIApp,\n        exclude: str | list[str] | None,\n        exclude_opt_key: str,\n        scopes: Scopes | None,\n        retrieve_user_handler: AsyncCallable[[dict[str, Any], ASGIConnection[Any, Any, Any, Any]], Any],\n    ) -> None:\n        \"\"\"Session based authentication middleware.\n\n        Args:\n            app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.\n            exclude: A pattern or list of patterns to skip in the authentication middleware.\n            exclude_opt_key: An identifier to use on routes to disable authentication and authorization checks for a particular route.\n            scopes: ASGI scopes processed by the authentication middleware.\n            retrieve_user_handler: Callable that receives the ``session`` value from the authentication middleware and returns a ``user`` value.\n        \"\"\"\n        super().__init__(app=app, exclude=exclude, exclude_from_auth_key=exclude_opt_key, scopes=scopes)\n        self.retrieve_user_handler = retrieve_user_handler\n\n    async def authenticate_request(self, connection: ASGIConnection[Any, Any, Any, Any]) -> AuthenticationResult:\n        \"\"\"Authenticate an incoming connection.\n\n        Args:\n            connection: An :class:`ASGIConnection <.connection.ASGIConnection>` instance.\n\n        Raises:\n            NotAuthorizedException: if session data is empty or user is not found.\n\n        Returns:\n            :class:`AuthenticationResult <.middleware.authentication.AuthenticationResult>`\n        \"\"\"\n        if not connection.session or connection.session is Empty:\n            # the assignment of 'Empty' forces the session middleware to clear session data.\n            connection.scope[\"session\"] = Empty\n            raise NotAuthorizedException(\"no session data found\")\n\n        user = await self.retrieve_user_handler(connection.session, connection)\n\n        if not user:\n            connection.scope[\"session\"] = Empty\n            raise NotAuthorizedException(\"no user correlating to session found\")\n\n        return AuthenticationResult(user=user, auth=connection.session)\n", "path": "litestar/security/session_auth/middleware.py"}], "after_files": [{"content": "from __future__ import annotations\n\nfrom dataclasses import dataclass, field\nfrom typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterable, Sequence, cast\n\nfrom litestar.middleware.base import DefineMiddleware\nfrom litestar.middleware.session.base import BaseBackendConfig, BaseSessionBackendT\nfrom litestar.openapi.spec import Components, SecurityRequirement, SecurityScheme\nfrom litestar.security.base import AbstractSecurityConfig, UserType\nfrom litestar.security.session_auth.middleware import MiddlewareWrapper, SessionAuthMiddleware\n\n__all__ = (\"SessionAuth\",)\n\nif TYPE_CHECKING:\n    from litestar.connection import ASGIConnection\n    from litestar.di import Provide\n    from litestar.types import ControllerRouterHandler, Guard, Method, Scopes, SyncOrAsyncUnion, TypeEncodersMap\n\n\n@dataclass\nclass SessionAuth(Generic[UserType, BaseSessionBackendT], AbstractSecurityConfig[UserType, Dict[str, Any]]):\n    \"\"\"Session Based Security Backend.\"\"\"\n\n    session_backend_config: BaseBackendConfig[BaseSessionBackendT]\n    \"\"\"A session backend config.\"\"\"\n    retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]\n    \"\"\"Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.\n\n    Notes:\n        - User and Auth can be any arbitrary values specified by the security backend.\n        - The User and Auth values will be set by the middleware as ``scope[\"user\"]`` and ``scope[\"auth\"]`` respectively.\n          Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.\n        - The callable can be sync or async. If it is sync, it will be wrapped to support async.\n\n    \"\"\"\n\n    authentication_middleware_class: type[SessionAuthMiddleware] = field(default=SessionAuthMiddleware)\n    \"\"\"The authentication middleware class to use.\n\n    Must inherit from :class:`SessionAuthMiddleware <litestar.security.session_auth.middleware.SessionAuthMiddleware>`\n    \"\"\"\n\n    guards: Iterable[Guard] | None = field(default=None)\n    \"\"\"An iterable of guards to call for requests, providing authorization functionalities.\"\"\"\n    exclude: str | list[str] | None = field(default=None)\n    \"\"\"A pattern or list of patterns to skip in the authentication middleware.\"\"\"\n    exclude_opt_key: str = field(default=\"exclude_from_auth\")\n    \"\"\"An identifier to use on routes to disable authentication and authorization checks for a particular route.\"\"\"\n    exclude_http_methods: Sequence[Method] | None = field(\n        default_factory=lambda: cast(\"Sequence[Method]\", [\"OPTIONS\", \"HEAD\"])\n    )\n    \"\"\"A sequence of http methods that do not require authentication. Defaults to ['OPTIONS', 'HEAD']\"\"\"\n    scopes: Scopes | None = field(default=None)\n    \"\"\"ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be\n    processed.\"\"\"\n    route_handlers: Iterable[ControllerRouterHandler] | None = field(default=None)\n    \"\"\"An optional iterable of route handlers to register.\"\"\"\n    dependencies: dict[str, Provide] | None = field(default=None)\n    \"\"\"An optional dictionary of dependency providers.\"\"\"\n\n    type_encoders: TypeEncodersMap | None = field(default=None)\n    \"\"\"A mapping of types to callables that transform them into types supported for serialization.\"\"\"\n\n    @property\n    def middleware(self) -> DefineMiddleware:\n        \"\"\"Use this property to insert the config into a middleware list on one of the application layers.\n\n        Examples:\n            .. code-block: python\n\n                from typing import Any\n                from os import urandom\n\n                from litestar import Litestar, Request, get\n                from litestar_session import SessionAuth\n\n\n                async def retrieve_user_from_session(session: dict[str, Any]) -> Any:\n                    # implement logic here to retrieve a ``user`` datum given the session dictionary\n                    ...\n\n\n                session_auth_config = SessionAuth(\n                    secret=urandom(16), retrieve_user_handler=retrieve_user_from_session\n                )\n\n\n                @get(\"/\")\n                def my_handler(request: Request) -> None:\n                    ...\n\n\n                app = Litestar(route_handlers=[my_handler], middleware=[session_auth_config.middleware])\n\n\n        Returns:\n            An instance of DefineMiddleware including ``self`` as the config kwarg value.\n        \"\"\"\n        return DefineMiddleware(MiddlewareWrapper, config=self)\n\n    @property\n    def session_backend(self) -> BaseSessionBackendT:\n        \"\"\"Create a session backend.\n\n        Returns:\n            A subclass of :class:`BaseSessionBackend <litestar.middleware.session.base.BaseSessionBackend>`\n        \"\"\"\n        return self.session_backend_config._backend_class(config=self.session_backend_config)\n\n    @property\n    def openapi_components(self) -> Components:\n        \"\"\"Create OpenAPI documentation for the Session Authentication schema used.\n\n        Returns:\n            An :class:`Components <litestar.openapi.spec.components.Components>` instance.\n        \"\"\"\n        return Components(\n            security_schemes={\n                \"sessionCookie\": SecurityScheme(\n                    type=\"apiKey\",\n                    name=self.session_backend_config.key,\n                    security_scheme_in=\"cookie\",  # pyright: ignore\n                    description=\"Session cookie authentication.\",\n                )\n            }\n        )\n\n    @property\n    def security_requirement(self) -> SecurityRequirement:\n        \"\"\"Return OpenAPI 3.1.\n\n        :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for the auth\n        backend.\n\n        Returns:\n            An OpenAPI 3.1 :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` dictionary.\n        \"\"\"\n        return {\"sessionCookie\": []}\n", "path": "litestar/security/session_auth/auth.py"}, {"content": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Any, Sequence\n\nfrom litestar.exceptions import NotAuthorizedException\nfrom litestar.middleware.authentication import (\n    AbstractAuthenticationMiddleware,\n    AuthenticationResult,\n)\nfrom litestar.middleware.exceptions import ExceptionHandlerMiddleware\nfrom litestar.middleware.session.base import SessionMiddleware\nfrom litestar.types import Empty, Method, Scopes\n\n__all__ = (\"MiddlewareWrapper\", \"SessionAuthMiddleware\")\n\nif TYPE_CHECKING:\n    from litestar.connection import ASGIConnection\n    from litestar.security.session_auth.auth import SessionAuth\n    from litestar.types import ASGIApp, Receive, Scope, Send\n    from litestar.utils import AsyncCallable\n\n\nclass MiddlewareWrapper:\n    \"\"\"Wrapper class that serves as the middleware entry point.\"\"\"\n\n    def __init__(self, app: ASGIApp, config: SessionAuth[Any, Any]) -> None:\n        \"\"\"Wrap the SessionAuthMiddleware inside ExceptionHandlerMiddleware, and it wraps this inside SessionMiddleware.\n        This allows the auth middleware to raise exceptions and still have the response handled, while having the\n        session cleared.\n\n        Args:\n            app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.\n            config: An instance of SessionAuth.\n        \"\"\"\n        self.app = app\n        self.config = config\n        self.has_wrapped_middleware = False\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        \"\"\"Handle creating a middleware stack and calling it.\n\n        Args:\n            scope: The ASGI connection scope.\n            receive: The ASGI receive function.\n            send: The ASGI send function.\n\n        Returns:\n            None\n        \"\"\"\n        if not self.has_wrapped_middleware:\n            litestar_app = scope[\"app\"]\n            auth_middleware = self.config.authentication_middleware_class(\n                app=self.app,\n                exclude=self.config.exclude,\n                exclude_http_methods=self.config.exclude_http_methods,\n                exclude_opt_key=self.config.exclude_opt_key,\n                scopes=self.config.scopes,\n                retrieve_user_handler=self.config.retrieve_user_handler,  # type: ignore\n            )\n            exception_middleware = ExceptionHandlerMiddleware(\n                app=auth_middleware,\n                exception_handlers=litestar_app.exception_handlers or {},  # pyright: ignore\n                debug=litestar_app.debug,\n            )\n            self.app = SessionMiddleware(\n                app=exception_middleware,\n                backend=self.config.session_backend,\n            )\n            self.has_wrapped_middleware = True\n        await self.app(scope, receive, send)\n\n\nclass SessionAuthMiddleware(AbstractAuthenticationMiddleware):\n    \"\"\"Session Authentication Middleware.\"\"\"\n\n    def __init__(\n        self,\n        app: ASGIApp,\n        exclude: str | list[str] | None,\n        exclude_http_methods: Sequence[Method] | None,\n        exclude_opt_key: str,\n        retrieve_user_handler: AsyncCallable[[dict[str, Any], ASGIConnection[Any, Any, Any, Any]], Any],\n        scopes: Scopes | None,\n    ) -> None:\n        \"\"\"Session based authentication middleware.\n\n        Args:\n            app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.\n            exclude: A pattern or list of patterns to skip in the authentication middleware.\n            exclude_http_methods: A sequence of http methods that do not require authentication.\n            exclude_opt_key: An identifier to use on routes to disable authentication and authorization checks for a particular route.\n            scopes: ASGI scopes processed by the authentication middleware.\n            retrieve_user_handler: Callable that receives the ``session`` value from the authentication middleware and returns a ``user`` value.\n        \"\"\"\n        super().__init__(\n            app=app,\n            exclude=exclude,\n            exclude_from_auth_key=exclude_opt_key,\n            exclude_http_methods=exclude_http_methods,\n            scopes=scopes,\n        )\n        self.retrieve_user_handler = retrieve_user_handler\n\n    async def authenticate_request(self, connection: ASGIConnection[Any, Any, Any, Any]) -> AuthenticationResult:\n        \"\"\"Authenticate an incoming connection.\n\n        Args:\n            connection: An :class:`ASGIConnection <.connection.ASGIConnection>` instance.\n\n        Raises:\n            NotAuthorizedException: if session data is empty or user is not found.\n\n        Returns:\n            :class:`AuthenticationResult <.middleware.authentication.AuthenticationResult>`\n        \"\"\"\n        if not connection.session or connection.session is Empty:\n            # the assignment of 'Empty' forces the session middleware to clear session data.\n            connection.scope[\"session\"] = Empty\n            raise NotAuthorizedException(\"no session data found\")\n\n        user = await self.retrieve_user_handler(connection.session, connection)\n\n        if not user:\n            connection.scope[\"session\"] = Empty\n            raise NotAuthorizedException(\"no user correlating to session found\")\n\n        return AuthenticationResult(user=user, auth=connection.session)\n", "path": "litestar/security/session_auth/middleware.py"}]}