Reputation: 51
I'm currently integrating SSO using Azure AD for a Django Project. I'm currently using the package: https://github.com/leibowitz/django-azure-ad-auth . I have followed the docs to setup the Azure AD Authentication . On entering the application url, it takes me to the microsoft login page and after entering the credentials it's redirected to the application. But on redirection to the application after the Azure Auth, the code checks in the session for 'nonce' & 'state' variables , which are strangely returned as None and hence the application redirects to the failure url.
@never_cache
def auth(request):
backend = AzureActiveDirectoryBackend()
redirect_uri = request.build_absolute_uri(reverse(complete))
nonce = str(uuid.uuid4())
request.session['nonce'] = nonce
state = str(uuid.uuid4())
request.session['state'] = state
login_url = backend.login_url(
redirect_uri=redirect_uri,
nonce=nonce,
state=state
)
return HttpResponseRedirect(login_url)
@never_cache
@csrf_exempt
def complete(request):
backend = AzureActiveDirectoryBackend()
method = 'GET' if backend.RESPONSE_MODE == 'fragment' else 'POST'
original_state = request.session.get('state')
state = getattr(request, method).get('state')
if original_state == state:
token = getattr(request, method).get('id_token')
nonce = request.session.get('nonce')
user = backend.authenticate(token=token, nonce=nonce)
if user is not None:
login(request, user)
return HttpResponseRedirect(get_login_success_url(request))
return HttpResponseRedirect('failure')
This is the code used for authentication.
Settings.py sample is given below:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'azure_ad_auth.backends.AzureActiveDirectoryBackend',
)
LOGIN_REDIRECT_URL = '/login_successful/'
AAD_TENANT_ID = 'd472b4f4-95c5-4eb3-8a9a-3615c837eada'
AAD_CLIENT_ID = '75e38b53-8174-4dc6-a8f6-bb7a913f1565'
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_SAVE_EVERY_REQUEST = True
SESSION_COOKIE_AGE = 86400 # sec
SESSION_COOKIE_DOMAIN = None
SESSION_COOKIE_NAME = 'DSESSIONID'
SESSION_COOKIE_SECURE = True
Traceback
TypeError at /TypeError at /project/azure/complete/
must be str, not NoneType
Request Method: POST
Request URL: http://testdomain.com/project/azure/complete/
Django Version: 2.2.4
Exception Type: TypeError
Exception Value:
must be str, not NoneType
Exception Location: /home/project/azure_auth/views.py in complete, line 57
Python Executable: /home/project/app/venv/bin/python3
Python Version: 3.6.8
Python Path:
['/home/project/app/project',
'/home/project/app/venv/bin',
'/home/project/app/venv/lib64/python36.zip',
'/home/project/app/venv/lib64/python3.6',
'/home/project/app/venv/lib64/python3.6/lib-dynload',
'/usr/lib64/python3.6',
'/usr/lib/python3.6',
'/home/project/app/venv/lib/python3.6/site-packages']
Server time: Tue, 19 Nov 2019 05:21:10 +0000/azure/complete/
must be str, not NoneType
Request Method: POST
Request URL: http://testdomain.com/project/azure/complete/
Django Version: 2.2.4
Exception Type: TypeError
Exception Value:
must be str, not NoneType
Exception Location: /home/project/app/project/azure_auth/views.py in complete, line 57
Python Executable: /home/project/app/venv/bin/python3
Python Version: 3.6.8
Python Path:
['/home/project/app/project',
'/home/project/app/venv/bin',
'/home/project/app/venv/lib64/python36.zip',
'/home/project/app/venv/lib64/python3.6',
'/home/project/app/venv/lib64/python3.6/lib-dynload',
'/usr/lib64/python3.6',
'/usr/lib/python3.6',
'/home/project/app/venv/lib/python3.6/site-packages']
Server time: Tue, 19 Nov 2019 05:21:10 +0000
/home/project/app/project/azure_auth/views.py in complete
f.write("nonce -->"+nonce+"\n") …
▼ Local vars
Variable Value
backend
<azure_auth.backends.AzureActiveDirectoryBackend object at 0x7f5c688dce80>
data
['82aff4f9-2cc0-4521-aea7-ad3281d20774\n',
'ba821364-86c9-4233-881f-bdc772f7c488\n']
f
<_io.TextIOWrapper name='t1.txt' mode='w' encoding='UTF-8'>
method
'POST'
n
'82aff4f9-2cc0-4521-aea7-ad3281d20774'
nonce
None
original_state
None
request
<WSGIRequest: POST '/project/azure/complete/'>
state
'fd93da6a-9009-4363-9640-9364df7f64df'
token
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkJCOENlRlZxeWFHckdOdWVoSklpTDRkZmp6dyIsImtpZCI6IkJCOENlRlZxeWFHckdOdWVoSklpTDRkZmp6dyJ9.eyJhdWQiOiI0MDMyODJjZi1kYjlmLTQ1OTYtOWM1My0wMmI1MTA2ZDA0MDIiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYmM0OTNhOC0wZDI0LTQ0NTQtYTgxNS1mNGNhNThlOGMwOWQvIiwiaWF0IjoxNTc0MTQwNTY5LCJuYmYiOjE1NzQxNDA1NjksImV4cCI6MTU3NDE0NDQ2OSwiYWlvIjoiNDJWZ1lCQSt4TFhqNEdVTjRRWEJiU3ZOZmF4NXBHY2NPenFoNzFuNDlXMmxnYTYzMjIwQiIsImFtciI6WyJwd2QiXSwiZmFtaWx5X25hbWUiOiJFIEsgUyIsImdpdmVuX25hbWUiOiJTdXNyZWV0aGEiLCJpbl9jb3JwIjoidHJ1ZSIsImlwYWRkciI6IjE4Mi43NS4xNjcuMTg4IiwibmFtZSI6IkUgSyBTLFN1c3JlZXRoYSIsIm5vbmNlIjoiODgyNTg4ZjgtMGM3MC00Y2JlLTk4MTktY2JkNjUyZmI0MDQ5Iiwib2lkIjoiNTU0ZjYzZWEtOTg4Yi00MmMwLTk4NjUtMTIxMDNkZTdhZTBmIiwib25wcmVtX3NpZCI6IlMtMS01LTIxLTYwMzE5MzI1LTExNjA5ODI5NTEtMTYwMTc3MzkwNy02NTg1OTMiLCJzdWIiOiI2aERUa1hYYkN3Wm5rcHEwSU9wRTRVWk56RHZlRFhvVjM3RGV5U3dkaDZRIiwidGlkIjoiZmJjNDkzYTgtMGQyNC00NDU0LWE4MTUtZjRjYTU4ZThjMDlkIiwidW5pcXVlX25hbWUiOiJTRTA3NTA0OEBjZXJuZXIubmV0IiwidXBuIjoiU0UwNzUwNDhAY2VybmVyLm5ldCIsInV0aSI6IkZTQmhnVDg4UTAyUHNfU293ZDdtQUEiLCJ2ZXIiOiIxLjAifQ.Rvc6xcPRZ01iebYtEyAWeyDnQEUVtqV1L1mapr658jLog-_yIASyEm3kMrkt6dIWWEO3dJSe3k05xOJlbnHqcjaR5LKAwOZzGR_oBmyIyB8-IvuEankNVpwYtcz8mY7kFr6AqQmIsx7xLLgv4grp-bSy4eRqjk36VeLX_LwMBuM_U6V70w0gXN1vvFCj0tjsv-VtTAmNgvdxS0ltzdD3rzZ87DoXbPWmoozLtO9WBRsJvMuvn-frBtYUYkIhs3I-eVAO9ZG2IWEuLQx6k7RBmzX6HgFi9SVpyEhNru7fmwO-qj5uRj9FQa45lCZluUV25o_AV1NQ94d5lnFyeMh7uw'
user
None
I got the above error while trying to write the session variables to file (for debugging.)
Upvotes: 3
Views: 3908
Reputation: 101
I know this question is a bit old, but the session won't be able to be retrieved (and with it the original state and nonce), and will fail the comparison if the cookie is not being sent by the browser.
The cookie is not sent by default in django 2.1+, since the default settings add SameSite=Lax
The cookies used for django.contrib.sessions, django.contrib.messages, and Django’s CSRF protection now set the SameSite flag to Lax by default. Browsers that respect this flag won’t send these cookies on cross-origin requests. If you rely on the old behavior, set the SESSION_COOKIE_SAMESITE and/or CSRF_COOKIE_SAMESITE setting to None.
https://docs.djangoproject.com/en/3.0/releases/2.1/#samesite-cookies
In theory this should still send the cookie (from what I understand), but for some reason chrome doesn't seem to. There's something I clearly do not understand, so if anyone knows better please comment.
Anyway, changing the setting via SESSION_COOKIE_SAMESITE = None
should work.
Upvotes: 2