Repository: ag2ai/faststream (Python)

Issue:
Bug: confluent.KafkaRouter with SASLScram512 fails in version 0.5.36
**Describe the bug**
From https://discord.com/channels/1085457301214855171/1085457302280228898/1352183480049729566:

After updating to version faststream==0.5.36, we’re experiencing an issue with confluent.fastapi.KafkaRouter on startup. Our dependencies: faststream==0.5.36, confluent-kafka==2.8.0.

We rolled back to version 0.5.35, and the issue disappeared.

**How to reproduce**
Include source code:

```python
security = SASLScram512(
    username=KAFKA_SETTINGS.kafka_auth_user,
    password=KAFKA_SETTINGS.kafka_auth_password,
    use_ssl=False,
)
router = KafkaRouter(
    KAFKA_SETTINGS.kafka_instance,
    security=security,
)
```

**Observed behavior**
```txt
File "/usr/local/lib/python3.8/site-packages/faststream/broker/fastapi/router.py", line 324, in start_broker_lifespan
    await self.broker.start()
File "/usr/local/lib/python3.8/site-packages/faststream/confluent/broker/broker.py", line 456, in start
    await super().start()
File "/usr/local/lib/python3.8/site-packages/faststream/broker/core/usecase.py", line 219, in start
    await self.connect()
File "/usr/local/lib/python3.8/site-packages/faststream/confluent/broker/broker.py", line 423, in connect
    return await super().connect(**kwargs)
File "/usr/local/lib/python3.8/site-packages/faststream/broker/core/usecase.py", line 226, in connect
    self._connection = await self._connect(**connection_kwargs)
File "/usr/local/lib/python3.8/site-packages/faststream/confluent/broker/broker.py", line 435, in _connect
    native_producer = AsyncConfluentProducer(
File "/usr/local/lib/python3.8/site-packages/faststream/confluent/client.py", line 109, in __init__
    self.producer = Producer(final_config, logger=self.logger) # type: ignore[call-arg]
cimpl.KafkaException: KafkaError{code=_INVALID_ARG,val=-186,str="No such configuration property: "sasl_mechanism""}
```

**Environment**
Our dependencies: faststream==0.5.36, confluent-kafka==2.8.0.




Discussion:

Patch:
diff --git a/faststream/__about__.py b/faststream/__about__.py
index a0fb071195..4e07cf7682 100644
--- a/faststream/__about__.py
+++ b/faststream/__about__.py
@@ -1,5 +1,5 @@
 """Simple and fast framework to create message brokers based microservices."""
 
-__version__ = "0.5.36"
+__version__ = "0.5.37"
 
 SERVICE_NAME = f"faststream-{__version__}"
diff --git a/faststream/confluent/schemas/params.py b/faststream/confluent/schemas/params.py
index e24a6ad4b8..cdde520f3d 100644
--- a/faststream/confluent/schemas/params.py
+++ b/faststream/confluent/schemas/params.py
@@ -2,19 +2,23 @@
 
 from typing_extensions import Required, TypedDict
 
-
-class SecurityOptions(TypedDict, total=False):
-    sasl_mechanism: Required[
-        Literal[
-            "PLAIN",
-            "GSSAPI",
-            "SCRAM-SHA-256",
-            "SCRAM-SHA-512",
-            "OAUTHBEARER",
-        ]
-    ]
-    sasl_plain_password: str
-    sasl_plain_username: str
+SecurityOptions = TypedDict(
+    "SecurityOptions",
+    {
+        "sasl.mechanism": Required[
+            Literal[
+                "PLAIN",
+                "GSSAPI",
+                "SCRAM-SHA-256",
+                "SCRAM-SHA-512",
+                "OAUTHBEARER",
+            ]
+        ],
+        "sasl.password": str,
+        "sasl.username": str,
+    },
+    total=False,
+)
 
 
 class ConsumerConnectionParams(TypedDict, total=False):
diff --git a/faststream/confluent/security.py b/faststream/confluent/security.py
index 6324b4c43a..3eef59cb89 100644
--- a/faststream/confluent/security.py
+++ b/faststream/confluent/security.py
@@ -49,9 +49,9 @@ def _parse_sasl_plaintext(security: SASLPlaintext) -> "AnyDict":
     return {
         "security_protocol": "SASL_SSL" if security.use_ssl else "SASL_PLAINTEXT",
         "security_config": {
-            "sasl_mechanism": "PLAIN",
-            "sasl_plain_username": security.username,
-            "sasl_plain_password": security.password,
+            "sasl.mechanism": "PLAIN",
+            "sasl.username": security.username,
+            "sasl.password": security.password,
         },
     }
 
