JSON response on auth.settings.on_failed_authentication with @request.restful()

80 views
Skip to first unread message

Henry Nguyen

unread,
Sep 4, 2014, 1:32:54 PM9/4/14
to
I have a method decorated with the following decorators:

@request.restful()
@auth.requires_login()


On an unauthenticated (non-logged-in) request, I get a 403 response with "Not authorized" in the response body, as expected per default settings. I would like to be able to modify this response to be JSON. I've tried modifying the following auth.settings as follows:

def json_response():
   
import json
   
raise HTTP(403, json.dumps(dict(content='Not authorized')))

auth
.settings.on_failed_authentication = json_response
auth
.settings.on_failed_authorization = json_response


However, I continue to receive the "Not authorized" string in the response to the RESTful method instead of the JSON. Upon further digging, I found line 3448 in gluon/tools.py with the following:

elif self.settings.allow_basic_login_only or \
        basic_accepted
or current.request.is_restful:
   
raise HTTP(403, "Not authorized")


It seems like methods with the @request.restful() decorator simply cannot be overridden to return a custom response on unauthenticated requests, at least without modifying tools.py. Is this correct?

Thanks ahead of time for any help.



Leonel Câmara

unread,
Sep 4, 2014, 1:38:06 PM9/4/14
to web...@googlegroups.com
Why? Why don't you simply analyse the HTTP return code where you're calling the API?

Henry Nguyen

unread,
Sep 4, 2014, 1:45:37 PM9/4/14
to
Primarily because I would like to display custom messages sent from the API, and I want them controllable from the API side. Specifically, our UI framework has a feature built in which allows us to display custom messages from the API by specifying the message characteristics in the response body. These characteristics need to be in JSON.

We can specify the messages on other authenticated requests and have them display fine, but we'd prefer to not have to make a custom case for handling these non-JSON unauthenticated requests.

Leonel Câmara

unread,
Sep 4, 2014, 2:17:47 PM9/4/14
to web...@googlegroups.com
Ohh, in this case, instead of modifying tools.py I would drop the auth.requires_login() decorator and use auth.is_logged_in to check inside the function. Something like:


@request.restful()
def api():
    def GET(*args,**vars):
        return dict()
    def POST(*args,**vars):
        return dict()
    def PUT(*args,**vars):
        return dict()
    def DELETE(*args,**vars):
        return dict()
    
    if not auth.is_logged_in():
        raise HTTP(403, YOUR_JSON_ERROR)
    return locals()


Henry Nguyen

unread,
Sep 4, 2014, 2:22:41 PM9/4/14
to web...@googlegroups.com
That is definitely a viable option... not as clean as the decorator but certainly functional. Thank you Leonel :)

Henry

Henry Nguyen

unread,
Sep 4, 2014, 2:50:02 PM9/4/14
to web...@googlegroups.com
Just for posterity's sake, I put the check into a custom decorator and used that new decorator instead:

def requires_login(function):

   
def check_is_logged_in(*args, **kwargs):
       
if not auth.is_logged_in():
           
raise HTTP(401, json.dumps(dict(content='Unauthorized.')))
       
return function(*args, **kwargs)

   
return check_is_logged_in


@request.restful()
@requires_login
def function():
   
...

Thanks again for the help, Leonel.

Henry
Reply all
Reply to author
Forward
0 new messages