{"record":{"id":"ff712a03e0b3fa90","repo":"aio-libs/aiohttp","slug":"a-is-not-allowed-in-username-rfc-1945-section","errorCode":null,"errorMessage":"A \":\" is not allowed in username (RFC 1945#section-11.1)","messagePattern":"A \":\" is not allowed in username \\(RFC 1945#section-11\\.1\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/client_middleware_digest_auth.py","lineNumber":209,"sourceCode":"    The core digest calculation is inspired by the implementation in\n    https://github.com/requests/requests/blob/v2.18.4/requests/auth.py\n    with added support for modern digest auth features and error handling.\n    \"\"\"\n\n    def __init__(\n        self,\n        login: str,\n        password: str,\n        preemptive: bool = True,\n    ) -> None:\n        if login is None:\n            raise ValueError(\"None is not allowed as login value\")\n\n        if password is None:\n            raise ValueError(\"None is not allowed as password value\")\n\n        if \":\" in login:\n            raise ValueError('A \":\" is not allowed in username (RFC 1945#section-11.1)')\n\n        self._login_str: Final[str] = login\n        self._login_bytes: Final[bytes] = login.encode(\"utf-8\")\n        self._password_bytes: Final[bytes] = password.encode(\"utf-8\")\n\n        self._last_nonce_bytes = b\"\"\n        self._nonce_count = 0\n        self._challenge: DigestAuthChallenge = {}\n        self._preemptive: bool = preemptive\n        # Set of URLs defining the protection space\n        self._protection_space: list[str] = []\n        # Origin the credentials are scoped to; set on the first request.\n        self._origin: URL | None = None\n\n    async def _encode(self, method: str, url: URL, body: Payload | Literal[b\"\"]) -> str:\n        \"\"\"\n        Build digest authorization header for the current challenge.\n","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/client_middleware_digest_auth.py#L191-L227","documentation":"Raised by DigestAuthMiddleware.__init__ when login contains a ':' character. RFC 1945 section 11.1 forbids ':' in digest usernames because it is the delimiter of the username realm fields in the Authorization header; including it would corrupt the header grammar.","triggerScenarios":"Constructing DigestAuthMiddleware(login='domain\\\\user:extra', password='x') or any login value that contains a colon. The ':' in login check fires before any encoding.","commonSituations":"AD-style 'domain\\\\user' formatted with a colon by mistake. Email-style 'user:realm' usernames. Concatenating realm and username with ':'.","solutions":["Remove the ':' from the username (e.g. use 'domain\\\\user' or 'user@realm' if the server accepts it).","If you constructed the value by joining fields with ':', switch the separator to '.' or '_'.","Verify against the server's accepted username format (often just the bare sAMAccountName)."],"exampleFix":"// before\nmw = DigestAuthMiddleware(login='corp:jdoe', password='x')\n// after\nmw = DigestAuthMiddleware(login='jdoe', password='x')","handlingStrategy":"validation","validationCode":"def sanitize_login(login: str) -> str:\n    if ':' in login:\n        raise ValueError('login must not contain \":\" per RFC 1945')\n    return login\n\nDigestAuthMiddleware(login=sanitize_login(login), password=password)","typeGuard":"def is_rfc1945_login(v: str) -> bool:\n    return isinstance(v, str) and ':' not in v","tryCatchPattern":"try:\n    mw = DigestAuthMiddleware(login=login, password=password)\nexcept ValueError as e:\n    if ':' in str(e) or 'RFC 1945' in str(e):\n        login = login.replace(':', '_')\n        mw = DigestAuthMiddleware(login=login, password=password)\n    else:\n        raise","preventionTips":["Build usernames from typed fields, never by joining with ':'.","Validate credential format at the config boundary, not in the auth library.","Document the RFC 1945 username restriction for ops teams supplying credentials."],"tags":["authentication","digest-auth","validation","rfc"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}