Given the following code snippet in a controller (default or any other): auth.settings.allow_basic_login = True def howdy(): auth.settings.allow_basic_login = True response.view = 'generic.json' if auth.user: this_user = auth.user.id else: this_user = "unset" return dict(user=this_user) if the controller action is called as such: % curl --user 't...@somewhere.com:supersecretpassword' http://127.0.0.1:8000/myapp/controller/howdy
this response you'll get it this: {"user": "unset"} The same goes for using auth.is_logged_in(): The result is different, however, when you use one of the 'requires' decorators: auth.settings.allow_basic_login = True def howdy(): auth.settings.allow_basic_login = True @auth.requires_login() def proforma(): pass #empty function just to invoke auth.requires proforma() #call empty function response.view = 'generic.json' if auth.user: this_user = auth.user.id else: this_user = "unset" return dict(user=this_user) this results in: % curl --user 't...@somewhere.com:supersecretpassword' http://127.0.0.1:8000/myapp/controller/howdy {"user": 1} After some digging I discovered that in tools.py auth.requires_* ends up calling login_bare which is why the second one works. I realize that according to the book ( http://web2py.com/books/default/chapter/29/9?search=login_bare) login_bare() can be called to login the user "manually". Unfortunately the examples for auth.settings.allow_basic_login in the manual/book (http://web2py.com/books/default/chapter/29/9#Access-Control-and-Basic-Authentication , http://web2py.com/books/default/chapter/29/9#Settings-and-messages , & http://web2py.com/books/default/chapter/29/10#Access-Control) don't address the fact that no login is actually executed without the decorators. With the last example if someone wanted to use that as a guide they might think that changing: @auth.requires_login() @request.restful() def api(): def GET(s): return 'access granted, you said %s' % s return locals() to: @request.restful() def api(): def GET(s): if auth.is_logged_in(): return 'access granted, you said %s' % s else: return 'access denied' return locals() Should work, but they would be mistaken (and likely to spend much time trying to figure out why one worked and the other did not). I don't know whether it was the intention that using basic auth prevent a call to log the user in by default. It seems that either the code should be fixed or we should update the documentation to clarify that login_bare() should be called explicitly (directly or indirectly) to actually execute the login process.