Projet

Général

Profil

0004-idp_oidc-render-templated-claims-in-user-info-creati.patch

Paul Marillonnet, 09 mars 2020 11:40

Télécharger (4,94 ko)

Voir les différences:

Subject: [PATCH 4/4] idp_oidc: render templated claims in user-info-creation
 utilities (#37884)

 src/authentic2_idp_oidc/utils.py | 11 +++--
 tests/test_idp_oidc.py           | 73 ++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 3 deletions(-)
src/authentic2_idp_oidc/utils.py
30 30

  
31 31
from authentic2 import hooks, crypto
32 32
from authentic2.attributes_ng.engine import get_attributes
33
from authentic2.utils.template import Template
33 34

  
34 35
from . import app_settings
35 36

  
......
197 198
        if not set(claim.get_scopes()).intersection(scope_set):
198 199
            continue
199 200
        claims_to_show.add(claim)
200
        if claim.value not in attributes:
201
            continue
202
        attribute_value = attributes[claim.value]
201
        if claim.value and ('{{' in claim.value or '{%' in claim.value):
202
            template = Template(claim.value)
203
            attribute_value = template.render(context=attributes)
204
        else:
205
            if claim.value not in attributes:
206
                continue
207
            attribute_value = attributes[claim.value]
203 208
        if attribute_value is None:
204 209
            continue
205 210
        user_info[claim.name] = normalize_claim_values(attribute_value)
tests/test_idp_oidc.py
1116 1116
    assert 'family_name' not in user_info
1117 1117

  
1118 1118

  
1119
def test_claim_templated(oidc_settings, normal_oidc_client, simple_user, app):
1120
    oidc_settings.A2_IDP_OIDC_SCOPES = ['openid', 'profile', 'email']
1121
    OIDCClaim.objects.filter(
1122
            client=normal_oidc_client, name='given_name').delete()
1123
    OIDCClaim.objects.filter(
1124
            client=normal_oidc_client, name='family_name').delete()
1125
    claim1 = OIDCClaim.objects.create(
1126
            client=normal_oidc_client,
1127
            name='given_name',
1128
            value='{{ django_user_first_name|add:"ounet" }}',
1129
            scopes='profile')
1130
    claim2 = OIDCClaim.objects.create(
1131
            client=normal_oidc_client,
1132
            name='family_name',
1133
            value='{{ "Von der "|add:django_user_last_name }}',
1134
            scopes='profile')
1135
    normal_oidc_client.authorization_flow = normal_oidc_client.FLOW_AUTHORIZATION_CODE
1136
    normal_oidc_client.authorization_mode = normal_oidc_client.AUTHORIZATION_MODE_NONE
1137
    normal_oidc_client.save()
1138

  
1139
    utils.login(app, simple_user)
1140

  
1141
    oidc_client = normal_oidc_client
1142
    redirect_uri = oidc_client.redirect_uris.split()[0]
1143

  
1144
    params = {
1145
        'client_id': oidc_client.client_id,
1146
        'scope': 'openid email profile',
1147
        'redirect_uri': redirect_uri,
1148
        'state': 'xxx',
1149
        'nonce': 'yyy',
1150
        'response_type': 'code',
1151
    }
1152

  
1153
    def sso():
1154
        authorize_url = make_url('oidc-authorize', params=params)
1155

  
1156
        response = app.get(authorize_url)
1157
        location = urlparse.urlparse(response['Location'])
1158
        query = urlparse.parse_qs(location.query)
1159
        code = query['code'][0]
1160

  
1161
        token_url = make_url('oidc-token')
1162
        response = app.post(token_url, params={
1163
            'grant_type': 'authorization_code',
1164
            'code': code,
1165
            'redirect_uri': oidc_client.redirect_uris.split()[0],
1166
        }, headers=client_authentication_headers(oidc_client))
1167
        access_token = response.json['access_token']
1168
        id_token = response.json['id_token']
1169

  
1170
        k = base64.b64encode(oidc_client.client_secret.encode('utf-8'))
1171
        key = JWK(kty='oct', k=force_text(k))
1172
        jwt = JWT(jwt=id_token, key=key)
1173
        claims = json.loads(jwt.claims)
1174

  
1175
        user_info_url = make_url('oidc-user-info')
1176
        response = app.get(user_info_url, headers=bearer_authentication_headers(access_token))
1177
        return claims, response.json
1178

  
1179
    claims, user_info = sso()
1180

  
1181
    assert claims['given_name'].endswith('ounet')
1182
    assert claims['given_name'].startswith(simple_user.first_name)
1183
    assert claims['family_name'].startswith('Von der')
1184
    assert claims['family_name'].endswith(simple_user.last_name)
1185

  
1186
    assert user_info['given_name'].endswith('ounet')
1187
    assert user_info['given_name'].startswith(simple_user.first_name)
1188
    assert user_info['family_name'].startswith('Von der')
1189
    assert user_info['family_name'].endswith(simple_user.last_name)
1190

  
1191

  
1119 1192
def test_client_is_valid_redirect_uri():
1120 1193
    client = OIDCClient(redirect_uris='''http://example.com
1121 1194
http://example2.com/
1122
-