I've just implemented an authentication mechanism in Kay framework for Google Apps MarketPlace. So let me introduce how to deploy a marketplace application with Kay(repository version).
I have made a few more improvements in authentication system of Kay Framework, so I slightly change this article at 4:20PM on May 13th 2010JST.
1. Create an app-id
In this example, I've created a brand new application slot called 'marketplace-app'.
2. Register a listing on the MarketPlace
Firstly, you need to register yourself as a MarketPlace Vendor.
http://www.google.com/enterprise/marketplace/
Click a link 'Become a vendor' in the bottom of the page above and you'll get an instruction.
Actually you need to click a link 'Sign in' at top-right corner of the page above, and fill the form.
Then, you can create your listing. Click a button 'Create a new listing' in your Vendor Profile page.
In this example, lets create an installable app, so check the first checkbox 'My product may be directly installed into Google Apps domains'.
You can fill other fields arbitrarily except for the field 'Manifest'.
Manifest xml here:
<?xml version="1.0" encoding="UTF-8" ?> <ApplicationManifest xmlns="http://schemas.google.com/ApplicationManifest/2009"> <!-- Support info to show in the marketplace & control panel --> <Support> <!-- URL for application setup as an optional redirect during the install --> <Link rel="setup" href="https://marketplace-app.appspot.com/a/${DOMAIN_NAME}/setup" /> <!-- URL for application configuration, accessed from the app settings page in the control panel --> <Link rel="manage" href="https://marketplace-app.appspot.com/a/${DOMAIN_NAME}/admin" /> <!-- URL explaining how customers get support. --> <Link rel="support" href="https://marketplace-app.appspot.com/a/${DOMAIN_NAME}/support" /> <!-- URL that is displayed to admins during the deletion process, to specify policies such as data retention, how to claim accounts, etc. --> <Link rel="deletion-policy" href="https://marketplace-app.appspot.com/deletion-policy" /> </Support> <!-- Name and description pulled from message bundles --> <Name>Marketplace sample application</Name> <Description>A simple application for the marketplace</Description> <!-- Show this link in Google's universal navigation for all users --> <Extension id="navLink" type="link"> <Name>Sample</Name> <Url>https://marketplace-app.appspot.com/a/${DOMAIN_NAME}/start</Url> <!-- This app also uses the Calendar API --> <Scope ref="calendarFeed"/> </Extension> <!-- Declare our OpenID realm so our app is white listed --> <Extension id="realm" type="openIdRealm"> <Url>https://marketplace-app.appspot.com/</Url> </Extension> <!-- Need access to the Calendar feed --> <Scope id="calendarFeed"> <Url>https://www.google.com/calendar/feeds/</Url> <Reason>This application shows the next Calendar event.</Reason> </Scope> </ApplicationManifest>
In this example, there is a calendar feed setting for 2 legged OAuth access scope. For more details with a Manifest file format, please see:
http://code.google.com/googleapps/marketplace/manifest.html
After adding your listings, you will see a preview page for your app. There is an attractive 'Add it now' button on the right, but of course, you need to implement your application before adding this app.
Instead, click a link 'My Vendor Profile' on the top-right corner and you can see your listings with a link 'View OAuth Consumer Key'.
3. Implementation
Let's create a new project with Kay management script:
$ python /some/where/kay/manage.py startproject marketplace-app Running on Kay-0.10.0 Finished creating new project: marketplace-app. $ cd marketplace-app $ python manage.py startapp core
settings.py:
INSTALLED_APPS = ( 'core', 'kay.ext.gaema', ) APP_MOUNT_POINTS = { 'core': '/', } MIDDLEWARE_CLASSES = ( 'kay.sessions.middleware.SessionMiddleware', 'kay.auth.middleware.AuthenticationMiddleware', ) AUTH_USER_BACKEND = "kay.auth.backends.gaema.GAEMABackend" GAEMA_USER_MODEL = "core.models.User" GAEMA_SECRETS = { 'google_consumer_key': 'your consumer key here', 'google_consumer_secret': 'your consumer key secret here', } IS_MARKETPLACE_APP = True
Replace GAEMA_SECRETS with actual values. You can see consumer key and consumer key secret with clicking the link 'View OAuth Consumer Key' mentioned above. The last attribute 'IS_MARKETPLACE_APP' is important for this authentication system work normaly.
core/models.py:
# -*- coding: utf-8 -*- # core.models from google.appengine.ext import db from kay.ext.gaema.models import GAEMAUser # Create your models here. class User(GAEMAUser): pass
Information of users will be stored into this model.
core/urls.py:
# -*- coding: utf-8 -*- # core.urls # from kay.routing import ( ViewGroup, Rule ) view_groups = [ ViewGroup( Rule('/a/<domain_name>/setup', endpoint='domain_setup', view='core.views.domain_setup'), Rule('/a/<domain_name>/admin', endpoint='domain_admin', view='core.views.domain_admin'), Rule('/a/<domain_name>/support', endpoint='domain_support', view='core.views.domain_support'), Rule('/a/<domain_name>/start', endpoint='domain_start', view='core.views.domain_start'), Rule('/deletion_policy', endpoint='deletion_policy', view='core.views.deletion_policy'), ) ]
core/views.py:
# -*- coding: utf-8 -*- """ core.views """ from werkzeug import ( unescape, redirect, Response, ) from kay.utils import render_to_response from kay.ext.gaema.utils import get_gaema_user from kay.auth.decorators import login_required def index(request): return render_to_response('core/index.html', {'message': 'Hello'}) def domain_setup(request, domain_name): callback = request.args.get('callback') if callback is None: return Response("No callback supplied.") return redirect(callback) def domain_admin(request, domain_name): return Response("%s administration." % domain_name) def domain_support(request, domain_name): return Response("%s support." % domain_name) def deletion_policy(request): return Response("Deletion policy.") @login_required def domain_start(request, domain_name): return Response("%s start.\n%s" % (domain_name, request.user.raw_user_data))
A decorator 'login_required' takes care of OpenID/OAuth stuff, so you don't need to do anything at all. The user information is in request.user.raw_user_data.
Let's deploy it to appspot.
$ python manage.py appcfg update
You can check the application with visiting https://marketplace-app.appspot.com/a/example.com/start where example.com should be replaced with your actual domain. This domain must be registered with Google Apps and make sure that "Federated Login using OpenID" is turned on.
If the app is successfully deployed, you can see an OpenID authentication display. Let's move on.
4. Add your app to your domain
Go back to your Vendor Profile Page, and click your application title, then you will see the preview page of your application.
Let's click 'Add it now' button on the right, and enter your google apps domain, and click 'Go'.
Follow an adding application wizard like 1) Agree to terms 2) Grant data access 3) External configuration 4) Enable the app, and wait for a while, and you can see a universal navigation link 'Sample' on the top left corner of your google apps applications.
If you click the link, you can silently signed into your application because Marketplace apps are whitelisted with a particular openid_realm.
In part 2 of this article, I'll show you how to access user's calendar data with gdata library.
To be continued..
4 comments:
excellent , thanks for the tutorial. waiting for oauth tutorial. -- you may want to add http://blog.notdot.net/2009/11/Enforcing-data-isolation-with-CurrentUserProperty
for marketplace too.
Thanks for this post. Was able to add my marketplace ... can see myappengineapp.appspot.com/a/mymarketplaceapp.com/[setup,admin] urls working fine. When I go to myappengineapp.appspot.com/a/mymarketplaceapp.com/start I get an error .. mentioned below ..
Traceback (most recent call last):
File "/base/data/home/apps/myappengineapp/1.341913087607156776/kay/app.py", line 339, in get_response
response = view_func(request, **values)
File "/base/data/home/apps/myappengineapp/1.341913087607156776/kay/utils/decorators.py", line 39, in __call__
return self.decorator(self.func)(*args, **kwargs)
File "/base/data/home/apps/myappengineapp/1.341913087607156776/kay/ext/gaema/decorators.py", line 48, in inner
nexturl=request.url))
File "/base/data/home/apps/myappengineapp/1.341913087607156776/kay/ext/gaema/utils.py", line 35, in create_marketplace_login_url
return url_for("gaema/marketplace_login", domain=domain)
File "/base/data/home/apps/myappengineapp/1.341913087607156776/kay/utils/__init__.py", line 110, in url_for
force_external=external)
File "/base/data/home/apps/myappengineapp/1.341913087607156776/kay/lib/werkzeug/routing.py", line 1409, in build
raise BuildError(endpoint, values, method)
BuildError: ('gaema/marketplace_login', {'domain': u'mymarketplaceapp.com'}, None)
Please bear with me ... new with kay framework. Have some django experience.
Does this error means that I am missing the template files.
The code is running using the latest code from trunk.
Please suggest.
Ignore my previous post ... forgot to add kay.ext.gemma in the apps ...
Very good stuff. Liked both Kay and what you have done with marketplace integration ... can't wait for your next post.
Thanks for the comments.
Actually, after I wrote the article, I made few more improvements in marketplace authentication with Kay framework.
So, I'll write a revised version of the same article before we go further into OAuth stuff.
Post a Comment