Skip to content Skip to sidebar Skip to footer

Pyramid.security: Is Getting User Info From A Database With Unauthenticated_userid(request) Really Secure?

I'm trying to make an accesible cache of user data using Pyramid doc's 'Making A “User Object” Available as a Request Attribute' example. They're using this code to return a u

Solution 1:

The unauthenticated_userid call is a cheaper call; it looks up the user id from the request without going through the whole authentication process again.

The key concept there is the word again. You should only use the method in views that have already been authorized. In other words, by the time you reach code that uses unauthenticated_userid you've already verified the user, and specifically do not want to do this again for this particular call.

Authenticating users against a backend persistent storage can be expensive, especially if such a storage doesn't support caching. The unauthenticated_userid API method is an optimization where the request is basically your userid cache.

Solution 2:

This is a late reply but it was linked as a source of confusion for some users of Pyramid.

The accepted answer here is not the actual reason that unauthenticated_userid is used for request.user. It has nothing to do with performance.

The reason that it uses unauthenticated_userid is because it makes it easier to reuse the authentication policy between applications with smaller modifications required. Your application needs a "source of truth" for whether the user is allowed to be considered authenticated and usually the policy's internal logic is not enough to make this determination. A valid cookie is nice, but you usually want to verify it with your backend before trusting it. Great, so where do we put that logic? Well unauthenticated_userid doesn't make sense because it is the reusable part of the policy that focuses specifically on parsing the request headers. You could put it into authenticated_userid but this method is not the one you normally care about in your application. You normally use request.user in your apps (rarely do you probably care about request.authenticated_userid directly) and lastly the request.user is a superset of functionality - it provides an entire user object, not just an id. It would be silly to verify the id without verifying the entire object in most cases. We can only have one "source of truth" and so the recipe declares it to be request.user. The groupfinder (and thus authenticated_userid) can now depend on request.user and trust that what it gets back from there has been properly verified with the backend. Also request.user is already reified and thus speeds up subsequent calls to request.authenticated_userid naturally.

Solution 3:

Looks like Martijn Pieters is right.

My micro benchmark to test this (in my project I use Redis as DB for users and everything else):

print ('start test')
t1 = time()
authenticated_userid(self.request)
print ('authenticated: ' + str(time()-t1))
t1 = time()
unauthenticated_userid(self.request)
print ('unauthenticated: ' + str(time()-t1))
print ('test_stop')

Results:

start test
REDIS AUTH! # <-- actually this is query to groups finder in Redisauthenticated: 0.00032901763916unauthenticated: 7.31945037842e-05
test_stop

It was tested for few times, results are constant :) Do you think I should add Martijn's answer to that article in Pyramid docs to make things more 'clear'? :)

Post a Comment for "Pyramid.security: Is Getting User Info From A Database With Unauthenticated_userid(request) Really Secure?"