I want to set up a rest api with an oauth 2.0 provider for authentication.I use python. is there any library for setting up an oauth 2.0 provider coded in python that runs on app engine ? Thanks.
OAuth2 support in builtin on both the Python and Java App Engine runtimes.
In Python all you need is:
from google.appengine.api import oauth
# Note, unlike in the Android app below, there's no 'oauth2:' prefix here
SCOPE = 'https://www.googleapis.com/auth/userinfo.email'
# magic happens here
user = oauth.get_current_user(SCOPE)
In Java you would use:
OAuthService oauth = OAuthServiceFactory.getOAuthService();
// Note, unlike in the Android app below, there's no 'oauth2:' prefix here
String SCOPE = "https://www.googleapis.com/auth/userinfo.email";
// magic happens here
User user = oauth.getCurrentUser(SCOPE);
Here's the full Python 2.7 handler which will allow you to verify the user:
from google.appengine.api import oauth
import logging
import traceback
import webapp2
class MainHandler(webapp2.RequestHandler):
def post(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hi there!\n')
# Note, unlike in the Android app below, there's no 'oauth2:' prefix here
scope = 'https://www.googleapis.com/auth/userinfo.email'
try:
self.response.write('\noauth.get_current_user(%s)' % repr(scope))
# validates audience of the OAuth2 access token
allowed_clients = ['407408718192.apps.googleusercontent.com'] # list your client ids here
token_audience = oauth.get_client_id(scope)
if token_audience not in allowed_clients:
raise oauth.OAuthRequestError('audience of token \'%s\' is not in allowed list (%s)' % (token_audience, allowed_clients))
# gets user object for the user represented by the oauth token
user = oauth.get_current_user(scope)
self.response.write(' = %s\n' % user)
self.response.write('- auth_domain = %s\n' % user.auth_domain())
self.response.write('- email = %s\n' % user.email())
self.response.write('- nickname = %s\n' % user.nickname())
self.response.write('- user_id = %s\n' % user.user_id())
except oauth.OAuthRequestError, e:
self.response.set_status(401)
self.response.write(' -> %s %s\n' % (e.__class__.__name__, e.message))
logging.warn(traceback.format_exc())
app = webapp2.WSGIApplication([
('/.*', MainHandler)
], debug=True)
The app.yaml is trivial
application: your-app-id
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
- url: .*
script: main.app
Note that client should send the OAuth2 token in an Authorization: Bearer
HTTP Request Header, e.g.
Authorization: Bearer ya29XAHES6ZT4w72FecXjZu4ZWskTSX3x3OqYxUSTIrA2IfxDDPpI
If you happen to be building an Android app, you can easily generate these tokens using the AccountManager
interface:
AccountManager accountManager = AccountManager.get(this);
Account[] accounts = accountManager.getAccountsByType("com.google");
// TODO: Allow the user to specify which account to authenticate with
for (Account account : accounts) {
Log.i(TAG, "- account.name = " + account.name);
}
// Note the "oauth2:" prefix here
String authTokenType = "oauth2:https://www.googleapis.com/auth/userinfo.email";
// Note: AccountManager will cache these token, even after they've expired.
// TODO: Invalidate expired tokens, either after auth fails, or preemptively via:
// accountManager.invalidateAuthToken(accounts[0].type, token);
accountManager.getAuthToken(accounts[0], authTokenType, null, this,
new AccountManagerCallback<Bundle>() {
@Override
public void run(AccountManagerFuture<Bundle> future) {
try {
String token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
Log.i(TAG, "Got KEY_AUTHTOKEN: " + token);
// Don't forget HTTP Header "Authorization: Bearer <token>"
callAppEngineRestApi(token); // <---- Your code here
} catch (OperationCanceledException e) {
Log.i(TAG, "The user has denied you access to the API");
} catch (Exception e) {
Log.i(TAG, "Exception: ", e);
}
}
}, null);
If you'd like to see everything put together, feel free to checkout these projects for the full source:
Have you checked out the OAuth for Python article information? It says that it is for "This reference describes how to use OAuth with Python applications as the service provider. "
I can't comment on the above answer so I have added it here for anyone struggling with this snippet:
# magic happens here
user = oauth.get_current_user(SCOPE)
This has been broken on AppEngine for a month if you're using service accounts (and as of today, I think also Google user tokens) as the token length causes issues in the AE library. Google have told me they are unlikely to fix it soon.
This is the only thing that works for me, at the moment:
token = self.request.headers['Authorization'].split(' ')[1]
url = 'https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=' + token
oauth_response = urlfetch.fetch(url)
if oauth_response.status_code != 200:
raise Exception('Unable to authorise: {}/{}'.format(oauth_response.status_code, oauth_response.content))
token_response = json.loads(oauth_response.content)
email = token_response['email']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With