@@ -60,9 +60,9 @@ def _parse_sasl_scram256(security: SASLScram256) -> "AnyDict":
     return {
         "security_protocol": "SASL_SSL" if security.use_ssl else "SASL_PLAINTEXT",
         "security_config": {
-            "sasl_mechanism": "SCRAM-SHA-256",
-            "sasl_plain_username": security.username,
-            "sasl_plain_password": security.password,
+            "sasl.mechanism": "SCRAM-SHA-256",
+            "sasl.username": security.username,
+            "sasl.password": security.password,
         },
     }
 
@@ -71,9 +71,9 @@ def _parse_sasl_scram512(security: SASLScram512) -> "AnyDict":
     return {
         "security_protocol": "SASL_SSL" if security.use_ssl else "SASL_PLAINTEXT",
         "security_config": {
-            "sasl_mechanism": "SCRAM-SHA-512",
-            "sasl_plain_username": security.username,
-            "sasl_plain_password": security.password,
+            "sasl.mechanism": "SCRAM-SHA-512",
+            "sasl.username": security.username,
+            "sasl.password": security.password,
         },
     }
 
@@ -82,7 +82,7 @@ def _parse_sasl_oauthbearer(security: SASLOAuthBearer) -> "AnyDict":
     return {
         "security_protocol": "SASL_SSL" if security.use_ssl else "SASL_PLAINTEXT",
         "security_config": {
-            "sasl_mechanism": "OAUTHBEARER",
+            "sasl.mechanism": "OAUTHBEARER",
         },
     }
 
@@ -91,6 +91,6 @@ def _parse_sasl_gssapi(security: SASLGSSAPI) -> "AnyDict":
     return {
         "security_protocol": "SASL_SSL" if security.use_ssl else "SASL_PLAINTEXT",
         "security_config": {
-            "sasl_mechanism": "GSSAPI",
+            "sasl.mechanism": "GSSAPI",
         },
     }


Test patch:
diff --git a/tests/a_docs/confluent/test_security.py b/tests/a_docs/confluent/test_security.py
index b0ba4c8676..bba3b12deb 100644
--- a/tests/a_docs/confluent/test_security.py
+++ b/tests/a_docs/confluent/test_security.py
@@ -30,9 +30,9 @@ async def test_scram256():
 
             call_kwargs = {
                 "security_config": {
-                    "sasl_mechanism": "SCRAM-SHA-256",
-                    "sasl_plain_username": "admin",
-                    "sasl_plain_password": "password",  # pragma: allowlist secret
+                    "sasl.mechanism": "SCRAM-SHA-256",
+                    "sasl.username": "admin",
+                    "sasl.password": "password",  # pragma: allowlist secret
                 },
                 "security_protocol": "SASL_SSL",
             }
@@ -58,9 +58,9 @@ async def test_scram512():
 
             call_kwargs = {
                 "security_config": {
-                    "sasl_mechanism": "SCRAM-SHA-512",
-                    "sasl_plain_username": "admin",
-                    "sasl_plain_password": "password",  # pragma: allowlist secret
+                    "sasl.mechanism": "SCRAM-SHA-512",
+                    "sasl.username": "admin",
+                    "sasl.password": "password",  # pragma: allowlist secret
                 },
                 "security_protocol": "SASL_SSL",
             }
@@ -86,9 +86,9 @@ async def test_plaintext():
 
             call_kwargs = {
                 "security_config": {
-                    "sasl_mechanism": "PLAIN",
-                    "sasl_plain_username": "admin",
-                    "sasl_plain_password": "password",  # pragma: allowlist secret
+                    "sasl.mechanism": "PLAIN",
+                    "sasl.username": "admin",
+                    "sasl.password": "password",  # pragma: allowlist secret
                 },
                 "security_protocol": "SASL_SSL",
             }
@@ -114,7 +114,7 @@ async def test_oathbearer():
 
             call_kwargs = {
                 "security_config": {
-                    "sasl_mechanism": "OAUTHBEARER",
+                    "sasl.mechanism": "OAUTHBEARER",
                 },
                 "security_protocol": "SASL_SSL",
             }
@@ -140,7 +140,7 @@ async def test_gssapi():
 
             call_kwargs = {
                 "security_config": {
-                    "sasl_mechanism": "GSSAPI",
+                    "sasl.mechanism": "GSSAPI",
                 },
                 "security_protocol": "SASL_SSL",
             }