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()

Reply via email to