@@ -90,6 +90,14 @@ def _merge_claims_challenge_and_capabilities(capabilities, claims_challenge):
90
90
return json .dumps (claims_dict )
91
91
92
92
93
+ def _str2bytes (raw ):
94
+ # A conversion based on duck-typing rather than six.text_type
95
+ try :
96
+ return raw .encode (encoding = "utf-8" )
97
+ except :
98
+ return raw
99
+
100
+
93
101
class ClientApplication (object ):
94
102
95
103
ACQUIRE_TOKEN_SILENT_ID = "84"
@@ -124,6 +132,7 @@ def __init__(
124
132
"private_key": "...-----BEGIN PRIVATE KEY-----...",
125
133
"thumbprint": "A1B2C3D4E5F6...",
126
134
"public_certificate": "...-----BEGIN CERTIFICATE-----..." (Optional. See below.)
135
+ "passphrase": "Passphrase if the private_key is encrypted (Optional)"
127
136
}
128
137
129
138
*Added in version 0.5.0*:
@@ -252,8 +261,18 @@ def _build_client(self, client_credential, authority):
252
261
headers = {}
253
262
if 'public_certificate' in client_credential :
254
263
headers ["x5c" ] = extract_certs (client_credential ['public_certificate' ])
264
+ if not client_credential .get ("passphrase" ):
265
+ unencrypted_private_key = client_credential ['private_key' ]
266
+ else :
267
+ from cryptography .hazmat .primitives import serialization
268
+ from cryptography .hazmat .backends import default_backend
269
+ unencrypted_private_key = serialization .load_pem_private_key (
270
+ _str2bytes (client_credential ["private_key" ]),
271
+ _str2bytes (client_credential ["passphrase" ]),
272
+ backend = default_backend (), # It was a required param until 2020
273
+ )
255
274
assertion = JwtAssertionCreator (
256
- client_credential [ "private_key" ] , algorithm = "RS256" ,
275
+ unencrypted_private_key , algorithm = "RS256" ,
257
276
sha1_thumbprint = client_credential .get ("thumbprint" ), headers = headers )
258
277
client_assertion = assertion .create_regenerative_assertion (
259
278
audience = authority .token_endpoint , issuer = self .client_id ,
0 commit comments