Comments (8)
Hi @efojs
You could always set LOGIN_REDIRECT_URL
to redirect the user to another url which runs the extra checks, but this won't work if the user has had the next
query param set when logging in.
With that in mind I really like the idea of being able to run some custom code if the users has been verified, ignoring is next
was set or not.
The issue with using the UserPassesTestMixin
is it causes a redirect on fail. When I first implemented a form of magic link authentication I simply kicked users who failed authentication to the login page but got feedback that it was rather confusing.
There is also the other issue is that it would not be possible to clear out the cookie created when using REQUIRE_SAME_BROWSER
.
What do you think about adding a method onto LoginVerify
which you can extend / override to do other actions? It can default to the current redirect action but you can do something different if you would like?
I'm thinking you would just need to do something like:
class CustomLoginVerify(LoginVerify):
def login_complete_action(self):
user = self.request.user.email
some_additional_activity_or_checks(user)
return redirect_to_say_complete_profile(user)
The LoginVerify
code would probably look something like:
class LoginVerify(TemplateView):
def get(self, request, *args, **kwargs):
...
response = self.login_complete_action(request)
if settings.REQUIRE_SAME_BROWSER:
cookie_name = f'magiclink{magiclink.pk}'
response.delete_cookie(cookie_name, magiclink.cookie_value)
return response
def login_complete_redirect(self, request) -> HttpResponse:
token = request.GET.get('token')
magiclink = MagicLink.objects.get(token=token)
return HttpResponseRedirect(magiclink.redirect_url)
def login_complete_action(self, request) -> HttpResponse:
return self.login_complete_redirect(request)
It will also probably be a good idea to add a new setting which makes it easily change the verify url so it can easily be pointed at a custom LoginVerify.
from django-magiclink.
As I had already done half the work above above, I decided to put the changes in a branch, it would be good to get your feedback @efojs - Especially for the README and if it's clear enough how to implement custom code:
from django-magiclink.
Hi. Thanks for quick response, you are fast) I'll check later today, please don't close it
from django-magiclink.
I'm not sure if I get your plan. But maybe you can get mine)
UserPassesTestMixin
does not necerelly redirect on fail.
It is raise_exception
attribute of AccessMixin
(its parent) being False
on default causes it.
It makes handle_no_permission
method redirect to login page on fail, or raise exception
Depending on the results of test_func
one can either customize handle_no_permission
(e.g. to cleanup cookies in request
) or (as you offer in login_complete_action
) customize get
before returning super
response or redirect to custom path
I mean it looks like you can put your check in test_func
and the rest, if needed, can be handled via mixin's methods — no need for custom methods, flows and paths.
Does it make sense? What am I missing in your approach?
from django-magiclink.
Hey @efojs
I mean it looks like you can put your check in test_func and the rest, if needed, can be handled via mixin's methods — no need for custom methods, flows and paths.
Is there a way to swap the view from LoginVerify
to a custom one without the extra setting and path / urls if we use the UserPassesTestMixin
? Or do you just mean the custom login_complete_action
method isn't needed?
I should note I split login_complete_redirect
and login_complete_action
so if someone wanted to override login_complete_action
but keep the redirect the same they could just call return self.login_complete_redirect()
I believe the issue with your approach is to remove a cookie from the clients machine you need to delete it from a response
object not a request
object.
On top of this the cookie we are trying to clean up is done if the login is successful
(REQUIRE_SAME_BROWSER check).
I wanted to try and make sure my understanding of the flow you are suggesting is correct so I decided to create a new branch which would pass the same tests as the branch I created above.
Most importantly it needs to pass this test - https://github.com/pyepye/django-magiclink/blob/verify-flow/tests/test_login_verify.py#L115 - which both does a custom redirect AND deletes the cookie for a custom verify endpoint..
The diff between the code I suggested above and the UserPassesTestMixin
style (no test changes)
verify-flow...verify-flow-mixin
When overriding the get()
method you would then either be stuck only redirecting to same redirect response as the LoginVerify
get()
which isn't very flexible or you would need to manually add the extra code to delete the cookie which I don't think would be very clear?
For example here is the code required:
Custom method
Test view: https://github.com/pyepye/django-magiclink/blob/verify-flow/tests/urls.py#L17-L21
README: https://github.com/pyepye/django-magiclink/blob/verify-flow/README.md#custom-login-verify-flow
UserPassesTestMixin style
Test view: https://github.com/pyepye/django-magiclink/blob/verify-flow-mixin/tests/urls.py#L17-L34
README: https://github.com/pyepye/django-magiclink/blob/verify-flow-mixin/README.md#custom-login-verify-flow
The UserPassesTestMixin
approach does allow for a custom fail flow using handle_no_permission
but we can easily add a similar method in to match this.
Also as a side point, using the UserPassesTestMixin
isn't semantically correct as we are trying to control authentication to the system where as the Mixin is meant to be for checking access / authorization to a specific view. I don't think this is a reason not to use it if it works though.
Does that make sense at all? Hopefully I've misunderstood you and UserPassesTestMixin
Saying all that, I was hoping the README updates would be enough to show how custom code could be run with my approach but it doesn't seem to be. I'll think about what wording I can add to make it more clear.
from django-magiclink.
Hi! Excuse me for not responding long. I could not wrap my head around it.
And now, when I came with another request, I can't afford posting, until I respond to this, so I wrapped)
And you are right. Because you offer:
- reason of failure, which I can't see how to implement with
test_func()
, - redirecting to another URL, despite it looks wrong place, and for sure it was solved before (to complete profile, accept new version of user agreement or else), but I can't think of any solution (except maybe some kind of
get_success_url()
)
And also I've just realized that I need this solution, because I redirect after callingsuper().get()
(thus not deleting cookie)
So yes, cool, would be glad if you update with it
As for docs/implementation, I think naming is a bit confusing (login_complete_action
, login_complete_redirect
), idk, maybe because English is not my native
In the example you check is_superuser
twice:
if self.request.user.is_superuser:
url = reverse('superuser_page')
elif self.request.user.is_superuser:
...
And not sure if there is a need for MAGICLINK_LOGIN_VERIFY_URL
I mean I use your original names and all works fine
(or why not to customize all names then)
from django-magiclink.
Hi @efojs
I cleaned up the code a little, removed the confusing login_complete_redirect
and fixed the double is_superuser
.
It's also now been merged into master so will be in the next release (which I will do later this evening)
Thanks
Matt
from django-magiclink.
I've created a new release - version 1.1.0 - which has been pushed to Pypi.
from django-magiclink.
Related Issues (14)
- docs email send configuration HOT 1
- don't specify loginverify failed redirect external url HOT 3
- Use the magiclink token in REST calls HOT 2
- Wrong email entered msg and first login redirect
- E-Mail enumeration through the login form
- hashed email instead of plaintext
- can we bump packaging to be above v22 given that it's now v23? HOT 1
- why the missing domain in the signup link? HOT 1
- Refactoring suggestions
- Security HOT 6
- No module named 'packaging' HOT 4
- Anonimize/not store IP addresses HOT 6
- Cookie not deleted with LoginVerify HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-magiclink.