[Checkins] SVN: zope.app.openidconsumer/trunk/ Rough (really rough) draft of an OpenID consumer.
Shane Hathaway
shane at hathawaymix.org
Mon Feb 23 18:45:57 EST 2009
Log message for revision 97184:
Rough (really rough) draft of an OpenID consumer.
Changed:
A zope.app.openidconsumer/trunk/
A zope.app.openidconsumer/trunk/bootstrap.py
A zope.app.openidconsumer/trunk/buildout.cfg
A zope.app.openidconsumer/trunk/setup.py
A zope.app.openidconsumer/trunk/src/
A zope.app.openidconsumer/trunk/src/zope/
A zope.app.openidconsumer/trunk/src/zope/__init__.py
A zope.app.openidconsumer/trunk/src/zope/app/
A zope.app.openidconsumer/trunk/src/zope/app/__init__.py
A zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/
A zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/__init__.py
A zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/authentication.py
A zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/configure.zcml
A zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/interfaces.py
A zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/register.py
A zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/view.py
-=-
Added: zope.app.openidconsumer/trunk/bootstrap.py
===================================================================
--- zope.app.openidconsumer/trunk/bootstrap.py (rev 0)
+++ zope.app.openidconsumer/trunk/bootstrap.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 96548 2009-02-14 21:07:51Z shane $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+ ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+ cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+ os.P_WAIT, sys.executable, sys.executable,
+ '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+ dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)
Added: zope.app.openidconsumer/trunk/buildout.cfg
===================================================================
--- zope.app.openidconsumer/trunk/buildout.cfg (rev 0)
+++ zope.app.openidconsumer/trunk/buildout.cfg 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,23 @@
+[buildout]
+develop = .
+parts = test python coverage-test coverage-report
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zope.app.openidconsumer
+
+[python]
+recipe = zc.recipe.egg
+eggs = zope.app.openidconsumer
+interpreter = python
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = zope.app.openidconsumer
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')
Added: zope.app.openidconsumer/trunk/setup.py
===================================================================
--- zope.app.openidconsumer/trunk/setup.py (rev 0)
+++ zope.app.openidconsumer/trunk/setup.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+from setuptools import setup, find_packages
+
+setup(name='zope.app.openidconsumer',
+
+ # Fill in project info below
+ version='0.1',
+ description="",
+ long_description="",
+ keywords='',
+ author='',
+ author_email='',
+ url='',
+ license='',
+ # Get more from http://www.python.org/pypi?%3Aaction=list_classifiers
+ classifiers=['Programming Language :: Python',
+ 'Environment :: Web Environment',
+ 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application',
+ 'Framework :: Zope3',
+ ],
+
+ packages=find_packages('src'),
+ package_dir = {'': 'src'},
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=['setuptools',
+ 'python-openid',
+ 'ZODB3',
+ 'zope.app.component',
+ 'zope.app.security',
+ 'zope.component',
+ 'zope.traversing',
+ 'zope.interface',
+ 'zope.location',
+ 'zope.publisher',
+ 'zope.session',
+ 'zope.security',
+ 'zope.formlib',
+ 'zope.schema',
+ ],
+ )
Added: zope.app.openidconsumer/trunk/src/zope/__init__.py
===================================================================
--- zope.app.openidconsumer/trunk/src/zope/__init__.py (rev 0)
+++ zope.app.openidconsumer/trunk/src/zope/__init__.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,7 @@
+# this is a namespace package
+try:
+ import pkg_resources
+ pkg_resources.declare_namespace(__name__)
+except ImportError:
+ import pkgutil
+ __path__ = pkgutil.extend_path(__path__, __name__)
Added: zope.app.openidconsumer/trunk/src/zope/app/__init__.py
===================================================================
--- zope.app.openidconsumer/trunk/src/zope/app/__init__.py (rev 0)
+++ zope.app.openidconsumer/trunk/src/zope/app/__init__.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,7 @@
+# this is a namespace package
+try:
+ import pkg_resources
+ pkg_resources.declare_namespace(__name__)
+except ImportError:
+ import pkgutil
+ __path__ = pkgutil.extend_path(__path__, __name__)
Added: zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/__init__.py
===================================================================
--- zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/__init__.py (rev 0)
+++ zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/__init__.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1 @@
+# Make this directory a package
Added: zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/authentication.py
===================================================================
--- zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/authentication.py (rev 0)
+++ zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/authentication.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,156 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+from urllib import quote_plus
+
+from openid.consumer.consumer import Consumer
+from openid.consumer.consumer import SUCCESS
+from openid.store.memstore import MemoryStore
+from persistent import Persistent
+from persistent.mapping import PersistentMapping
+from zope.app.component.hooks import getSite
+from zope.app.security.interfaces import PrincipalLookupError
+from zope.component import getMultiAdapter
+from zope.traversing.browser import absoluteURL
+from zope.interface import implements
+from zope.location import Location
+from zope.publisher.interfaces import Redirect
+from zope.session.interfaces import ISession
+from zope.security.interfaces import IPrincipal
+
+from zope.app.openidconsumer.interfaces import AuthenticationFailed
+from zope.app.openidconsumer.interfaces import IOpenIDConsumer
+
+PACKAGE = 'zope.app.openidconsumer'
+PRINCIPAL = 'principal'
+CONSUMER = 'consumer'
+
+store = MemoryStore()
+
+
+class OpenIDPrincipal(object):
+ implements(IPrincipal)
+
+ description = u"User authenticated via OpenID"
+
+ def __init__(self, principal_id):
+ self.id = self.title = principal_id
+
+
+class OpenIDConsumer(Persistent, Location):
+ implements(IOpenIDConsumer)
+
+ identity_provider = None
+
+ def authenticate(self, request):
+ """Identify a principal for a request.
+
+ If a principal can be identified, then return the
+ principal. Otherwise, return None.
+ """
+ #if not IBrowserRequest.providedBy(request):
+ # raise NotImplementedError(
+ # "only browser requests are supported by OpenIDConsumer")
+ session = ISession(request)[PACKAGE]
+ return session.get(PRINCIPAL, None)
+
+ def _get_consumer(self, request):
+ session = ISession(request)[PACKAGE]
+ consumer_session_data = session.get(CONSUMER)
+ if consumer_session_data is None:
+ consumer_session_data = PersistentMapping()
+ session[CONSUMER] = consumer_session_data
+ else:
+ consumer_session_data._p_changed = True
+ return Consumer(consumer_session_data, store)
+
+ def _get_view_url(self, request, name):
+ site = getSite()
+ base = absoluteURL(site, request)
+ res = "%s/@@openid/%s" % (base, name)
+ next_url = request.get('nextURL')
+ if next_url:
+ res += '?nextURL=' + quote_plus(next_url)
+ return res
+
+ def login(self, request, identity_url=None):
+ if self.identity_provider:
+ # override
+ identity_url = self.identity_provider
+ if identity_url:
+ consumer = self._get_consumer(request)
+ auth_req = consumer.begin(identity_url)
+ site = getSite()
+ realm = absoluteURL(site, request)
+ url = auth_req.redirectURL(
+ realm, self._get_view_url(request, 'complete'))
+ else:
+ url = self._get_view_url(request, 'choose_identity')
+ request.response.redirect(url)
+
+ def complete(self, request):
+ app_url = self._get_view_url(request, 'complete')
+ consumer = self._get_consumer(request)
+ resp = consumer.complete(request.form, app_url)
+ if resp.status != SUCCESS:
+ raise AuthenticationFailed(resp)
+ else:
+ session = ISession(request)[PACKAGE]
+ session[PRINCIPAL] = OpenIDPrincipal(resp.identity_url)
+ next_url = request.get('nextURL')
+ if not next_url:
+ next_url = absoluteURL(getSite(), request)
+ request.response.redirect(next_url)
+
+ def unauthenticatedPrincipal(self):
+ """Return the unauthenticated principal, if one is defined.
+
+ Return None if no unauthenticated principal is defined.
+
+ The unauthenticated principal must be an IUnauthenticatedPrincipal.
+ """
+ return None
+
+ def unauthorized(self, principal_id, request):
+ """Signal an authorization failure.
+
+ This method is called when an auhorization problem
+ occurs. It can perform a variety of actions, such
+ as issuing an HTTP authentication challenge or
+ displaying a login interface.
+
+ Note that the authentication utility nearest to the
+ requested resource is called. It is up to
+ authentication utility implementations to
+ collaborate with utilities higher in the object
+ hierarchy.
+
+ If no principal has been identified, id will be
+ None.
+ """
+ self.login(request)
+
+ def getPrincipal(self, id):
+ """Get principal meta-data.
+
+ Returns an object of type IPrincipal for the given principal
+ id. A PrincipalLookupError is raised if the principal cannot be
+ found.
+
+ Note that the authentication utility nearest to the requested
+ resource is called. It is up to authentication utility
+ implementations to collaborate with utilities higher in the
+ object hierarchy.
+ """
+ raise PrincipalLookupError()
Added: zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/configure.zcml
===================================================================
--- zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/configure.zcml (rev 0)
+++ zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/configure.zcml 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,79 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="zope"
+ >
+
+ <class class=".authentication.OpenIDConsumer">
+ <require
+ permission="zope.ManageSite"
+ interface=".interfaces.IOpenIDConsumerConfig"
+ set_schema=".interfaces.IOpenIDConsumerConfig"
+ />
+ <require
+ permission="zope.ManageServices"
+ attributes="registrationManager"
+ />
+ </class>
+
+ <browser:addform
+ schema=".interfaces.IOpenIDConsumerConfig"
+ label="Add OpenID Consumer"
+ content_factory=".authentication.OpenIDConsumer"
+ name="AddOpenIDConsumer"
+ permission="zope.ManageServices"
+ >
+
+ <browser:widget
+ field="identity_provider"
+ class="zope.app.form.browser.TextWidget"
+ required="False"
+ convert_missing_value="False"
+ />
+
+ </browser:addform>
+
+ <browser:addMenuItem
+ class=".authentication.OpenIDConsumer"
+ view="AddOpenIDConsumer"
+ title="OpenID Authentication Consumer"
+ description="Consumer of OpenID authentication services"
+ permission="zope.ManageServices"
+ />
+
+ <browser:page
+ for=".interfaces.IOpenIDConsumerConfig"
+ name="addRegistration.html"
+ permission="zope.ManageSite"
+ class=".register.Registration"
+ />
+
+ <browser:editform
+ schema=".interfaces.IOpenIDConsumerConfig"
+ label="Edit OpenID Authentication Consumer"
+ name="configure"
+ menu="zmi_views" title="Configure"
+ permission="zope.ManageServices"
+ />
+
+ <browser:view
+ name="openid"
+ for="zope.location.interfaces.ISite"
+ permission="zope.Public"
+ class=".view.OpenIDView"
+ >
+ <browser:page
+ name="choose_identity"
+ attribute="choose_identity"
+ />
+ <browser:page
+ name="login"
+ attribute="login"
+ />
+ <browser:page
+ name="complete"
+ attribute="complete"
+ />
+ </browser:view>
+
+</configure>
Added: zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/interfaces.py
===================================================================
--- zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/interfaces.py (rev 0)
+++ zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/interfaces.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+from zope.app.security.interfaces import IAuthentication
+from zope.interface import Interface
+from zope.schema import URI
+
+class IOpenIDConsumerConfig(Interface):
+ identity_provider = URI(
+ title=u'Identity Provider URI',
+ required=False
+ )
+
+class IOpenIDConsumer(IOpenIDConsumerConfig, IAuthentication):
+ pass
+
+class AuthenticationFailed(Exception):
+ """OpenID authentication failed"""
Added: zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/register.py
===================================================================
--- zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/register.py (rev 0)
+++ zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/register.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,22 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+
+from zope.app.openidconsumer.interfaces import IOpenIDConsumer
+from zope.app.component.browser.registration import AddUtilityRegistration
+
+class Registration(AddUtilityRegistration):
+ label = u"Register an OpenID authentication utility"
+ name = ''
+ provided = IOpenIDConsumer
Added: zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/view.py
===================================================================
--- zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/view.py (rev 0)
+++ zope.app.openidconsumer/trunk/src/zope/app/openidconsumer/view.py 2009-02-23 23:45:56 UTC (rev 97184)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+
+from zope.component import getUtility
+from zope.formlib.form import action
+from zope.formlib.form import Fields
+from zope.formlib.form import Form
+from zope.interface import Interface
+from zope.publisher.browser import BrowserView
+from zope.schema import TextLine
+
+from zope.app.openidconsumer.interfaces import IOpenIDConsumer
+
+
+class IChooseIdentitySchema(Interface):
+ url = TextLine(title=u'OpenID URL')
+
+class ChooseIdentityForm(Form):
+ label = u'OpenID Login'
+ form_fields = Fields(IChooseIdentitySchema)
+
+ @action(u"Login")
+ def login(self, action, data):
+ auth = getUtility(IOpenIDConsumer, context=self)
+ auth.login(self.request, data['url'])
+
+
+class OpenIDView(BrowserView):
+
+ def choose_identity(self):
+ return ChooseIdentityForm(self.context, self.request)()
+
+ def login(self):
+ auth = getUtility(IOpenIDConsumer, context=self)
+ auth.login(self.request)
+
+ def complete(self):
+ auth = getUtility(IOpenIDConsumer, context=self)
+ auth.complete(self.request)
+
More information about the Checkins
mailing list