Skip to content

Commit bbeb494

Browse files
Vit Curdarayluo
authored andcommitted
certificate made optionall
update as per discussion
1 parent 14bcad3 commit bbeb494

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

msal/application.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,27 @@ def _str2bytes(raw):
6666
except:
6767
return raw
6868

69+
def _extract_cert_and_thumbprints(private_key, cert):
70+
# Cert concepts https://security.stackexchange.com/a/226758/125264
71+
from cryptography.hazmat.primitives import hashes, serialization
72+
cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM).decode()
73+
x5c = [
74+
'\n'.join(cert_pem.splitlines()[1:-1])
75+
]
76+
sha256_thumbprint = cert.fingerprint(hashes.SHA256()).hex()
77+
sha1_thumbprint = cert.fingerprint(hashes.SHA1()).hex()
78+
return private_key, sha256_thumbprint, sha1_thumbprint, x5c
6979

7080
def _parse_pfx(pfx_path, passphrase_bytes):
7181
# Cert concepts https://security.stackexchange.com/a/226758/125264
72-
from cryptography.hazmat.primitives import hashes, serialization
7382
from cryptography.hazmat.primitives.serialization import pkcs12
7483
with open(pfx_path, 'rb') as f:
7584
private_key, cert, _ = pkcs12.load_key_and_certificates( # cryptography 2.5+
7685
# https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/#cryptography.hazmat.primitives.serialization.pkcs12.load_key_and_certificates
7786
f.read(), passphrase_bytes)
7887
if not (private_key and cert):
7988
raise ValueError("Your PFX file shall contain both private key and cert")
80-
cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM).decode() # cryptography 1.0+
81-
x5c = [
82-
'\n'.join(cert_pem.splitlines()[1:-1]) # Strip the "--- header ---" and "--- footer ---"
83-
]
84-
sha256_thumbprint = cert.fingerprint(hashes.SHA256()).hex() # cryptography 0.7+
85-
sha1_thumbprint = cert.fingerprint(hashes.SHA1()).hex() # cryptography 0.7+
86-
# https://cryptography.io/en/latest/x509/reference/#x-509-certificate-object
87-
return private_key, sha256_thumbprint, sha1_thumbprint, x5c
89+
return _extract_cert_and_thumbprints(private_key, cert)
8890

8991

9092
def _load_private_key_from_pem_str(private_key_pem_str, passphrase_bytes):
@@ -288,7 +290,7 @@ def __init__(
288290
289291
{
290292
"private_key": "...-----BEGIN PRIVATE KEY-----... in PEM format",
291-
"thumbprint": "An SHA-1 thumbprint such as A1B2C3D4E5F6...",
293+
"thumbprint": "An SHA-1 thumbprint such as A1B2C3D4E5F6...", # Optional since version 1.35.0
292294
"passphrase": "Needed if the private_key is encrypted (Added in version 1.6.0)",
293295
"public_certificate": "...-----BEGIN CERTIFICATE-----...", # Needed if you use Subject Name/Issuer auth. Added in version 0.5.0.
294296
}
@@ -803,6 +805,22 @@ def _build_client(self, client_credential, authority, skip_regional_client=False
803805
passphrase_bytes)
804806
if client_credential.get("public_certificate") is True and x5c:
805807
headers["x5c"] = x5c
808+
elif (client_credential.get("private_key")
809+
and client_credential.get("public_certificate")
810+
and not client_credential.get("thumbprint")): #in case user does not pass thumbprint but only certificate and private key
811+
if passphrase_bytes: # PEM with passphrase
812+
private_key = _load_private_key_from_pem_str(
813+
client_credential['private_key'], passphrase_bytes)
814+
else: # PEM without passphrase
815+
private_key = client_credential['private_key']
816+
817+
private_key, sha256_thumbprint, sha1_thumbprint, x5c =(
818+
_extract_cert_and_thumbprints(
819+
private_key,
820+
client_credential['public_certificate']))
821+
if x5c:
822+
headers["x5c"] = x5c
823+
806824
elif (
807825
client_credential.get("private_key") # PEM blob
808826
and client_credential.get("thumbprint")):
@@ -1828,9 +1846,9 @@ def acquire_token_by_username_password(
18281846
18291847
- A successful response would contain "access_token" key,
18301848
- an error response would contain "error" and usually "error_description".
1831-
1832-
[Deprecated] This API is deprecated for public client flows and will be
1833-
removed in a future release. Use a more secure flow instead.
1849+
1850+
[Deprecated] This API is deprecated for public client flows and will be
1851+
removed in a future release. Use a more secure flow instead.
18341852
Migration guide: https://aka.ms/msal-ropc-migration
18351853
18361854
"""

0 commit comments

Comments
 (0)