AuthTktAuthenticationPolicy with custom Session objects

171 views
Skip to first unread message

Ben Sizer

unread,
Jun 19, 2012, 8:38:35 PM6/19/12
to pylons-discuss
I have written my own Session object, based on the example Pyramid 1.3
provides, but with my own persistence mechanism - all well and good (I
think). In the cookie I store a key into my database, so that I can
retrieve persistent session info.

Now I'd like to implement authorization, so that I can show different
content to different authenticated users. So I looked at the
authentication policy docs and then at the AuthTktAuthenticationPolicy
and associated classes. They appear to also read and write a cookie,
and it seems like there is a large amount of overlap with the session
code. It's not clear if the two peacefully co-exist, or whether they
should be rolled into one object.

I figure I can use different cookie names in each case, but it seems
to be duplicating effort and increasing the chance of bugs, eg. if one
cookie expires when the other is valid, etc. I had imagined that I
would have 1 session object, linked to a single cookie. That session
would have a current_user() method or similar which would retrieve the
user from the database, based on a user ID stored in the session.

Basically, I don't know how to use these 2 things together - the doc
page on Sessions has nothing to say about auth or about security
(apart from the warning about the unencrypted session type) and the
page on Security says nothing about sessions. I could probably write
my own AuthenticationPolicy that queries my Session object but that
would involve it setting cookie headers which would interfere with
that Session.

How should I proceed?

--
Ben Sizer

Chris McDonough

unread,
Jun 19, 2012, 9:18:03 PM6/19/12
to pylons-...@googlegroups.com

Michael Merickel

unread,
Jun 20, 2012, 1:04:00 AM6/20/12
to pylons-...@googlegroups.com
In the event that your Session object you keep referring to isn't
integrated into Pyramid's `request.session`, then a) you should look
into doing that (link below) and then use the
SessionAuthenticationPolicy as Chris suggested or b) you should just
write your own authentication policy that uses your Session object.

http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/sessions.html#creating-your-own-session-factory
> --
> You received this message because you are subscribed to the Google Groups
> "pylons-discuss" group.
> To post to this group, send email to pylons-...@googlegroups.com.
> To unsubscribe from this group, send email to
> pylons-discus...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/pylons-discuss?hl=en.
>

Ben Sizer

unread,
Jun 20, 2012, 10:07:52 AM6/20/12
to pylons-...@googlegroups.com
I have set up my Session object the usual way, via a session factory, etc.

SessionAuthenticationPolicy looks like exactly what I need, but are there any examples of its use? It would be handy to know where it pulls userids from, for example. Also it seems to want to be reading and writing auth values to the session itself, so does that affect how I have mark a user as logged in?

I'd also like to know whether there is any support for getting an automatically populated User object, eg. "request.current_user", although if necessary I'm happy to do this manually in each view.

--
Ben Sizer
> To post to this group, send email to pylons-discuss@googlegroups.com.
> To unsubscribe from this group, send email to
> pylons-discuss+unsubscribe@googlegroups.com.

Chris McDonough

unread,
Jun 20, 2012, 10:33:15 AM6/20/12
to pylons-...@googlegroups.com
On 06/20/2012 10:07 AM, Ben Sizer wrote:
> I have set up my Session object the usual way, via a session factory, etc.
>
> SessionAuthenticationPolicy looks like exactly what I need, but are
> there any examples of its use? It would be handy to know where it pulls
> userids from, for example. Also it seems to want to be reading and
> writing auth values to the session itself, so does that affect how I
> have mark a user as logged in?

See the "callback" argument to its constructor. It's meant to be a
function that accepts a user id and returns one of:

- A sequence of group ids

- An empty sequence (no groups associated with the user)

- None

If it returns None, it means that the userid doesn't exist in the
database. If it returns a sequence (either empty or populated), it
means the user exists in the database.

How you implement the callback is up to you. If you don't implement the
callback, the userid is taken from the session without any checking.

See either of the two tutorials in
http://docs.pylonsproject.org/projects/pyramid_tutorials/en/latest/wiki_tutorials.html
for examples of how Pyramid security works. It's irrelevant which
authentication policy is in use, all of them work more or less the same.

