I have inherited a legacy Django application (currently on 2.2.24
), that I am trying to modernize step by step. One requirement is to move from MySQL to an Azure SQL database.
Unfortunately, I ran into an issue, where I just can’t read back the session data from the database!
This is what my settings.py looks like. As you can see, django.contrib.sessions
is set, as well as django.contrib.sessions.middleware.SessionMiddleware
. Also, I have explicitly set SESSION_ENGINE = 'django.contrib.sessions.backends.db'
, which should be the default.
# ...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_swagger',
# ...
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
]
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
]
DATABASES = {
'default': {
'ENGINE': 'mssql', # https://github.com/microsoft/mssql-django
'NAME': '<hiden>',
'USER': '<hiden>',
'PASSWORD': '<hiden>',
'HOST': '<hiden>',
'PORT': '1433,
'OPTIONS': {
'driver': 'ODBC Driver 17 for SQL Server',
}
}
}
# ...
This is what the misbehaving views.py looks like, which is part of an Azure AD login procedure (def auth(request)
=> sso/login
& def complete(request)
=> sso/complete
)
After execution leaves def auth(request)
, I can see a new entry in the table dbo.django_session
. However, when execution enters def complete(request)
, the session dictionary is empty. Also request.session.session_key
doesn’t hold anything. However, I see a session cookie is getting set!!!
@never_cache
def auth(request):
request.session.flush()
nonce = str(uuid.uuid4())
request.session['nonce'] = nonce # store to session db
state = str(uuid.uuid4())
request.session['state'] = state # store to session db
backend = AzureActiveDirectoryBackend()
redirect_uri = AZURE_AD_REDIRECT_URI or request.build_absolute_uri(reverse(complete))
login_url = backend.login_url(
nonce=nonce,
state=state,
redirect_uri=redirect_uri
)
if settings.DEBUG:
print('login_url:', login_url)
return HttpResponseRedirect(login_url)
@never_cache
@csrf_exempt
def complete(request):
backend = AzureActiveDirectoryBackend()
method = 'GET' if backend.RESPONSE_MODE == 'fragment' else 'POST' # form_post / fragment
# EMPTY !!!
s_key = request.session.session_key
keys = request.session.keys()
items = request.session.items()
# EMPTY AS WELL
original_state = request.session.get('state') # dictionary from SessionMiddleware
resp_meta = getattr(request, method) # request.GET / request.POST
state = resp_meta.get('state')
if original_state != state:
return HttpResponse('<h1>State is lost</h1>\n\nRefresh the page (F5).')
if "error" in resp_meta:
return HttpResponse('<h1>%s</h1> \n %s \n\n error_uri:<a>%s</a>' % (
resp_meta['error'], resp_meta['error_description'], resp_meta['error_uri']))
# ...
Other things I have tried without success:
- Starting with a fresh database
- Recreating the
SECRET_KEY
- Calling
request.session.modified = True
- Setting SESSION_CCOKIE_SECURE = False
What is going on here? Any help on this is greatly appreciated!