Search code examples
pythonauthenticationcookiespyramid

Get username information from a cookie in Pyramid (Python)


I'm writing a Pyramid app that allows registration of arbitrary number of users in a database table. This is my login code:

@view_config(route_name='login', renderer='templates/login.jinja2')
def login(request):
    username = request.params.get('username', '')
    error = ''
    if request.method == 'POST':
        error = 'Login Failed'
        authenticated = False
        try:
            authenticated = do_login(request)
        except ValueError as e:
            error = str(e)
        if authenticated:
            headers = remember(request, username)
            return HTTPFound(request.route_url('home'), headers=headers)
    return {'error': error, 'username': username}

where

def do_login(request):
    username = request.params.get('username', None)
    password = request.params.get('password', None)
    if not (username and password):
        raise ValueError('both username and password required')
    manager = BCRYPTPasswordManager()
    cur = request.db.cursor()
    try:
        cur.execute("SELECT password FROM users WHERE username=%s", [username])
    except psycopg2.Error:
        raise ValueError("That username already exists!")
    actual_password = cur.fetchall()[0][0]  # Extrrrract the data
    return manager.check(actual_password, password)

I want to display the username on all views once a given user is authenticated. My understanding is that the authentication information is stored in a cookie, and that cookie looks like (auth_tkt=""). How do I get the "current" username from this cookie?

Or am I more confused than I realize?


Solution

  • You can get the authenticated username by calling request.authenticated_userid. You can find more about this in official docs.

    I also tend to store the whole user object (and dbsession) in the request like this:

    def includeme(config):
        from .models.user import User
    
        settings = config.get_settings()
        dbsession_factory = get_dbsession_factory(settings)
        config.add_request_method(
            lambda request: dbsession_factory(),
            'dbsession',
            reify=True)
        config.add_request_method(
            lambda request: User.get_by_username(
                request.dbsession,
                request.authenticated_userid),
            'user',
            reify=True)
    
    def get_dbsession_factory(settings):
        engine = engine_from_config(settings, 'sqlalchemy.')
        dbsession_factory = sessionmaker()
        register(dbsession_factory)
        dbsession_factory.configure(bind=engine)
        return dbsession_factory 
    

    Then you just call config.include('your_app.models') in your app __init__.