While testing out a new tool I’m working on that uses a variety of OAuth2 providers and thought I’d catalog some of the quirks I came across. This is just for the authorization flow, not for actually making requests once you’ve secured a token. Now that the OAuth2 spec is solidified we should start seeing less and less of these issues.
Good: The APIs Console is one of the best out there. My favorite feature: allowing you to specify multiple callback URLs for a single app. This makes testing different environments way easier because you don’t need to go back and constantly edit the callback URL value.
Good: The OAuth 2.0 Playground is fantastic. It will show you all the HTTP requests that are made for a standard auth flow. This makes it really easy to debug issues on your end by comparing the requests. I used it to diagnose the following problem.
Bad: When requesting an Access Token the request will fail if you include any parameters that it is not expecting. Google does not require a
type parameter when getting the token like some other APIs do and will give you a 400 Bad Request with an
invalid_request error if they are included.
Bad: The scopes options are not immediately obvious. There’s a huge list of services and you must enable them individually (good) in the ‘Services’ section of your project in the APIs Console. This page though does not list the scopes value to use. The Playground does have what appears to be a complete list.
Bad: If you just want to use OAuth with the Graph API, you still need to enable “Website with Facebook Login” in order to set the Site URL. This is hidden by default and took me a little bit to find it. This setting restricts which domains they will redirect back to.
Good: The Site URL only requires a domain instead of a full URL which means you can change your callback URL path without breaking your app.
Bad: When you create the app you select which services you want your app to have access to but during the auth flow only one of the services is displayed.
Bad: There’s no support for limiting access to read-only via scopes. The only option is full read/write for all of the apps selected.
Bad: Stripe does not use a
client_secret. Most client libraries and OAuth examples use it so it may be confusing for experienced developers wondering where that value is.
Bad: This is not technically wrong, but it isn’t common. When exchanging the code for an access token you are required to send an
Authorization header with a value of
Bearer and your Stripe account secret key (either test or live). I’d rather they just tell you to use the secret key as the client_secret and not require the additional header.
Bad: The docs say that the
scope parameter is optional but will give you an error (400 OAuthException – Invalid scope field(s)) if it is specified with an empty value. You should specify at least ‘basic’ or omit the parameter to accept the default.
Bad: The redirect URL settings requires HTTPS which can be difficult if you’re trying to test locally (for instance my test app runs on http://localhost:5001 which is accepted every where else). Box has informed me this will be resolved soon.
Bad: Does not use scopes for read-only or read/write access (is configured with the application). Box has also told me they will be changing this once they have more than one scope.
Good: Permissions are set via an extensive and clear list of scopes. Very nice.
Good: Callback URL validation is set via domain only (similar to Facebook).
Bad: Scopes must be specified comma-separated, contrary to the OAuth2 spec. This is on the roadmap to be fixed.
Good: The application manager allows you to generate a token for yourself with custom scopes without having to go through the flow. This is extremely helpful during development.
Here are some others that I tried that I didn’t have any notable issues with: MailChimp, Foursquare, Wordpress. I also tried Force.com OAuth for their REST API and there were no technical issues.
Here are the services I desperately wish would move from OAuth 1.0a to OAuth 2.0: Twitter, Dropbox, LinkedIn
If you’ve come across a unique implementation quirk of your own, post it below in the comments.