Thanks, Massimo! I think that retrieving and deleting the token in request.args(0) is just what I needed.
And the @auth.requires_login() was an accidental inclusion of code from when I used basic authentication. I had the API working with basic authentication before I decided to go with token-based authentication. I don't need or intend to use two different authentication methods. Thanks again, Eric On Sep 15, 11:15 pm, Massimo Di Pierro <[email protected]> wrote: > Looking at your code again: > > @auth.requires_login() > def call(token): > row = db(db.subscription.token == token).select().first() > my_number = row.my_calls > if my_number > 0 & my_token == token: > db(db.subscription.token == > my_token).update(my_calls=db.subscription.my_calls-1) > return service() > else: > raise Exception() > > I see two problems: > 1) > you have both @auth.requires_login() which only works if you enable > auth.allow_basic_login = True > and you have token authentication. Are you sure you want two > authentications one on top of the other? > 2) > call is a method and cannot take arguments. > > If your intention is passing the token as request.args(0) simply do: > > def call(): > token = request.args(0) # grab the token > row = db(db.subscription.token == token).select().first() > my_number = row.my_calls > if my_number > 0 & my_token == token: > db(db.subscription.token == > my_token).update(my_calls=db.subscription.my_calls-1) > del request.args[0] # make sure you remove the token else you > may mess-up some services. > return service() > else: > raise Exception() > > On Sep 15, 2:46 pm, Eric <[email protected]> wrote: > > > > > > > > > OK, here's where my background as a non-CS/humanities major starts to > > hurt. I'm trying to implement a token authentication for a web > > service using RPC. I've also developed a sign-up/payment website for > > the web service that uses web2py with auth. I had the service working > > fine using basic authentication, but then I realized that my target > > audience may not always use a client with basic authentication > > enabled, plus a token authentication system offers me other advantages > > that I would like. > > > Anyway, I need advice on where exactly is best to check for the > > token. Intuitively, it seems reasonable to check for the token in the > > call function that I've exposed, but what is confusing me is the fact > > that all the arguments passed by the call go to the decorated RPC > > function that is called. Indeed, when I check the token in the > > exposed call action and use curl to make the call using a valid token, > > I get a "invalid function (api/call)" error. > > > So how would I should I pass a token to the exposed call action in > > addition to passing other arguments to the various linked actions? > > > Or do I need to check for the token inside each of my remote > > procedures? Also, is there a good way to cache the token, or will I > > need to check it on every call? > > > Finally, I had a counter working well with basic authentication to > > limit calls to a certain number per month. I guess if I have to check > > for the token inside each of my remote procedures, then that's also > > where I´ll need to put the counter. This would seem to make for messy > > and repetitive code, but I'm not sure what else to do. > > > Would anyone like to jump in or point me to a pertinent resource? I'd > > be very grateful. Django has a token API plugin > > at:https://github.com/jpulgarin/django-tokenapi/tree/master/tokenapi but > > I'm not able to extrapolate from their plugin to my app. > > > ####### > > #model## > > ################## > > db.define_table('subscription', > > Field('id','id'), > > Field('token', > > label=T('User Token')), > > Field('my_calls', type='integer', default=100, > > label=T('User Calls'),writable=False,readable=False), > > Field('subscription_method', 'reference method', required=True, > > label=T('Subscription Method')), > > Field('is_active','boolean',default=False, > > label=T('Active'),writable=False,readable=False), > > Field('created_on','datetime',default=request.now, > > label=T('Created On'),writable=False,readable=False), > > Field('modified_on','datetime',default=request.now, > > label=T('Modified On'),writable=False,readable=False, > > update=request.now), > > Field('created_by',db.auth_user,default=auth.user_id, > > label=T('Created By'),writable=False,readable=False), > > Field('modified_by',db.auth_user,default=auth.user_id, > > label=T('Modified By'),writable=False,readable=False, > > update=auth.user_id), > > format='%(plan)s', > > migrate=settings.migrate) > > > ############ > > ##controller#### > > # coding: utf8 > > from gluon.tools import Service > > service = Service(globals()) > > > @service.run > > def my_function1(foo,bar): > > ... > > return response.body.getvalue() > > > @service.run > > def my_function2(foo,bar): > > ... > > return response.body.getvalue() > > > @auth.requires_login() > > def call(token): > > row = db(db.subscription.token == token).select().first() > > my_number = row.my_calls > > if my_number > 0 & my_token == token: > > db(db.subscription.token == > > my_token).update(my_calls=db.subscription.my_calls-1) > > return service() > > else: > > raise Exception()

