idp_oidc: get user profile selection or consent even when prompt=none (#72507)

This commit is contained in:
Paul Marillonnet 2022-12-16 10:12:06 +01:00
parent 0443245e1e
commit c5b67aaae1
2 changed files with 70 additions and 11 deletions

View File

@ -164,11 +164,6 @@ class InteractionRequired(OIDCException):
show_message = False
class ConsentRequired(OIDCException):
error_code = 'consent_required'
show_message = False
class AccessDenied(OIDCException):
error_code = 'access_denied'
show_message = False
@ -402,8 +397,6 @@ def authorize_for_client(request, client, redirect_uri):
if (authorized_scopes & scopes) < scopes:
needs_scope_validation = True
if needs_scope_validation or (user_has_selectable_profiles and client.activate_user_profiles):
if 'none' in prompt:
raise ConsentRequired(_('Consent is required but prompt parameter is "none"'))
if request.method == 'POST':
if request.POST.get('profile-validation', ''):
try:

View File

@ -37,6 +37,7 @@ from jwcrypto.jwt import JWT
from authentic2.a2_rbac.models import OrganizationalUnit, Role
from authentic2.a2_rbac.utils import get_default_ou
from authentic2.custom_user.models import Profile, ProfileType
from authentic2.models import Attribute, AuthorizedRole
from authentic2.utils.misc import good_next_url, make_url
from authentic2_auth_oidc.utils import parse_timestamp
@ -734,7 +735,37 @@ def test_invalid_request(oidc_client, caplog, oidc_settings, simple_user, app, m
assert urllib.parse.urlparse(response['Location']).path == reverse('auth_login')
if oidc_client.authorization_mode != oidc_client.AUTHORIZATION_MODE_NONE:
# prompt is none, but consent is required
# prompt is none, but account selection is required, out-of-spec corner case without error
oidc_client.activate_user_profiles = True
oidc_client.save()
profile_type_manager = ProfileType.objects.create(
name='One Manager Type',
slug='one-manager-type',
)
profile_type_delegate = ProfileType.objects.create(
name='One Delegate Type',
slug='one-delegate-type',
)
profile_manager = Profile.objects.create(
user=simple_user,
profile_type=profile_type_manager,
identifier='Entity 789',
email='manager@example789.org',
)
profile_delegate = Profile.objects.create(
user=simple_user,
profile_type=profile_type_delegate,
identifier='Entity 1011',
email='delegate@example1011.org',
)
# authorization exists
authorize = OIDCAuthorization.objects.create(
client=oidc_client,
user=simple_user,
scopes='openid profile email',
expired=now() + datetime.timedelta(days=2),
)
response = app.get(
make_url(
'oidc-authorize',
@ -742,14 +773,49 @@ def test_invalid_request(oidc_client, caplog, oidc_settings, simple_user, app, m
'client_id': oidc_client.client_id,
'redirect_uri': redirect_uri,
'response_type': response_type,
'scope': 'openid email profile',
'scope': 'openid',
'prompt': 'none',
},
)
)
assert_authorize_error(
response, 'consent_required', 'Consent is required but prompt parameter is "none"', message=False
response.form['profile-validation'] = str(profile_manager.id)
response = response.form.submit('accept')
if oidc_client.authorization_flow == OIDCClient.FLOW_IMPLICIT:
assert 'access_token' in response.location
assert 'id_token' in response.location
assert 'expires_in' in response.location
assert 'token_type' in response.location
elif oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
assert 'code' in response.location
profile_manager.delete()
profile_delegate.delete()
authorize.delete()
# prompt is none, consent is required, out-of-spec corner case without error
response = app.get(
make_url(
'oidc-authorize',
params={
'client_id': oidc_client.client_id,
'redirect_uri': redirect_uri,
'response_type': response_type,
'scope': 'openid',
'prompt': 'none',
},
)
)
response = response.form.submit('accept')
if oidc_client.authorization_flow == OIDCClient.FLOW_IMPLICIT:
assert 'access_token' in response.location
assert 'id_token' in response.location
assert 'expires_in' in response.location
assert 'token_type' in response.location
elif oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
assert 'code' in response.location
# user do not consent
response = app.get(