http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/auth/wiki2_auth.html
has a more detailed description of how security works in the wiki2 tutorial.

> I'd also like to know whether there is any support for getting an
> automatically populated User object, eg. "request.current_user",
> although if necessary I'm happy to do this manually in each view.

http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/auth/user_object.html
> pylons-...@googlegroups.com
> <mailto:pylons-...@googlegroups.com>.
> > To unsubscribe from this group, send email to
> > pylons-discus...@googlegroups.com
> <mailto:pylons-discuss%2Bunsu...@googlegroups.com>.
> > For more options, visit this group at
> > http://groups.google.com/group/pylons-discuss?hl=en
> <http://groups.google.com/group/pylons-discuss?hl=en>.
> >
>
> --
> You received this message because you are subscribed to the Google
> Groups "pylons-discuss" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/pylons-discuss/-/-I5cRbkh8i0J.
> To post to this group, send email to pylons-...@googlegroups.com.
> To unsubscribe from this group, send email to
> pylons-discus...@googlegroups.com.

Ben Sizer

unread,
Jun 21, 2012, 10:15:27 AM6/21/12
to pylons-...@googlegroups.com
On Wednesday, 20 June 2012 15:33:15 UTC+1, Chris McDonough wrote:
On 06/20/2012 10:07 AM, Ben Sizer wrote:
> I have set up my Session object the usual way, via a session factory, etc.
>
> SessionAuthenticationPolicy looks like exactly what I need, but are
> there any examples of its use? It would be handy to know where it pulls
> userids from, for example. Also it seems to want to be reading and
> writing auth values to the session itself, so does that affect how I
> have mark a user as logged in?

See the "callback" argument to its constructor.  It's meant to be a
function that accepts a user id and returns one of:

- A sequence of group ids

- An empty sequence (no groups associated with the user)

- None

If it returns None, it means that the userid doesn't exist in the
database.  If it returns a sequence (either empty or populated), it
means the user exists in the database.

How you implement the callback is up to you.

Thanks Chris. My issue was about what all that stuff means though - for example, I didn't know what 'user id' means in this context, whether it was something specific to Pyramid, whether I get any control over what that type is, etc. It isn't clear in the docs where the system gets this value from, so it's hard to know what you would compare it to. But I think I worked out that it's an arbitrary type which you pass in via remember().

Similarly, I don't have user groups in my system so when you say "a sequence of group ids" it's a bit confusing, as are several references to 'groupfinder' functions in examples and code. I am just returning the original user_id wrapped in a list, and that seems to work.

As I understand it, the system works somewhat like this:

  - to log in, your app must check the credentials, and then stores a user id in the Authentication policy via the 'remember' function.
  - the SessionAuthenticationPolicy implements remember() via storing that user id in the current session;
  - if you use unauthenticated_userid() in your app, SessionAuthenticationPolicy will pull that user id value back from the session;
  - if you use authenticated_userid() in your app, it'll call the callback you specified for the Authentication policy to check that the user id still exists before returning it;
  - to log out, your app removes the user id from the session via the 'forget' function.

Is that about right? I'm still a bit fuzzy on what exactly a principal means, but from a quick look at the code I think I can ignore most of that since I never call effective_principals() and don't currently need to support groups of users.

One more thing is that I don't fully understand is the use of forget() and session.invalidate(). I would like to be able to clear the cookie and destroy the server-side data at the same time when logging out - should I just call forget followed by invalidate(), and keep all cookie-related information out of invalidate()?

--
Ben Sizer

Jonathan Vanasco

unread,
Jun 21, 2012, 10:22:56 AM6/21/12
to pylons-discuss
if you're using beaker sessions:

session.invalidate() leaves the cookie, but kills the server side
data associated with it.
session.kill() kills the cookie, but a new session/session_id/
cookie is created.

i'm not sure what the other session backings do.

fwiw, I was just as confused as you with the various pyramid auth
mechanisms. i also realized that they would take quite a bit of
integration work ( to handle caching, etc ) -- so i just wrote my own
auth system. i use some custom decorators :

@require_logged_in( require_https=True,
require_permissions=[list,of], etc )
@require_logged_out()

and just bypass all the pyramid auth.
Reply all
Reply to author
Forward
0 new messages