idp_oidc: refactor cleaning of claim values (#57525)

This commit is contained in:
Benjamin Dauvergne 2021-10-01 18:58:46 +02:00
parent bea7640b8e
commit 7d2c4ef181
2 changed files with 28 additions and 11 deletions

View File

@ -17,6 +17,7 @@
import base64
import hashlib
import json
import logging
import urllib.parse
import uuid
@ -33,6 +34,8 @@ from authentic2.utils.template import Template
from . import app_settings
logger = logging.getLogger(__name__)
def base64url(content):
return base64.urlsafe_b64encode(content).strip(b'=')
@ -170,15 +173,14 @@ def reverse_pairwise_sub(client, sub):
return None
def normalize_claim_values(values):
values_list = []
if isinstance(values, str) or not hasattr(values, '__iter__'):
return values
for value in values:
if isinstance(value, bool):
value = str(value).lower()
values_list.append(value)
return values_list
def clean_claim_value(value):
if isinstance(value, (int, float, str, bool)):
return value
if isinstance(value, dict):
return {clean_claim_value(k): clean_claim_value(v) for k, v in value.items()}
if hasattr(value, '__iter__'):
return [clean_claim_value(v) for v in value]
return str(value)
def create_user_info(request, client, user, scope_set, id_token=False):
@ -206,13 +208,23 @@ def create_user_info(request, client, user, scope_set, id_token=False):
else:
if claim.value not in attributes:
continue
attribute_value = attributes[claim.value]
try:
attribute_value = attributes[claim.value]
except KeyError:
msg = f'idp_oidc: could not map claim "{claim.name}", claim value "{claim.value}" not found'
logger.exception(msg)
if attribute_value is None:
continue
user_info[claim.name] = normalize_claim_values(attribute_value)
try:
user_info[claim.name] = clean_claim_value(attribute_value)
except Exception:
msg = f'idp_oidc: could not map claim {claim.name}'
logger.exception(msg)
continue
# check if attribute is verified
if claim.value + ':verified' in attributes:
user_info[claim.name + '_verified'] = True
for claim in claims_to_show:
if claim.name not in user_info:
default_value = None

View File

@ -27,6 +27,7 @@ from django.core.files import File
from django.http import QueryDict
from django.test.utils import override_settings
from django.urls import reverse
from django.utils.dateparse import parse_datetime
from django.utils.encoding import force_text
from django.utils.timezone import now
from jwcrypto.jwk import JWK, JWKSet
@ -289,12 +290,16 @@ def test_authorization_code_sso(
OIDCClaim.objects.create(
client=oidc_client, name='cityscape_image', value='django_user_cityscape_image', scopes='profile'
)
OIDCClaim.objects.create(
client=oidc_client, name='date_joined', value='django_user_date_joined', scopes='profile'
)
simple_user.roles.add(
get_role_model().objects.create(name='Whatever', slug='whatever', ou=get_default_ou())
)
response = app.get(user_info_url, headers=bearer_authentication_headers(access_token))
assert response.json['ou'] == simple_user.ou.name
assert response.json['roles'][0] == 'Whatever'
assert parse_datetime(response.json['date_joined'])
assert response.json.get('cityscape_image') is None
with open('tests/200x200.jpg', 'rb') as fd:
simple_user.attributes.cityscape_image = File(fd)