EngineAuth: Multi-Provider Authentication for App Engine
EngineAuth is a standardized approach to third party authentication / authorization, designed to be as simple as possible, both for the developer and the end user.
Disclaimer
Warning
EngineAuth is in the very early stages of development and the api is likely to change frequently and in non-backwards compatible ways. Please provide any issues, suggestions, or general feedback through the Issue Tracker, or in the comments section of this documentation.
Demo
EngineAuth Example - Example site
How it Works
Note
If you are unable to view the above image. Please log into your Google Docs account, or log out of Google altogether. There's currently a Google Docs bug that requires a user to be sign in to Google Docs to view public content.
Supported Strategies & Providers
New strategies will be written as needed. If there's a particular strategy that your interested in please create a new issues using the strategy request label.
OAuth
OAuth2
OpenID Provider
- All - via App Engine OpenID
Email & Password
If the provider that you need isn't provided not to worry, adding additional providers is simple, and in many cases only requires a few lines of code.
Requirements
- Google App Engine running Python 2.7
Installation
Copy the engineauth
directory and the contents of lib
directory to your project's root
directory.
Dependencies
- oauth2client - Required for OAuth2 Strategies
- httplib2 - Required for OAuth and OAuth2 Strategies
- uri-templates - Required for OAuth and OAuth2 Strategies
- python-gflags - Required for OAuth and OAuth2 Strategies
- python-oauth2 - Required for OAuth Strategies
Configuring EngineAuth
In your appengine_config.py
add:
def webapp_add_wsgi_middleware(app): from engineauth import middleware return middleware.AuthMiddleware(app) engineauth = { 'secret_key': 'CHANGE_TO_A_SECRET_KEY', 'user_model': 'engineauth.models.User', } engineauth['provider.auth'] = { 'user_model': 'engineauth.models.User', 'session_backend': 'datastore', } # Facebook Authentication engineauth['provider.facebook'] = { 'client_id': 'CHANGE_TO_FACEBOOK_APP_ID', 'client_secret': 'CHANGE_TO_FACEBOOK_CLIENT_SECRET', 'scope': 'email', } # Google Plus Authentication engineauth['provider.google'] = { 'client_id': 'CHANGE_TO_GOOGLE_CLIENT_ID', 'client_secret': 'CHANGE_TO_GOOGLE_CLIENT_SECRET', 'api_key': 'CHANGE_TO_GOOGLE_API_KEY', 'scope': 'https://www.googleapis.com/auth/plus.me', } # Twitter Authentication engineauth['provider.twitter'] = { 'client_id': 'CHAGNE_TO_TWITTER_CONSUMER_KEY', 'client_secret': 'CHAGNE_TO_TWITTER_CONSUMER_SECRET', }
Acquiring Client Keys
- Go to: https://developers.facebook.com/apps
- Select your application
- Under
Select how your app integrates with Facebook
clickWebsite
. In theSite URL:
field enter your domain E.g. http://example.com/ or http://localhost:8080/ be sure to include the closing/
. - Copy
App ID/API Key
asclient_id
- Copy
App Secret
asclient_secret
Note
Zuckerberg won't allow you to specify multiple callback domains for a single application. So for development you must create a separate application. Then, in your appengine_config.py
you can specify which config will be loaded at runtime.
import os ON_DEV = os.environ.get('SERVER_SOFTWARE', '').startswith('Dev') if ON_DEV: # Facebook settings for Development FACEBOOK_APP_KEY = 'DEVELOPMENT_APP_KEY' FACEBOOK_APP_SECRET = 'DEVELOPMENT_APP_SECRET' else: # Facebook settings for Production FACEBOOK_APP_KEY = 'PRODUCTION_APP_KEY' FACEBOOK_APP_SECRET = 'PRODUCTION_APP_SECRET' engineauth['provider.facebook'] = { 'client_id': FACEBOOK_APP_KEY, 'client_secret': FACEBOOK_APP_SECRET, 'scope': 'email', }
Google Plus
- Go to: https://code.google.com/apis/console
- Select your application or create a new one.
- Choose
API Access
- Click
Create an OAuth 2.0 client ID..
- Enter Product name -> Next
- Select
Web application
- Under
Your site or host
select(more options)
- Under
Authorized Redirect URIs
add your domain name followed by/auth/google/callback
E.g.http://localhost:8080/auth/google/callback
,http://YOUR_DOMAIN.COM/auth/google/callback
- Click
Create client ID
- Copy
Client ID
asclient_id
- Copy
Client secret
asclient_secret
- Enable Google+ API in the console.
- Go to: https://dev.twitter.com/apps
- Select your application or create a new one.
- Make sure the you set the callback to
http://YOUR_DOMAIN.COM/auth/twitter/callback
. It's fine to set this to your production url, EngineAuth passes a redirect url while authenticating so there's no need to specifylocalhost:8080
here. - Go to Details OAuth settings
- Copy
Consumer key
asclient_id
- Copy
Consumer secret
asclient_secret
- Go to: https://www.linkedin.com/secure/developer?newapp
- Fill in required fileds. You may leave
OAuth Redirect URL:
blank. - Click
Add Application
- Copy
API Key
asclient_id
- Copy
Secret Key
asclient_secret
- Click
Done
Github
- Go to: https://github.com/account/applications/new
- Fill in required fileds. For
Callback URL
enter ``http://YOUR_DOMAIN.COM/auth/github/callback` - Click
Create Application
- Copy
Client ID
asclient_id
- Copy
Secret
asclient_secret
- Click
Done
App Engine OpenID
- Go to: https://appengine.google.com
- Select your application
- Choose
Application Settings
- Choose
(Experimental Federated Login)
from theAuthentication Options
drop down - Click Save
Objectives
User
When beginning any new web application, that involves users, you've probably asked yourself:
- How can I verify my user's identities?
- How do I protect their privacy?
- How can I make the signup process as simple as possible?
- How do I save my user from entering their information on yet another sight?
- How can I leverage the wealth of information that my users have entered into third party sights?
Which brings us to:
Note
Objective #1
Provide a clear path for Authentication / Authorization, that is secure, simple to use, and allows users to share their information, effortlessly.
Developer
And from a development standpoint you've probably ask:
- How can I save myself from writing yet another authentication strategy?
- As developers why are we all writing the same code, over and over again?
- How can I share what I've learn with others?
Which brings us to:
Note
Objective #2
The solution should be easy to implement, and easy to extend and share.
Credits
EngineAuth brings together ideas and code from many projects:
- Google App Engine and the Google App Engine Team: Obviously.
- Rodrigo Moraes: many aspects of this project were derived form his work on webapp2. Including sessions, models, test setup, and even this documentation.
- Google Api Python Client: this library provides the foundation for EngineAuth's Authentication and Authorization.
- OmniAuth: the basic structure for
Provider
Strategies
comes from OmniAuth - TODO: add others.
License
EngineAuth is licensed under the Apache License 2.0.