Skip to content

Commit eead403

Browse files
Altering how JWT_ALGORITHMS work in oidc authenticator
1 parent 6b2efe3 commit eead403

File tree

1 file changed

+37
-4
lines changed
  • ansible_base/authentication/authenticator_plugins

1 file changed

+37
-4
lines changed

ansible_base/authentication/authenticator_plugins/oidc.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ class OpenIdConnectConfiguration(BaseAuthenticatorConfiguration):
123123
)
124124

125125
JWT_ALGORITHMS = ListField(
126-
help_text=_("The algorithm(s) for decoding JWT responses from the IDP."),
126+
help_text=_(
127+
"The algorithm(s) for decoding JWT responses from the IDP. "
128+
"Leave blank to extract from the .well-known configuration (if that fails we will attempt the default algorithms). "
129+
"Set to ['none'] to not use encrypted tokens (the provider must send unencrypted tokens for this to work)"
130+
),
127131
default=None,
128132
allow_null=True,
129133
validators=[JWTAlgorithmListFieldValidator()],
@@ -263,6 +267,28 @@ def public_key(self):
263267
)
264268
return None
265269

270+
def _get_jwt_algorithms(self) -> list[str]:
271+
"""
272+
Get the JWT algorithms to pass to the decode
273+
"""
274+
if self.setting("JWT_ALGORITHMS"):
275+
# If the admin specified the algorithms then use them
276+
return self.setting("JWT_ALGORITHMS")
277+
else:
278+
# Try to get the algorithms from the .well-known/openid-configuration
279+
try:
280+
logger.debug("Attempting to get the JWT algorithms from the .well-known/openid-configuration")
281+
config = self.oidc_config()
282+
idp_algorithms = config.get("id_token_encryption_alg_values_supported")
283+
if idp_algorithms:
284+
logger.debug(f"JWT algorithms supported by the IDP: {idp_algorithms}")
285+
return idp_algorithms
286+
except Exception as e:
287+
# In controller 2.4 we did not have the ability to set the JWT algorithms so we will use the default algorithms
288+
lib_defaults = super().JWT_ALGORITHMS
289+
logger.error(f"Unable to get JWT algorithms from the .well-known/openid-configuration, defaulting to {lib_defaults}: {e}")
290+
return lib_defaults
291+
266292
def user_data(self, access_token, *args, **kwargs):
267293
"""
268294
This function overrides the one in social auth class OpenIdConnectAuth, since
@@ -277,18 +303,25 @@ def user_data(self, access_token, *args, **kwargs):
277303
# If the content type is application/jwt than we can assume that the token is encrypted. Otherwise it should be application/json
278304
pubkey = self.public_key()
279305
if not pubkey:
280-
logger.error(_("OIDC client sent encrypted user info response, but no public key found."))
306+
logger.error("OIDC client sent encrypted user info response, but no public key found.")
281307
return None
308+
# Get the algorithms to pass to the decode
309+
algorithms = self._get_jwt_algorithms()
310+
options = {}
311+
if algorithms == ['none']:
312+
logger.info("JWT decryption algorithm is set to ['none'], will proceed but this is insecure")
313+
options['verify_signature'] = False
282314
try:
283315
data = jwt.decode(
284316
access_token,
285317
key=pubkey,
286-
algorithms=self.setting("JWT_ALGORITHMS"),
318+
algorithms=algorithms,
287319
audience=self.setting("KEY"),
320+
options=options,
288321
)
289322
return data
290323
except PyJWTError as e:
291-
logger.error(_(f"Unable to decode user info response JWT: {e}"))
324+
logger.error(f"Unable to decode user info response JWT: {e}")
292325
return None
293326
return user_data.json()
294327

0 commit comments

Comments
 (0)