Callback URL trailing slashes, Django 4.2 changed behaviour
In all of our (Both AA and Django-ESI) documentation, we refer to the callback url as being /sso/callback
, however in https://gitlab.com/allianceauth/django-esi/-/blob/master/esi/urls.py?ref_type=heads#L9 re_path(r'^callback/$', views.receive_callback, name='callback'),
we define the url as with a trailing slash
By the good graces of Django and the APPEND_SLASH setting, this silently redirects any /sso/callback
requests to /sso/callback/
https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-APPEND_SLASH
At some point this internal django behaviour has changed, resulting in an actual 404 being thrown and caught by our error handling. https://forum.djangoproject.com/t/getting-a-404-with-redirected-requests-for-append-slash-in-logging-middleware/22722 https://code.djangoproject.com/ticket/33700
This is only interrupts the users login/add token flow when out of debug, which is why it hasnt been caught until now.
See the difference in behaviour in Django 4.0 (AA v3.8.1) and Django 4.2 (AA v4.0.0b1) https://cdn.discordapp.com/attachments/656411889441570826/1210437441555660830/image.png?ex=65ea8eb6&is=65d819b6&hm=2800f08def10463fa7efecd4e00bc48e180d79fc7f40fe2a45c35f3a86b2d00b& https://cdn.discordapp.com/attachments/1105330582042460180/1210433227131588608/image.png?ex=65ea8aca&is=65d815ca&hm=902e84e0b7515d9917ae84794ca15c226acb24bc3fefbecb2595d081179f4df6&
There is a possibility this is related to something else in AA v4.0 that i still need to investigate. but there has also clearly been a change in behaviour in Django for this feature, and on the whole our urls.py doesnt properly represent what we document our callback should be.
We have a few options for minimal impact,
Removing the fullmatch would match against both trailing slash and no slash callbacks (matching both our code and our documentation equally)
urlpatterns = [
re_path(r'^callback', views.receive_callback, name='callback'),
]
Or we accept that trailing slash callbacks were never intentional and it was only a django behaviour that allowed it to work for so long
urlpatterns = [
re_path(r'^callback', views.receive_callback, name='callback'),
]
or simplify it down with the new(er) django path's
urlpatterns = [
path('callback', views.receive_callback, name='callback'),
]