Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limiting the access only to certain views #13

Closed
PetrDlouhy opened this issue Aug 7, 2018 · 7 comments
Closed

Limiting the access only to certain views #13

PetrDlouhy opened this issue Aug 7, 2018 · 7 comments

Comments

@PetrDlouhy
Copy link

Hi,

I wanted to implement scenario, where user gets access only to one view through the e-mail and is then able to set only few things on that view. I use django-sesame for generating the key, and I have following code for the views:

class SesameUserMixin():
    def get_object(self):
        backend = ModelBackend()
        self.token = self.request.GET['url_auth_token']
        user = backend.parse_token(self.token)
        if user is None:
            raise PermissionDenied("bad token")
        return user

    def get_success_url(self):
        return "%s?url_auth_token=%s" % (super().get_success_url(), self.token)

Do you think, that such thing should be part of django-sesame and it's documentation? Should I make PR from this?

I am also considering if it is possible (and advisable) to sign the view name or url into the token and then. Then it would be possible to create tokens valid only for certain views (and possibly it's parameters).

@aaugustin
Copy link
Owner

Do you have the django-sesame middleware enabled?

If you do, then I don't think you need that code:

  • get_object could simply return self.request.user
  • you don't need to preserve the token in the URL; the logged in user is already preserved in the session

If you want to have different access depending on whether the user authenticated with a sesame token or with a login and password, I think you should listen to the user_logged_in signal and record in the session which backend was used for authenticating. Then your views can check this value in the session.

@danizen
Copy link

danizen commented Sep 4, 2018

@aaugustin, I have a similar use-case, where I only want the alternative login to work an a particular URL, and I protect that URL from certain remote IP addresses. I use this only to allow AppScan and developers to login to the system.

My code for this view is as follows:

class SesameLoginView(View):
    """
    Login using Django sesame to save on middleware overhead and restrict IP
    """

    @method_decorator(remote_ip_permitted(remote_ips=['130.14.160.', '130.14.15.165', '130.14.16.166', '130.14.16.167']))
    def get(self, request, *args, **kwargs):
        token = request.GET.get(TOKEN_NAME)
        if token is None:
            return HttpResponseRedirect('/')

        user = authenticate(url_auth_token=token)
        if user is not None:
            login(request, user)
            if not request.user.is_anonymous:
                messages.add_message(request, messages.SUCCESS, 'Login succeeded. Welcome, %s' % user.nih_login_id)

        return HttpResponseRedirect('/')

Obviously, including this view would require a little more engineering - the decorator is specific to my use case because our Network Engineers use X-Forwarded-For-IPV6 rather than X-Forwarded-For, and so my decorators and such have evolved over time.

After my lightning talk at DjangoCon 2016 - https://danizen.net/anti-social-auth/, I discovered that AppScan is not permitted to go to the IP address for NIH wide login. I've handled that badly so far - most of our software engineers just as appsec to run their scans, but I want to run my own. django-sesame may be the answer, but having a view based login is 100% required.

@aaugustin
Copy link
Owner

If I understood correctly, these are slightly different use cases:

  • @PetrDlouhy wants to enable login to specific views with a token, but not to persist authentication with django.contrib.auth and django.contrib.sessions, because logging in with a token is considered less trusted than logging in with credentials. However I'm not sure I understood what would be needed there and what changes in django-sesame would make that use case easier.

  • @danizen wants login to kick in only on specific views (instead of all views with a middleware) and then to persist authentication. The easiest way to do this may be to subclass the django-sesame middleware as follows:

class InternalAuthenticationMiddleware(sesame.middleware.AuthenticationMiddleware):

    # If you're using new-style middleware (settings.MIDDLEWARE)

    def __call__(self, request):
        if remote_ip(request) in TRUSTED_REMOTE_IPS:
            return super().__call__(request)

    # If you're using old-style middleware (settings.MIDDLEWARE_CLASSES)

    def process_request(self, request):
        if remote_ip(request) in TRUSTED_REMOTE_IPS:
            return super().process_request(request)

@PetrDlouhy
Copy link
Author

PetrDlouhy commented Sep 8, 2018

@aaugustin Yes, I would like to login on specific views without allowing the user anywhere else, and it works with current django-sesame code. I only have to add the SesameUserMixin and not activate sesame.middleware.AuthenticationMiddleware and sesame.backends.ModelBackend.

So the simplest way to add support for this use-case into django-sesame would be adding the mixin to the code and documenting the usage. Although this basic support could be quite limiting - it would be nice if the the token could be associated with specific view, so different views couldn't be accessed by same token.

@aaugustin
Copy link
Owner

I've been looking at this again today.

I think that your use cases are a bit narrow to warrant first-class support in django-sesame and that I should document the APIs you need to implement them.

As far as I can tell, I just have to document authenticate(url_auth_token=token) — that is, that the django-sesame authentication backend accepts an url_auth_token argument.

Everything else is just standard django.contrib.auth stuff.

aaugustin added a commit that referenced this issue May 1, 2019
This makes it easier to use django-sesame without the middleware.

Documentation coming in the next commit.

Ref #13.
@aaugustin
Copy link
Owner

I believe that https://github.com/aaugustin/django-sesame#per-view-authentication does what you want. Please let me know if it doesn't!

@aaugustin
Copy link
Owner

First class support will be available in version 3.0 with the authenticate decorator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants