Skip to content
This repository has been archived by the owner on Jun 29, 2019. It is now read-only.

Commit

Permalink
Merge pull request #42 from wndhydrnt/tornado_server
Browse files Browse the repository at this point in the history
Tornado Web Server
  • Loading branch information
wndhydrnt committed May 16, 2015
2 parents 3005bf6 + bb9bffe commit 1976ffc
Show file tree
Hide file tree
Showing 30 changed files with 788 additions and 487 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
## 0.8.0 (unreleased)
## 1.0.0 (unreleased)

Features:

- Logging support ([@wndhydrnt][])
- Each grant accepts its own site adapter (see [Migration notes](http://python-oauth2.readthedocs.org/en/latest/migration.html)) ([@wndhydrnt][])
- [Tornado](http://www.tornadoweb.org/) adapter

Improvements:

- Catch unexpected exceptions and respond with a OAuth2 'server_error' ([@wndhydrnt][])
- Declare optional dependencies in setup.py ([@wndhydrnt][])
- Move WSGI server code into its own module ([@wndhydrnt][])
- Renamed class acting as entrypoint for WSGI server from 'Server' to 'Application' ([@wndhydrnt][])

Bugfixes:

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014 Markus Meyer
Copyright (c) 2015 Markus Meyer

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down
20 changes: 11 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ Example Authorization server
import oauth2.error
import oauth2.store.memory
import oauth2.tokengenerator
import oauth2.web
import oauth2.web.wsgi
# Create a SiteAdapter to interact with the user.
# This can be used to display confirmation dialogs and the like.
Expand Down Expand Up @@ -72,38 +73,39 @@ Example Authorization server
client_store.add_client(client_id="abc", client_secret="xyz",
redirect_uris=["http://localhost/callback"])
site_adapter = ExampleSiteAdapter()
# Create an in-memory storage to store issued tokens.
# LocalTokenStore can store access and auth tokens
token_store = oauth2.store.memory.TokenStore()
# Create the controller.
auth_controller = oauth2.Provider(
provider = oauth2.Provider(
access_token_store=token_store,
auth_code_store=token_store,
client_store=client_store,
token_generator=oauth2.tokengenerator.Uuid4()
)
site_adapter = ExampleSiteAdapter()
# Add Grants you want to support
auth_controller.add_grant(oauth2.grant.AuthorizationCodeGrant(site_adapter=site_adapter))
auth_controller.add_grant(oauth2.grant.ImplicitGrant(site_adapter=site_adapter))
provider.add_grant(oauth2.grant.AuthorizationCodeGrant(site_adapter=site_adapter))
provider.add_grant(oauth2.grant.ImplicitGrant(site_adapter=site_adapter))
# Add refresh token capability and set expiration time of access tokens
# to 30 days
auth_controller.add_grant(oauth2.grant.RefreshToken(expires_in=2592000))
provider.add_grant(oauth2.grant.RefreshToken(expires_in=2592000))
# Wrap the controller with the Wsgi adapter
app = oauth2.web.Wsgi(server=auth_controller)
app = oauth2.web.wsgi.Application(provider=provider)
if __name__ == "__main__":
httpd = make_server('', 8080, app)
httpd.serve_forever()
This example only shows how to instantiate the server.
It is not a working example as a client app is missing. Take a look at the
`examples <examples/>`_ directory.
`examples <docs/examples/>`_ directory.

Supported storage backends
**************************
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

# General information about the project.
project = u'python-oauth2'
copyright = u'2013, Markus Meyer'
copyright = u'2015, Markus Meyer'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Expand Down Expand Up @@ -93,7 +93,7 @@

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
html_theme = 'sphinx_rtd_theme'

# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
from multiprocessing.process import Process
from wsgiref.simple_server import make_server, WSGIRequestHandler

sys.path.insert(0, os.path.abspath(os.path.realpath(__file__) + '/../../'))
sys.path.insert(0, os.path.abspath(os.path.realpath(__file__) + '/../../../'))

from oauth2 import Provider
from oauth2.error import UserNotAuthenticated
from oauth2.store.memory import ClientStore, TokenStore
from oauth2.tokengenerator import Uuid4
from oauth2.web import Wsgi, AuthorizationCodeGrantSiteAdapter
from oauth2.web import AuthorizationCodeGrantSiteAdapter
from oauth2.web.wsgi import Application
from oauth2.grant import AuthorizationCodeGrant


Expand Down Expand Up @@ -102,7 +103,7 @@ def __init__(self):

def __call__(self, env, start_response):
if env["PATH_INFO"] == "/app":
status, body, headers = self._serve_application()
status, body, headers = self._serve_application(env)
elif env["PATH_INFO"] == "/callback":
status, body, headers = self._read_auth_token(env)
else:
Expand Down Expand Up @@ -142,6 +143,11 @@ def _read_auth_token(self, env):
print("Receiving authorization token...")

query_params = urlparse.parse_qs(env["QUERY_STRING"])

if "error" in query_params:
location = "/app?error=" + query_params["error"][0]
return "302 Found", "", {"Location": location}

self.auth_token = query_params["code"][0]

print("Received temporary authorization token '%s'" % (self.auth_token,))
Expand All @@ -160,7 +166,13 @@ def _request_auth_token(self):

return "302 Found", "", {"Location": location}

def _serve_application(self):
def _serve_application(self, env):
query_params = urlparse.parse_qs(env["QUERY_STRING"])

if ("error" in query_params
and query_params["error"][0] == "access_denied"):
return "200 OK", "User has denied access", {}

if self.access_token is None:
if self.auth_token is None:
return self._request_auth_token()
Expand Down Expand Up @@ -191,16 +203,16 @@ def run_auth_server():

token_store = TokenStore()

auth_controller = Provider(
provider = Provider(
access_token_store=token_store,
auth_code_store=token_store,
client_store=client_store,
token_generator=Uuid4())
auth_controller.add_grant(
provider.add_grant(
AuthorizationCodeGrant(site_adapter=TestSiteAdapter())
)

app = Wsgi(server=auth_controller)
app = Application(provider=provider)

httpd = make_server('', 8080, app, handler_class=OAuthRequestHandler)

Expand All @@ -227,4 +239,4 @@ def sigint_handler(signal, frame):
signal.signal(signal.SIGINT, sigint_handler)

if __name__ == "__main__":
main()
main()
72 changes: 72 additions & 0 deletions docs/examples/base_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from wsgiref.simple_server import make_server
import oauth2
import oauth2.grant
import oauth2.error
import oauth2.store.memory
import oauth2.tokengenerator
import oauth2.web.wsgi


# Create a SiteAdapter to interact with the user.
# This can be used to display confirmation dialogs and the like.
class ExampleSiteAdapter(oauth2.web.AuthorizationCodeGrantSiteAdapter,
oauth2.web.ImplicitGrantSiteAdapter):
def authenticate(self, request, environ, scopes):
# Check if the user has granted access
if request.post_param("confirm") == "confirm":
return {}

raise oauth2.error.UserNotAuthenticated

def render_auth_page(self, request, response, environ, scopes):
response.body = '''
<html>
<body>
<form method="POST" name="confirmation_form">
<input type="submit" name="confirm" value="confirm" />
<input type="submit" name="deny" value="deny" />
</form>
</body>
</html>'''
return response

def user_has_denied_access(self, request):
# Check if the user has denied access
if request.post_param("deny") == "deny":
return True
return False

# Create an in-memory storage to store your client apps.
client_store = oauth2.store.memory.ClientStore()
# Add a client
client_store.add_client(client_id="abc", client_secret="xyz",
redirect_uris=["http://localhost/callback"])

site_adapter = ExampleSiteAdapter()

# Create an in-memory storage to store issued tokens.
# LocalTokenStore can store access and auth tokens
token_store = oauth2.store.memory.TokenStore()

# Create the controller.
provider = oauth2.Provider(
access_token_store=token_store,
auth_code_store=token_store,
client_store=client_store,
token_generator=oauth2.tokengenerator.Uuid4()
)

# Add Grants you want to support
provider.add_grant(oauth2.grant.AuthorizationCodeGrant(site_adapter=site_adapter))
provider.add_grant(oauth2.grant.ImplicitGrant(site_adapter=site_adapter))

# Add refresh token capability and set expiration time of access tokens
# to 30 days
provider.add_grant(oauth2.grant.RefreshToken(expires_in=2592000))

# Wrap the controller with the Wsgi adapter
app = oauth2.web.wsgi.Application(provider=provider)

if __name__ == "__main__":
httpd = make_server('', 8080, app)
httpd.serve_forever()
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import os
import sys
import urllib
import urlparse
import json
import signal

from multiprocessing.process import Process
from wsgiref.simple_server import make_server, WSGIRequestHandler

sys.path.insert(0, os.path.abspath(os.path.realpath(__file__) + '/../../'))
sys.path.insert(0, os.path.abspath(os.path.realpath(__file__) + '/../../../'))

from oauth2 import Provider
from oauth2.error import UserNotAuthenticated
from oauth2.store.memory import ClientStore, TokenStore
from oauth2.tokengenerator import Uuid4
from oauth2.web import Wsgi
from oauth2.web.wsgi import Application
from oauth2.grant import ClientCredentialsGrant


class OAuthRequestHandler(WSGIRequestHandler):
"""
Request handler that enables formatting of the log messages on the console.
Expand Down Expand Up @@ -44,7 +41,7 @@ def run_auth_server():
token_generator=token_gen)
auth_controller.add_grant(ClientCredentialsGrant())

app = Wsgi(server=auth_controller)
app = Application(provider=auth_controller)

httpd = make_server('', 8080, app, handler_class=OAuthRequestHandler)

Expand Down
11 changes: 6 additions & 5 deletions examples/implicit_grant.py → docs/examples/implicit_grant.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
from multiprocessing import Process
from wsgiref.simple_server import make_server

sys.path.insert(0, os.path.abspath(os.path.realpath(__file__) + '/../../'))
sys.path.insert(0, os.path.abspath(os.path.realpath(__file__) + '/../../../'))

from oauth2 import Provider
from oauth2.error import UserNotAuthenticated
from oauth2.web import Wsgi, ImplicitGrantSiteAdapter
from oauth2.web import ImplicitGrantSiteAdapter
from oauth2.web.wsgi import Application
from oauth2.tokengenerator import Uuid4
from oauth2.grant import ImplicitGrant
from oauth2.store.memory import ClientStore, TokenStore
Expand Down Expand Up @@ -123,14 +124,14 @@ def run_auth_server():

token_store = TokenStore()

auth_server = Provider(
provider = Provider(
access_token_store=token_store,
auth_code_store=token_store,
client_store=client_store,
token_generator=Uuid4())
auth_server.add_grant(ImplicitGrant(site_adapter=TestSiteAdapter()))
provider.add_grant(ImplicitGrant(site_adapter=TestSiteAdapter()))

app = Wsgi(server=auth_server)
app = Application(provider=provider)

httpd = make_server('', 8080, app)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
from urllib2 import HTTPError
from wsgiref.simple_server import make_server

sys.path.insert(0, os.path.abspath(os.path.realpath(__file__) + '/../../'))
sys.path.insert(0, os.path.abspath(os.path.realpath(__file__) + '/../../../'))

from oauth2.compatibility import parse_qs, urlencode
from oauth2 import Provider
from oauth2.error import UserNotAuthenticated
from oauth2.store.memory import ClientStore, TokenStore
from oauth2.tokengenerator import Uuid4
from oauth2.web import Wsgi, ResourceOwnerGrantSiteAdapter
from oauth2.web import ResourceOwnerGrantSiteAdapter
from oauth2.web.wsgi import Application
from oauth2.grant import ResourceOwnerGrant


Expand Down Expand Up @@ -187,17 +188,17 @@ def run_auth_server():

token_store = TokenStore()

auth_controller = Provider(
provider = Provider(
access_token_store=token_store,
auth_code_store=token_store,
client_store=client_store,
token_generator=Uuid4())

auth_controller.add_grant(
provider.add_grant(
ResourceOwnerGrant(site_adapter=TestSiteAdapter())
)

app = Wsgi(server=auth_controller)
app = Application(provider=provider)

httpd = make_server('', 8080, app)

Expand Down

0 comments on commit 1976ffc

Please sign in to comment.