MCPcopy Index your code
hub / github.com/mongodb/mongo-python-driver / _authenticate_scram

Function _authenticate_scram

pymongo/asynchronous/auth.py:72–154  ·  view source on GitHub ↗

Authenticate using SCRAM.

(
    credentials: MongoCredential, conn: AsyncConnection, mechanism: str
)

Source from the content-addressed store, hash-verified

70
71
72async def _authenticate_scram(
73 credentials: MongoCredential, conn: AsyncConnection, mechanism: str
74) -> None:
75 """Authenticate using SCRAM."""
76 username = credentials.username
77 if mechanism == "SCRAM-SHA-256":
78 digest = "sha256"
79 digestmod = hashlib.sha256
80 data = saslprep(credentials.password).encode("utf-8")
81 else:
82 digest = "sha1"
83 digestmod = hashlib.sha1
84 data = _password_digest(username, credentials.password).encode("utf-8")
85 source = credentials.source
86 cache = credentials.cache
87
88 # Make local
89 _hmac = hmac.HMAC
90
91 ctx = conn.auth_ctx
92 if ctx and ctx.speculate_succeeded():
93 assert isinstance(ctx, _ScramContext)
94 assert ctx.scram_data is not None
95 nonce, first_bare = ctx.scram_data
96 res = ctx.speculative_authenticate
97 else:
98 nonce, first_bare, cmd = _authenticate_scram_start(credentials, mechanism)
99 res = await conn.command(source, cmd)
100
101 assert res is not None
102 server_first = res["payload"]
103 parsed = _parse_scram_response(server_first)
104 iterations = int(parsed[b"i"])
105 if iterations < 4096:
106 raise OperationFailure("Server returned an invalid iteration count.")
107 salt = parsed[b"s"]
108 rnonce = parsed[b"r"]
109 if not rnonce.startswith(nonce):
110 raise OperationFailure("Server returned an invalid nonce.")
111
112 without_proof = b"c=biws,r=" + rnonce
113 if cache.data:
114 client_key, server_key, csalt, citerations = cache.data
115 else:
116 client_key, server_key, csalt, citerations = None, None, None, None
117
118 # Salt and / or iterations could change for a number of different
119 # reasons. Either changing invalidates the cache.
120 if not client_key or salt != csalt or iterations != citerations:
121 salted_pass = hashlib.pbkdf2_hmac(digest, data, standard_b64decode(salt), iterations)
122 client_key = _hmac(salted_pass, b"Client Key", digestmod).digest()
123 server_key = _hmac(salted_pass, b"Server Key", digestmod).digest()
124 cache.data = (client_key, server_key, salt, iterations)
125 stored_key = digestmod(client_key).digest()
126 auth_msg = b",".join((first_bare, server_first, without_proof))
127 client_sig = _hmac(stored_key, auth_msg, digestmod).digest()
128 client_proof = b"p=" + standard_b64encode(_xor(client_key, client_sig))
129 client_final = b",".join((without_proof, client_proof))

Callers 1

_authenticate_defaultFunction · 0.70

Calls 11

saslprepFunction · 0.90
_parse_scram_responseFunction · 0.90
OperationFailureClass · 0.90
_xorFunction · 0.90
BinaryClass · 0.90
encodeMethod · 0.80
_password_digestFunction · 0.70
speculate_succeededMethod · 0.45
commandMethod · 0.45
joinMethod · 0.45

Tested by

no test coverage detected