Comments (11)
So, guess the view could use the LOGOUT_REDIRECT_URL Django setting in the event of a failure.
In the events of a success, it could use the LOGIN_REDIRECT_URL or "next".
from django-sesame.
I think that's a valid feature request.
from django-sesame.
Let's go back to the use case in order to clarify the constraints. The goal is to provide an alternative login mechanism via django-sesame, typically for "service account"-style access, when adding the django-sesame middleware isn't desirable.
(Here the reason for not adding the django-sesame middleware is to avoid deploying that login mechanism to all URLs. I see it as a layer of defense-in-depth on top of django-sesame, which is a more risky authentication mechanism.)
For testing purposes, you don't really care about redirecting. Your testing script can simply navigate to the next URL. Redirecting after login is a rats nest — see Django's LoginView
— so I'd rather avoid it.
Your implementation looks correct to me (although I don't understand why you need the if not request.user.is_anonymous
conditional). Here's a slightly more generic version, without redirects (untested):
from http import HTTPStatus
from django.contrib.auth import authenticate, login
from django.http import HttpResponse
from . import settings
def login(request, scope="", max_age=None):
sesame = request.GET.get(settings.TOKEN_NAME)
if sesame is None:
return HttpResponse(
b"login failed: missing token",
content_type="text/plain; charset=utf-8",
status=HTTPStatus.UNAUTHORIZED,
)
user = authenticate(request, sesame=sesame, scope=scope, max_age=max_age)
if user is None:
return HttpResponse(
b"login failed: invalid token",
content_type="text/plain; charset=utf-8",
status=HTTPStatus.FORBIDDEN,
)
login(request, user) # always updates the last login date.
return HttpResponse(status=HTTPStatus.NO_CONTENT)
Going through the higher-level get_user
function isn't really simpler. The primary purpose of get_user
is to update the last login date, but login
does that already, so you have to tell get_user
not to do it. This isn't an improvement over the previous version (untested):
from http import HTTPStatus
from django.contrib.auth import login
from django.http import HttpResponse
from .utils import get_user
def login(request, scope="", max_age=None):
# login(request, user) will update the last login date.
user = get_user(request, update_last_login=False, scope=scope, max_age=max_age)
if user is None:
return HttpResponse(
b"login failed: invalid or missing token",
content_type="text/plain; charset=utf-8",
status=HTTPStatus.FORBIDDEN,
)
login(request, user)
return HttpResponse(status=HTTPStatus.NO_CONTENT)
Probably that solves your use case. However, I'm not sure it's sufficiently widely useful to be provided in django-sesame. For non-scripted use cases, I need to support redirecting to a customizable URL.
from django-sesame.
I agree with you on avoiding get_user().
I understand that many users of django-sesame use it not for functional testing, or to login for dynamic security analysis, but to be able to enable email based login for tickler emails. This reduces the costs of conversions in much the same way as social login does. No one likes it when the first thing an email does is demand that you login.
What about setting that restricts the middleware to work only on certain request PATHs? That is present in django-cas-ng, which is what our federated login uses on-premise (see https://www.danizen.net/anti-social-auth/). This for instance allows login to be restricted to the django admin.
from django-sesame.
Sorry, I meant "a setting" that restricts the middleware, such as SESAME_PATH_STARTS_WITH,
which would default to None. It seems to me that this limits the amount of code surface for you to maintain while also enabling django-sesame to be used out of the box for this use case. To be honest, it is not just my code that restricts this login to a certain subnet - my DevOps does this as a control so that public apps can have "internal-only" URLs - sort as a "technical control" if you speak that compliance/security language.
from django-sesame.
When I first used django-sesame, set_unusable_password
didn't exist, and it wasn't the default. My management commands in the common code that supports my applications probably do not call set_unusable _password
. I will fix that :)
If you do not like the idea of adding a setting like SESAME_PATH_STARTS_WITH
, please go ahead and close with such a comment. If you do like it, I will be happy to craft a pull request or simply wait for you or one of your maintainers/contributers.
from django-sesame.
Yesterday I attempted to clean up how Django implements redirects after login/logout: django/django#15608. This makes it much more realistic to implement a custom login view in django-sesame that redirects securely, by backporting or importing the mixin that I created in this PR. Let's see where that goes.
Then, I've been giving this further thought. Actually, it's a really good issue because it forces a more structured understanding of use cases for django-sesame.
Users may want:
- permanent authentication ("log the user in with django.contrib.auth/sessions") or temporary authentication ("just give me a user for this request")
- global authentication ("every page on the website") or local authentication ("just a few pages")
The corresponding solutions are:
- permanent x global: use the middleware
- permanent x local: this is the feature requested here
- the code samples discussed above support this use case with a dedicated login view
- it would be possible to provide a decorator for this
- pro: it would result in shorter URLs (
/target?sesame=...
instead of/sesame_login?sesame=...&next=%2ftarget
) - con: it would generate security sensitive events (logging in)
as a side-effect of GET requests on regular URLs, reviving some of the concerns with the middleware approach
- pro: it would result in shorter URLs (
- temporary x global: not supported
- I'm not sure about use cases for this; it might be useful if you want short lived authentication (via short lived tokens) anywhere but you don't want to upgrade it to long lived authentication (via sessions); does anyone want this?
- temporary x local: use
user = get_user(request)
- it would be possible to provide a decorator for this
- this raises a few questions e.g. what if another user is already logged in but no obvious blocker
- it would be possible to provide a decorator for this
Long story short, here's one possible plan:
- Restructure README to clarify use cases & appropriate APIs
- Add a login view for the permanent x local use case
- Consider adding a decorator as an alternative solution for the permanent x local use case (= either do it or file an issue for later)
- Consider adding a decorator for the temporary x local use case (same)
from django-sesame.
One thing I didn't address — I dislike the idea of a setting containing of whitelist of URLs; this is too far from the URLconf or the view. I'd rather apply a decorator in the URLconf or directly on the view.
from django-sesame.
I dislike the idea of a setting containing of whitelist of URLs; this is too far from the URLconf or the view. I'd rather apply a decorator in the URLconf or directly on the view.
I see that - spreading it out into middleware, URLconf, and the views undermines the clarity of the code. A security professional might talk about increasing attack surface. I used to advocate that many developers apply security decorators directly in URLconf so that they can validate security in one file - but I found it too convenient personally to do that in the views once I understood "@method_decorator", and also DRF with authentication classes makes that sort of difficult anyway.
from django-sesame.
Hello @danizen, what do you think of #83?
I haven't written the documentation yet; you can look at the tests for intended usage.
from django-sesame.
I should have followed up on this. NIH Central IT created an "Automated Login Utility" which works for both Django and other web frameworks. The way it works is by saving a cookie (which can be moved from the browser to some automated session or used via Selenium so that when Django redirects to the usually interactive federated login, the login flows right through.
This addresses the issue I had. However, I will still try this out and get you feedback.
from django-sesame.
Related Issues (20)
- struct.pack error creating token using custom User model with UUID as pk HOT 1
- Feature: Enforce same session link usage HOT 3
- Documentation: clarify dynamic max_age is ignored with SESAME_MAX_AGE = None (the default) HOT 2
- Discussion: what is the benefit of going through the authentication backend system? HOT 4
- Non existent user ID returned / Security concerns HOT 3
- Authenticate a view without user HOT 2
- Django admin does not log in after adding Middleware HOT 10
- Rename master branch to main HOT 1
- sesame tokens seem to be missing a bunch of entropy on my Django installation (first characters are all 'AAAAAA' HOT 3
- Is ModelBackend actually needed? HOT 2
- Expired Token: enhance user journey HOT 2
- Support changing signature length HOT 1
- Add support for SECRET_KEY_FALLBACKS
- Typo in tutorial for Login by email
- Deprecated dependencies HOT 2
- minimum ua parser version HOT 2
- SESAME_PRIMARY_KEY_FIELD=uuid does not allow login HOT 2
- Add an option to invalidate magic links on email change HOT 4
- override_settings doesn't update sesame settings HOT 6
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-sesame.