Friday, November 21, 2014

Now you tell me.

Play 2.0 Support is Now Part of the Scala Plugin

The key change we’d like to highlight is that the Scala and Play 2.0 plugins have merged together, so with IntelliJ IDEA 14 you don’t need to install them separately because Play 2.0 support is now a part of the Scala plugin. You still need to run IntelliJ IDEA Ultimate to enable Play 2.0 support though.

Saturday, November 01, 2014

Why Google's Oauth2 implementation is poor

When comparing oauth2 providers I find that Google, while being the most compliant has the absolute worst working examples of their code. Everytime I see example code from google I get the mental image picture of a 24 year old developer who claims "its works!" while not even considering how someone who has never used the technology they are proposing may interpret their completely uncommented code base.

import os
import logging
import httplib2
from apiclient.discovery import build
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.http import HttpResponse
from django.http import HttpResponseBadRequest
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django_sample.plus.models import CredentialsModel
from django_sample import settings
from oauth2client import xsrfutil
from oauth2client.client import flow_from_clientsecrets
from oauth2client.django_orm import Storage
# CLIENT_SECRETS, name of a file containing the OAuth 2.0 information for this
# application, including client_id and client_secret, which are found
# on the API Access tab on the Google APIs
# Console <http://code.google.com/apis/console>
CLIENT_SECRETS = os.path.join(os.path.dirname(__file__), '..', 'client_secrets.json')
FLOW = flow_from_clientsecrets(
CLIENT_SECRETS,
scope='https://www.googleapis.com/auth/plus.me',
redirect_uri='http://localhost:8000/oauth2callback')
@login_required
def index(request):
storage = Storage(CredentialsModel, 'id', request.user, 'credential')
credential = storage.get()
if credential is None or credential.invalid == True:
FLOW.params['state'] = xsrfutil.generate_token(settings.SECRET_KEY,
request.user)
authorize_url = FLOW.step1_get_authorize_url()
return HttpResponseRedirect(authorize_url)
else:
http = httplib2.Http()
http = credential.authorize(http)
service = build("plus", "v1", http=http)
activities = service.activities()
activitylist = activities.list(collection='public',
userId='me').execute()
logging.info(activitylist)
return render_to_response('plus/welcome.html', {
'activitylist': activitylist,
})
@login_required
def auth_return(request):
if not xsrfutil.validate_token(settings.SECRET_KEY, request.REQUEST['state'],
request.user):
return HttpResponseBadRequest()
credential = FLOW.step2_exchange(request.REQUEST)
storage = Storage(CredentialsModel, 'id', request.user, 'credential')
storage.put(credential)
return HttpResponseRedirect("/")
view raw gistfile1.txt hosted with ❤ by GitHub


Really? So I attempted to get this framework working in my app for hours. It requires that you use the google model objects and the xsrfutil libs to work (I guess I never got it to).

https://developers.google.com/accounts/docs/OAuth2WebServer

and

https://code.google.com/p/google-api-python-client/source/browse/samples/django_sample/plus/views.py

This FLOW framework obscures the oauth2 process from the developer, so you are completely dependent on the code base being simple to understand to get the implementation working. Secondly creating the oauth2 app client credentials are buried deep in google's "API Dashboard". It was the longest amount of time I have ever spent on an oauth2 implementation. I have done many of these and this one is very difficult to work with.

Compare this to oauth2 providers that actually give you the curl approaches directly, and allow you to compare it to their API. Their oauth2 implementation is not hidden, and you can easily figure out what needs to be done.

Paypal
https://developer.paypal.com/docs/api/#authorizations
Pretty good outh2 implementation, well documented, easy to use API. Poor user object returned on successful auth in some cases.

Github
https://developer.github.com/v3/oauth/
Its good. Period.

Coinbase
https://www.coinbase.com/docs/api/authentication
Good implementation and documentation. The python examples were a little off but a python dev can figure it our. Their support responds to problems. Worthy.

Here are my recommendations to oauth providers:
  • Make the entire three legged process easy to natively implement via curl commands.
  • Build auth apis that are simple extensions of that flow 
  • Make sure that the client api can access enough user information to create a user record on the target app without asking for more information. 
  • Make it easy for developer to create client app secrets and manage multiple environments.