Take the 2-minute tour ×

I've been looking for a way to authenticate user by user and password passed in http header.

curl --user user1:pass1 http://localhost:6543/the_resource

The idea is to check if passed credentials allow user to view *the_resource* and if not return 401 - Forbidden.

I've found only examples of authentication policy where there has to be a login and logout view or this basic authentication policy which I don't know how to bind with Pyramid's ACL.

I will appreciate any help, how to start.

One more thing came to my mind. How to force this pup-up login window for basic authentication?

share|improve this question
add comment

2 Answers

In the end it became clear how to use authentication and authorization. Everything was actually written I just didn't catch the concept at once. I'll try to write how I got it working explaining in a noobish way, which I had to explain it to myself. I hope it will be useful to someone. Sources in the end may help to understand my writing ;) All comments are welcome. If I got something wrong, please correct me.


Most important is the basic authentication in which BasicAuthenticationPolicy must have methods that can be used later in pyramid application - like authenticated_userid(request). These methods use _get_basicauth_credentials() which pulls out login and password that were passed in http header. The actual checking if the login and password are correct happens in mycheck().

Now in __init__.py we must add BasicAuthenticationPolicy with method mycheck as an argument to our application configurator, so the pyramid can use it.

In a matter of authentication that is all. Now you should be able if and who was authenticated using authenticated_userid(request) (see views.py)


To use pyramid authorization to resources we need to add ACLAuthorizationPolicy to our configurator in __init__.py and add __acl__ to the resources. In most simple case to the root_factory (see this and this) ACL defines which group has what permission. If I'm not mistaken in (Allow, 'group:viewers', 'view') 'group:viewers' has to be what authentication method - mycheck() - returns.

The last step in authorization is add permission to certain view using a decorator (or in add_route). If we add the ACL permission - view - to a view_page then group:viewers is allowed to see that page (call view_page).


import binascii

from zope.interface import implements

from paste.httpheaders import AUTHORIZATION
from paste.httpheaders import WWW_AUTHENTICATE

from pyramid.interfaces import IAuthenticationPolicy
from pyramid.security import Everyone
from pyramid.security import Authenticated
import yaml

def mycheck(credentials, request):
login = credentials['login']
password = credentials['password']

USERS = {'user1':'pass1',
GROUPS = {'user1':['group:viewers'],

if login in USERS and USERS[login] == password:
    return GROUPS.get(login, [])
    return None

def _get_basicauth_credentials(request):
    authorization = AUTHORIZATION(request.environ)
        authmeth, auth = authorization.split(' ', 1)
    except ValueError: # not enough values to unpack
        return None
    if authmeth.lower() == 'basic':
            auth = auth.strip().decode('base64')
        except binascii.Error: # can't decode
            return None
            login, password = auth.split(':', 1)
        except ValueError: # not enough values to unpack
            return None
        return {'login':login, 'password':password}

    return None

class BasicAuthenticationPolicy(object):
    """ A :app:`Pyramid` :term:`authentication policy` which
    obtains data from basic authentication headers.

    Constructor Arguments


        A callback passed the credentials and the request,
        expected to return None if the userid doesn't exist or a sequence


        Default: ``Realm``.  The Basic Auth realm string.


    def __init__(self, check, realm='Realm'):
        self.check = check
        self.realm = realm

    def authenticated_userid(self, request):
        credentials = _get_basicauth_credentials(request)
        if credentials is None:
            return None
        userid = credentials['login']
        if self.check(credentials, request) is not None: # is not None!
            return userid

    def effective_principals(self, request):
        effective_principals = [Everyone]
        credentials = _get_basicauth_credentials(request)
        if credentials is None:
            return effective_principals
        userid = credentials['login']
        groups = self.check(credentials, request)
        if groups is None: # is None!
            return effective_principals
        return effective_principals

    def unauthenticated_userid(self, request):
        creds = self._get_credentials(request)
        if creds is not None:
            return creds['login']
        return None

    def remember(self, request, principal, **kw):
        return []

    def forget(self, request):
        head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
        return head


from pyramid.config import Configurator
from myproject.resources import Root
from myproject.basic_authentication import BasicAuthenticationPolicy, mycheck
from pyramid.authorization import ACLAuthorizationPolicy

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    config = Configurator(root_factory='myproject.models.RootFactory', 

    config.add_static_view('static', 'myproject:static', cache_max_age=3600)

    config.add_route('view_page', '/view')
    config.add_route('edit_page', '/edit')

    app = config.make_wsgi_app()
    return app


from pyramid.security import Allow

class RootFactory(object):
    __acl__ = [ (Allow, 'group:viewers', 'view'),
                (Allow, 'group:editors', 'edit') ]
    def __init__(self, request):


from pyramid.security import authenticated_userid
from pyramid.view import view_config

#def my_view(request):
#    return render_to_response('templates/simple.pt', {})

@view_config(route_name='view_page', renderer='templates/view.pt', permission='view')
def view_page(request):
    return {}

def edit_page(request):
    return {}    
share|improve this answer
add comment

Well what you are asking for is Basic auth. You linked to the recipe, which you'll want to use. This handles identifying users and computing their principals. Principals are used by the ACL system, along with the permission specified on the view, to determine Allow/Deny access.

I think the trick is figuring out how to handle denying a user access to the resource, which is not enumerated in that recipe. You can do that by providing a custom "Forbidden View" that is invoked on a URL when the view denies access. At which point, Basic states that you provide a challenge to the client.

def forbidden_view(request):
    resp = HTTPUnauthorized()
    resp.www_authenticate = 'Basic realm="Secure Area"'
    return resp

That's untested, but gives you the general idea of how to use a forbidden view. This will challenge the client, and then they are free to make another request (hopefully with credentials) that gets turned into principals that are mapped to the permissions you care about.

share|improve this answer
add comment

Your Answer


