Commit e3cd2e3c authored by Joao Pedro Lopes's avatar Joao Pedro Lopes
Browse files
parent c3fbbf5b
Pipeline #3094317 passed with stages
in 10 minutes and 45 seconds
......@@ -291,46 +291,58 @@ class FTS3OAuth2ResourceProvider(ResourceProvider):
:param access_token:
:return: tuple(valid, credential) or tuple(False, None)
"""
def decode(key):
log.debug("Attempt decoding using key={}".format(key.export()))
try:
if "wlcg" in issuer:
audience = "https://wlcg.cern.ch/jwt/v1/any"
credential = jwt.decode(
access_token,
key.export_to_pem(),
algorithms=[algorithm],
audience=audience,
)
else:
# We don't check audience for non-WLCG token
credential = jwt.decode(
access_token,
key.export_to_pem(),
algorithms=[algorithm],
options={"verify_aud": False},
)
return credential
except Exception:
return None
log.debug("entered validate_token_offline")
credential = None
try:
unverified_payload = jwt.decode(access_token, verify=False)
unverified_header = jwt.get_unverified_header(access_token)
issuer = unverified_payload["iss"]
key_id = unverified_header["kid"]
log.debug("issuer={}, key_id={}".format(issuer, key_id))
algorithm = unverified_header.get("alg", "RS256")
log.debug("alg={}".format(algorithm))
pub_key = oidc_manager.get_provider_key(issuer, key_id)
log.debug("key={}".format(pub_key))
pub_key = JWK.from_json(json.dumps(pub_key.to_dict()))
log.debug("pubkey={}".format(pub_key))
# Verify & Validate
if "wlcg" in issuer:
audience = "https://wlcg.cern.ch/jwt/v1/any"
credential = jwt.decode(
access_token,
pub_key.export_to_pem(),
algorithms=[algorithm],
audience=[audience],
)
else:
credential = jwt.decode(
access_token,
pub_key.export_to_pem(),
algorithms=[algorithm],
options={
"verify_aud": False
}, # We don't check audience for non-WLCG token
)
log.debug("offline_response::: {}".format(credential))
key_id = unverified_header.get("kid")
algorithm = unverified_header.get("alg")
log.debug("issuer={}, key_id={}, alg={}".format(issuer, key_id, algorithm))
# Retrieval of keys
keys = oidc_manager.filter_provider_keys(issuer, key_id, algorithm)
jwkeys = [JWK.from_json(json.dumps(key.to_dict())) for key in keys]
# Find the first key which decodes the token
for jwkey in jwkeys:
credential = decode(jwkey)
if credential is not None:
log.debug("offline_response::: {}".format(credential))
break
except Exception as ex:
log.debug(ex)
log.debug("return False (exception)")
log.debug("return False, Exception: {}".format(ex))
return False, None
log.debug("return True, credential")
return True, credential
if credential is None:
log.debug("No key managed to decode the token")
log.debug("return {}, credential".format(credential is not None))
return (credential is not None), credential
def _validate_token_online(self, access_token):
"""
......
......@@ -57,20 +57,25 @@ class OIDCmanager:
for keybundle in keybundles:
keybundle.cache_time = cache_time
def get_provider_key(self, issuer, kid):
def filter_provider_keys(self, issuer, kid=None, alg=None):
"""
Get a Provider Key by ID
Return Provider Keys after applying Key ID and Algorithm filter.
If no filters match, return the full set.
:param issuer: provider
:param kid: Key ID
:return: key
:raise ValueError: if key not found
:param alg: Algorithm
:return: keys
:raise ValueError: client could not be retrieved
"""
client = self.clients[issuer]
keys = client.keyjar.get_issuer_keys(issuer) # List of Keys (from pyjwkest)
for key in keys:
if key.kid == kid:
return key
raise ValueError("Key with kid {} not found".format(kid))
client = self.clients.get(issuer)
if client is None:
raise ValueError("Could not retrieve client for issuer={}".format(issuer))
# List of Keys (from pyjwkest)
keys = client.keyjar.get_issuer_keys(issuer)
filtered_keys = [key for key in keys if key.kid == kid or key.alg == alg]
if len(filtered_keys) is 0:
return keys
return filtered_keys
def introspect(self, issuer, access_token):
"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment