selectively requiring login

41 views
Skip to first unread message

Larry Martell

unread,
Aug 1, 2016, 12:18:44 PM8/1/16
to django...@googlegroups.com
I have a view that is accessed both from the browser and from a
non-browser app. The request from the non browser app come from a
remote app where the user has already had to login (or they would
never get to the point where they could cause the request to be sent).
Is there a way to make login required when the request comes from a
browser but then not have login required when the request comes from
the app?

ludovic coues

unread,
Aug 1, 2016, 1:53:45 PM8/1/16
to django...@googlegroups.com
You could use an alternative way to login the user, transparent to the
user. Like giving a token to the app when it login.
> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CACwCsY6a3XNa1%2BUxqWVX0xht-H2Lx%2BkHzqq1D1S%2B%2Be-S6ZMfWA%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.



--

Cordialement, Coues Ludovic
+336 148 743 42

Larry Martell

unread,
Aug 1, 2016, 2:07:42 PM8/1/16
to django...@googlegroups.com
The problem is selectively bypassing or overriding the @login_required
decorator. The view is called from an endpoint that has that decorator
on it.

Michal Petrucha

unread,
Aug 1, 2016, 2:35:33 PM8/1/16
to django...@googlegroups.com
That sounds like a bad idea. Even with the “app”, when a request is
being made, the user has to be authenticated somehow. If you allow
your “app” to access the view without authentication (regardless of
what criterion you pick to determine it is the “app”, be it the
user-agent, referrer, or whatnot), what's to prevent a motivated
attacker from finding the criterion out using a sniffing proxy or some
other tool, and just making the request directly?

Cheers,

Michal
signature.asc

James Schneider

unread,
Aug 1, 2016, 3:05:37 PM8/1/16
to django...@googlegroups.com
On Mon, Aug 1, 2016 at 11:33 AM, Michal Petrucha <michal....@koniiiik.org> wrote:
On Mon, Aug 01, 2016 at 12:17:38PM -0400, Larry Martell wrote:
> I have a view that is accessed both from the browser and from a
> non-browser app. The request from the non browser app come from a
> remote app where the user has already had to login (or they would
> never get to the point where they could cause the request to be sent).
> Is there a way to make login required when the request comes from a
> browser but then not have login required when the request comes from
> the app?

That sounds like a bad idea. Even with the “app”, when a request is

+100
 

being made, the user has to be authenticated somehow. If you allow
your “app” to access the view without authentication (regardless of
what criterion you pick to determine it is the “app”, be it the
user-agent, referrer, or whatnot), what's to prevent a motivated
attacker from finding the criterion out using a sniffing proxy or some
other tool, and just making the request directly?


+100

Your end-users (regular browser sessions) and apps using API calls should probably be using a separate URL structure. In most cases the API calls have a unique identifier in the path such as being prepended with '/api/' and are often followed by a version number ('/api/v1/') to maintain compatibility with concurrent API versions.

While it is a terrible idea to have an authenticated and non-authenticated URL for the same resource (or set of resources), you can easily achieve this by having separate URL's for your browser sessions vs. API calls, and performing the login decoration on the browser URL in the urls.py file rather than decorating the view directly. The URL for the API call would not be decorated and can be accessed without requiring a login, but both URL's would point at the same view.

My advice is not to do that, though. 

You should heavily consider either having your app be authenticated (login and grab a session token via your API), or provide an API token to the local app that is associated with the user you want. The latter will require some extra infrastructure. 

The alternative is to not have the user log in no matter how they are accessing the URL. If it works without logging in, and there are no resources to protect, that sounds like the way to go. With the implementation you've indicated, you'll be asking for trouble operationally later when your view is expecting a user object, but it doesn't get one. Means more complexity for no appreciable gain. 

You can also implement some sort of SSO implementation (Shibboleth, CAS, OAuth, etc.) that can be used by both regular browser sessions and your custom application.

-James

Larry Martell

unread,
Aug 1, 2016, 3:40:40 PM8/1/16
to django...@googlegroups.com
I understand and know all that. The situation is that they have an existing django app. Nothing in the app can be accessed without logging in. Then they have an in house developed non browser client app and they want to access some of the functionality from the django app in the other app. When the other app comes up they do have to logi in and I do use the django auth system for that. But when a request comes in from the app there is nothing to tie it back to the previously authorized session. Is there something from the initial auth I can use to get past the @login_required decorator on the views? 

ludovic coues

unread,
Aug 1, 2016, 4:13:40 PM8/1/16
to django...@googlegroups.com
The session cookie ?

Or you could use another decorator or a middle-ware doing
authentication based on the ip and some information passed as get
argument. Like a token returned by django when you auth the user.

The request hit the new decorator, the decorator notice the user isn't
logged in and that it provide a token. It check if the token match a
recently logged in user and its ip and maybe the user-agent. If that's
the case, log the user in and let the request hit the @login_required
decorator.

If you don't simply reuse the session cookie, I would spend some time,
listening with wireshark and messing with a browser, checking that I
am not opening a hole.
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/CACwCsY4rN4i_bruDHnt24BNJNGFLCCBRH-N2uvn4ap%3DOUCqx2A%40mail.gmail.com.

Larry Martell

unread,
Aug 1, 2016, 5:17:58 PM8/1/16
to django...@googlegroups.com
How do I get the session cookie from the login and then how do I pass it in the subsequent request? 
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAEuG%2BTbEtZ17sYPWM2683aLC5%3DVV%2BVxCGvCbTr-F0gFV-32N-g%40mail.gmail.com.

Michal Petrucha

unread,
Aug 1, 2016, 5:20:00 PM8/1/16
to django...@googlegroups.com
On Mon, Aug 01, 2016 at 10:12:53PM +0200, ludovic coues wrote:
> The session cookie ?
>
> Or you could use another decorator or a middle-ware doing
> authentication based on the ip and some information passed as get
> argument. Like a token returned by django when you auth the user.

Using the IP address to authenticate a user (even if it's just one of
several signals) sounds like a bad idea, particularly when mobile
devices are involved – it is very common for a phone to switch back
and forth between a wifi connection, and a cellular connection, which
most of the time means switching to a different IP, or even an
entirely different ISP.

Also, passing authentication tokens inside the URI issomething that's
generally better avoided – what if there's some caching proxy
somewhere in between which would cache the full URL, including the
authentication token?

I would strongly recommend using one of the standard authentication
mechanisms instead of trying to roll your own custom solution for
authentication. If it is possible to use the session cookie, then by
all means do that. Otherwise you might want to investigate some form
of token-based authentication, maybe even something based on OAuth, or
perhaps JWT. The Django REST framework, for example, gives you many
options, both built-in, as well as popular third-party extensions.

Cheers,

Michal
signature.asc
Reply all
Reply to author
Forward
0 new messages