Skip to content

Commit 5a98a78

Browse files
kaushikaryan04pandafy
authored andcommitted
[change] Implemented-suggested-changes #523
-Added Validation for email -If validation is failed we try to get email from attributes -Added tests to see if Exception is raised when invalid mail is provided Fixes #523
1 parent e0946e0 commit 5a98a78

File tree

3 files changed

+58
-10
lines changed

3 files changed

+58
-10
lines changed

openwisp_radius/saml/utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,16 @@ def get_url_or_path(url):
99
if parsed_url.netloc:
1010
return f'{parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path}'
1111
return parsed_url.path
12+
13+
14+
def get_email_from_ava(ava):
15+
email_keys = (
16+
'email',
17+
'mail',
18+
'uid',
19+
)
20+
for key in email_keys:
21+
email = ava.get(key, None)
22+
if email is not None:
23+
return email[0]
24+
return None

openwisp_radius/saml/views.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import swapper
55
from allauth.account.models import EmailAddress
66
from allauth.account.utils import send_email_confirmation
7+
from allauth.utils import ValidationError
78
from django import forms
89
from django.conf import settings
910
from django.contrib.auth import get_user_model, logout
@@ -23,7 +24,7 @@
2324
from .. import settings as app_settings
2425
from ..api.views import RadiusTokenMixin
2526
from ..utils import get_organization_radius_settings, load_model
26-
from .utils import get_url_or_path
27+
from .utils import get_email_from_ava, get_url_or_path
2728

2829
logger = logging.getLogger(__name__)
2930

@@ -81,15 +82,30 @@ def post_login_hook(self, request, user, session_info):
8182
if uid_is_email:
8283
email = session_info['name_id'].text
8384
if email is None:
84-
email = session_info['ava'].get('email', [None])[0]
85+
email = get_email_from_ava(session_info['ava'])
8586
if email:
8687
user.email = email
87-
user.save()
88-
email_address = EmailAddress.objects.create(
89-
user=user, email=email, verified=True, primary=True
90-
)
91-
email_address.save()
92-
88+
try:
89+
user.full_clean()
90+
user.save()
91+
EmailAddress.objects.create(
92+
user=user, email=email, verified=True, primary=True
93+
)
94+
except ValidationError:
95+
assertion_email = get_email_from_ava(session_info['ava'])
96+
if assertion_email and assertion_email != email:
97+
user.email = assertion_email
98+
try:
99+
user.full_clean()
100+
user.save()
101+
EmailAddress.objects.create(
102+
user=user,
103+
email=assertion_email,
104+
verified=True,
105+
primary=True,
106+
)
107+
except ValidationError:
108+
raise ValidationError('Email Verification Failed')
93109
registered_user = RegisteredUser(
94110
user=user, method='saml', is_verified=app_settings.SAML_IS_VERIFIED
95111
)

openwisp_radius/tests/test_saml/test_views.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.conf import settings
88
from django.contrib.auth import SESSION_KEY, get_user_model
99
from django.core import mail
10+
from django.core.validators import ValidationError
1011
from django.test import TestCase, override_settings
1112
from django.urls import reverse, reverse_lazy
1213
from djangosaml2.tests import auth_response, conf
@@ -61,12 +62,12 @@ class TestAssertionConsumerServiceView(TestSamlMixin, TestCase):
6162
def _get_relay_state(self, redirect_url, org_slug):
6263
return f'{redirect_url}?org={org_slug}'
6364

64-
def _get_saml_response_for_acs_view(self, relay_state):
65+
def _get_saml_response_for_acs_view(self, relay_state, uid='[email protected]'):
6566
response = self.client.get(self.login_url, {'RelayState': relay_state})
6667
saml2_req = saml2_from_httpredirect_request(response.url)
6768
session_id = get_session_id_from_saml2(saml2_req)
6869
self.add_outstanding_query(session_id, relay_state)
69-
return auth_response(session_id, '[email protected]'), relay_state
70+
return auth_response(session_id, uid), relay_state
7071

7172
def _post_successful_auth_assertions(self, query_params, org_slug):
7273
self.assertEqual(User.objects.count(), 1)
@@ -108,6 +109,24 @@ def test_organization_slug_present(self):
108109
query_params = parse_qs(urlparse(response.url).query)
109110
self._post_successful_auth_assertions(query_params, org_slug)
110111

112+
@capture_any_output()
113+
def test_invalid_email_raise_validation_error(self):
114+
invalid_email = 'invalid_email@example'
115+
relay_state = self._get_relay_state(
116+
redirect_url='https://captive-portal.example.com', org_slug='default'
117+
)
118+
saml_response, relay_state = self._get_saml_response_for_acs_view(
119+
relay_state, uid=invalid_email
120+
)
121+
with self.assertRaises(ValidationError):
122+
self.client.post(
123+
reverse('radius:saml2_acs'),
124+
{
125+
'SAMLResponse': self.b64_for_post(saml_response),
126+
'RelayState': relay_state,
127+
},
128+
)
129+
111130
@capture_any_output()
112131
def test_relay_state_relative_path(self):
113132
expected_redirect_path = '/radius/saml2/additional-info/'

0 commit comments

Comments
 (0)