Skip to content

Commit b893d0f

Browse files
authored
Merge pull request #3 from knaperek/master
merge
2 parents 10c49ae + 5c59f6b commit b893d0f

File tree

5 files changed

+80
-10
lines changed

5 files changed

+80
-10
lines changed

.travis.yml

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,38 @@ matrix:
2828
env: TOX_ENV=py35-django111
2929
- python: 3.6
3030
env: TOX_ENV=py36-django111
31+
- python: 3.4
32+
env: TOX_ENV=py34-django20
33+
- python: 3.5
34+
env: TOX_ENV=py35-django20
35+
- python: 3.6
36+
env: TOX_ENV=py36-django20
37+
- python: 3.7
38+
env: TOX_ENV=py37-django20
3139
- python: 3.5
32-
env: TOX_ENV=py35-djangomaster
40+
env: TOX_ENV=py35-django21
41+
- python: 3.6
42+
env: TOX_ENV=py36-django21
43+
- python: 3.7
44+
env: TOX_ENV=py37-django21
45+
- python: 3.5
46+
env: TOX_ENV=py35-django22
47+
- python: 3.6
48+
env: TOX_ENV=py36-django22
49+
- python: 3.7
50+
env: TOX_ENV=py37-django22
51+
- python: 3.6
52+
env: TOX_ENV=py36-django30
53+
- python: 3.7
54+
env: TOX_ENV=py37-django30
3355
- python: 3.6
3456
env: TOX_ENV=py36-djangomaster
57+
- python: 3.7
58+
env: TOX_ENV=py37-djangomaster
3559
fast_finish: true
3660
allow_failures:
37-
- env: TOX_ENV=py35-djangomaster
3861
- env: TOX_ENV=py36-djangomaster
62+
- env: TOX_ENV=py37-djangomaster
3963

4064
addons:
4165
apt:

djangosaml2/exceptions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class IdPConfigurationMissing(Exception):
2+
pass

djangosaml2/tests/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@
3535
from django.utils.encoding import force_text
3636
except ImportError:
3737
from django.utils.text import force_text
38-
from django.utils.six.moves.urllib.parse import urlparse, parse_qs
38+
try:
39+
from django.utils.six.moves.urllib.parse import urlparse, parse_qs
40+
except ImportError:
41+
from urllib.parse import urlparse, parse_qs
3942

4043
from saml2.config import SPConfig
4144
from saml2.s_utils import decode_base64_and_inflate, deflate_and_base64_encode

djangosaml2/views.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,15 @@
3232
from django.views.decorators.http import require_POST
3333
from django.shortcuts import render
3434
from django.template import TemplateDoesNotExist
35-
from django.utils.six import text_type, binary_type, PY3
35+
36+
try:
37+
from django.utils.six import text_type, binary_type, PY3
38+
except ImportError:
39+
import sys
40+
PY3 = sys.version_info[0] == 3
41+
text_type = str
42+
binary_type = bytes
43+
3644
from django.views.decorators.csrf import csrf_exempt
3745

3846
from saml2 import BINDING_HTTP_REDIRECT, BINDING_HTTP_POST
@@ -49,6 +57,7 @@
4957

5058
from djangosaml2.cache import IdentityCache, OutstandingQueriesCache
5159
from djangosaml2.cache import StateCache
60+
from djangosaml2.exceptions import IdPConfigurationMissing
5261
from djangosaml2.conf import get_config
5362
from djangosaml2.overrides import Saml2Client
5463
from djangosaml2.signals import post_authenticated
@@ -136,6 +145,13 @@ def login(request,
136145
selected_idp = request.GET.get('idp', None)
137146
conf = get_config(config_loader_path, request)
138147

148+
kwargs = {}
149+
# pysaml needs a string otherwise: "cannot serialize True (type bool)"
150+
if getattr(conf, '_sp_force_authn'):
151+
kwargs['force_authn'] = "true"
152+
if getattr(conf, '_sp_allow_create', "false"):
153+
kwargs['allow_create'] = "true"
154+
139155
# is a embedded wayf needed?
140156
idps = available_idps(conf)
141157
if selected_idp is None and len(idps) > 1:
@@ -144,7 +160,13 @@ def login(request,
144160
'available_idps': idps.items(),
145161
'came_from': came_from,
146162
})
147-
163+
else:
164+
# is the first one, otherwise next logger message will print None
165+
if not idps:
166+
raise IdPConfigurationMissing(('IdP configuration is missing or '
167+
'its metadata is expired.'))
168+
selected_idp = list(idps.keys())[0]
169+
148170
# choose a binding to try first
149171
sign_requests = getattr(conf, '_sp_authn_requests_signed', False)
150172
binding = BINDING_HTTP_POST if sign_requests else BINDING_HTTP_REDIRECT
@@ -184,7 +206,7 @@ def login(request,
184206
session_id, result = client.prepare_for_authenticate(
185207
entityid=selected_idp, relay_state=came_from,
186208
binding=binding, sign=False, sigalg=sigalg,
187-
nsprefix=nsprefix)
209+
nsprefix=nsprefix, **kwargs)
188210
except TypeError as e:
189211
logger.error('Unable to know which IdP to use')
190212
return HttpResponse(text_type(e))
@@ -200,10 +222,11 @@ def login(request,
200222
return HttpResponse(text_type(e))
201223
session_id, request_xml = client.create_authn_request(
202224
location,
203-
binding=binding)
225+
binding=binding,
226+
**kwargs)
204227
try:
205228
if PY3:
206-
saml_request = base64.b64encode(binary_type(request_xml, 'UTF-8'))
229+
saml_request = base64.b64encode(binary_type(request_xml, 'UTF-8')).decode('utf-8')
207230
else:
208231
saml_request = base64.b64encode(binary_type(request_xml))
209232

@@ -458,7 +481,17 @@ def do_logout_service(request, data, binding, config_loader_path=None, next_page
458481
relay_state=data.get('RelayState', ''))
459482
state.sync()
460483
auth.logout(request)
461-
return HttpResponseRedirect(get_location(http_info))
484+
if (
485+
http_info.get('method', 'GET') == 'POST' and
486+
'data' in http_info and
487+
('Content-type', 'text/html') in http_info.get('headers', [])
488+
):
489+
# need to send back to the IDP a signed POST response with user session
490+
# return HTML form content to browser with auto form validation
491+
# to finally send request to the IDP
492+
return HttpResponse(http_info['data'])
493+
else:
494+
return HttpResponseRedirect(get_location(http_info))
462495
else:
463496
logger.error('No SAMLResponse or SAMLRequest parameter found')
464497
raise Http404('No SAMLResponse or SAMLRequest parameter found')

tox.ini

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ envlist =
44
py{27,34,35}-django19
55
py{27,34,35}-django110
66
py{27,34,35,36}-django111
7-
py{35,36}-djangomaster
7+
py{34,35,36,37}-django20
8+
py{35,36,37}-django21
9+
py{35,36,37}-django22
10+
py{36,37}-django30
11+
py{36,37}-djangomaster
812

913
[testenv]
1014
commands =
@@ -15,6 +19,10 @@ deps =
1519
django19: Django>=1.9,<1.10
1620
django110: Django>=1.10,<1.11
1721
django111: Django>=1.11,<2.0
22+
django20: Django>=2.0,<2.1
23+
django21: Django>=2.1,<2.2
24+
django22: Django>=2.2,<3.0
25+
django30: Django>=3.0,<3.1
1826
djangomaster: https://github.com/django/django/archive/master.tar.gz
1927
.[test]
2028

0 commit comments

Comments
 (0)