Cycloauth is a project mainly written in Python, based on the MIT license.
OAuth Provider for Cyclone
This is an OAuth 1.0a provider for cyclone It requires oauth2 and is based on wsgioauth.
cycloauth provides:
I am still working on tests and compliancy however am using it for a production project and so it should see regular updates toward supporting various consumer libraries.
This should be done from within a virtualenv
$ git clone git://github.com:/samuraisam/cycloauth
$ cd cycloauth
$ sudo pip install -r requirements.txt
$ sudo pip install -e ./
import cyclone.web, cycloauth.provider
# your application must include the provider mixin
class Application(cyclone.web.Application, cycloauth.provider.OAuthApplicationMixin):
def __init__(self, *args, **kwargs):
handlers = []
# here cycloauth.provider.handlers() takes a dictionary of settings
# I recommend using your global application settings
# we'll leave it blank for now to get something up and running
settings = {'debug': True}
handlers += handlers(settings)
cyclone.web.Application.__init__(self, handlers, **settings)
By default this gives you a few URLs which are overridable in settings (more later):
/oauth/request_token
used by clients to create a request token/oauth/authorize
shown to users in a web browser to request authorization to the client/oauth/access_token
used by clients to acquire an access tokenYou must provide a way to register new consumers with your service. The way in which you implement it is up to you however it must follow this common pattern:
from cyclone.web import RequestHandler
from cycloauth.provider import OAuthRequestHandlerMixin
from twisted.internet import defer
class RegisterApplicationHandler(RequestHandler, OAuthRequestHandlerMixin):
@defer.inlineCallbacks
@cyclone.web.asynchronous
def get(self):
c = yield self.application.oauth_storage.add_consumer()
yield self.application.oauth_storage.save_consumer(c)
self.write(dict(
key=c.key,
secret=c.secret
))
self.finish()
This will generate a new consumer key/secret and save it to the oauth store. Most likely you will also want to store it somewhere in your database attached to another sort of user account.
Protecting a service with OAuth authentication is pretty easy. It is important to note that ALL OAuth protected resources are required to be asynchronous
from cycloauth.provider import OAuthRequestHandlerMixin, oauth_authenticated
from cyclone.web import RequestHandler
class NativeProtectedMethodHandler(RequestHandler, OAuthRequestHandlerMixin):
@oauth_authenticated
def get(self):
self.write('you are authenticated as ' + str(self.oauth_token))
self.write('
you are authenticated using ' + str(self.oauth_consumer))
self.write('
holy protected resources batman!')
self.finish()
You are responsible for pulling other user information from your own database based on the oauth_token
and oauth_consumer
provided on the resource.
The default authorization handler simply generates an oauth_verifier
and redirects back to the application's oauth_callback
url. This is most likely an undesired behavior as the user has no chance to authorize the consumer to their account. In addition, there is no native login process enforced. To create this step you will need to do the following:
oauth_token
query parameterThe example implementation (actually the default one, but you get the idea):
from cyclone.web import RequestHandler
from cycloauth.provider import OAuthRequestHandlerMixin
from twisted.internet import defer
class AuthorizeHandler(RequestHandler, OAuthRequestHandlerMixin):
@defer.inlineCallbacks
@cyclone.web.asynchronous
def get(self):
str_tok = self.oauth_params['oauth_token']
token = yield self.application.oauth_storage.get_request_token(str_tok)
token.set_verifier() # here you can pass your own code to this function
yield self.application.oauth_storage.save_request_token(token)
cb = token.get_callback_url()
self.redirect(cb)
This handler is then provided via the full dot-notated path of the RequestHandler
in your settings:
settings['oauth_authorization_handler'] = 'mypackage.mysubpackage.AuthorizeHandler'
More likely than not in-memory OAuth Token storage will not be suitable for you.