Add next
query param with original request URL in requires decorator
#920
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
Recently when trying to make use of the
redirect
kwarg in therequires
decorator, I was surprised when I lost all information about where the user had been redirected from. I wanted this information so that I could redirect the user back to the original protected URL they had requested after authentication. I wrote a custom decorator to achieve this instead of usingrequires
.If we offer a
redirect
kwarg inside therequires
decorator, we may want the handler receiving the redirect to also be able to discern the original request destination. Otherwise, this information is lost.Changes
This PR modifies the
requires
decorator to add the original request url as a url-encoded query param (example:next=https%3A%2F%2Flocalhost%3A8000%2Fadmin%3Fqparam%3Dtest
) to the redirected request.For comparison, in Django, there's a
next
query param added when you opt to use theirlogin_required
decorator (and in Django it's also possible to select a custom query parameter name different from"next"
as well).Security Concerns
It's possible to deliberately craft malicious URLs with dangerous redirects to give to a known user of an application with weak security around redirects. Most of these considerations fall on the implementer of the handler receiving the redirect.
For instance, there are various attempts to mitigate these problems inside Django's
LoginView
:LoginView
performs the following security checks after successful login but before redirecting the user:next
URL are allowed (same host as initiated the request, for instance).next
is not pointing to the login handler, which would error in the browser with "the page isn't redirecting properly").Note: because Starlette offers no default login handler, we'd have to sternly warn the user not to redirect requests willy-nilly. In other words, we'd probably have to guide users in the docs away from potential security pitfalls and probably provide a sample implementation for them to copy.
Next Steps
We may also consider the following in this PR:
Construct the
next
query param only if a specific keyword argument has been provided to therequires
decorator (probablynext_url_query_param=None
or something like that) instead of always by default (this has the benefit of being backwards compatible as well: existing users would see no change; they'd have to opt-in to adding this kwarg).Provide a sample login handler in the docs that contains some code for validating the
next
url is safe before redirecting users to it.Callout in the docs the potential security pitfalls here.
This PR does not include any of the above because I wanted to present what I have for comment from the maintainers. I could also include one or more of the above changes.
Feedback welcome.