Don't Use OAuth for your API(ashfurrow.com)
ashfurrow.com
Don't Use OAuth for your API
http://ashfurrow.com/dont-use-oauth-for-your-api
26 comments
To be fair, Bearer Token is only one option for credentialing under Oauth2 (which also includes e.g. MAC, which is as good a authentication token as you could ask for).
And: Bearer Token is as good as the session cookies that are used in every app everywhere.
There's a valid criticism of OAuth2, and that's that there are lots of decisions that are left up to the Authorization server implementer, and they need to know what they're doing. And this is security: no one knows what they're doing well enough.
And: Bearer Token is as good as the session cookies that are used in every app everywhere.
There's a valid criticism of OAuth2, and that's that there are lots of decisions that are left up to the Authorization server implementer, and they need to know what they're doing. And this is security: no one knows what they're doing well enough.
Absolutely; however, the example given was Instagram, though, who uses bearer tokens, which are at once the easiest and least secure option. Since people tend to take the path of least resistance, they also seem to be the most popular option by a wide margin.
I use and enjoy OAuth2, and I'm not trying to bag on it; you're absolutely right in that it's up to the server to do things Right (and few people do; the fact that nearly nobody uses the state parameter is evidence enough of that!). However, I do think it's ridiculously faulty to hold Instagram's bearer token authorization up as the "secure way" to do things in contrast to OAuth1.
I think that both OAuth and OAuth2 are plenty secure in most use cases. TLS provides Good Enough(tm) protection for the vast majority of bearer token transactions, and as you point out, there's always MAC if you don't trust the integrity of the transport. But I do think it's ignorant to claim that OAuth 1 is insecure because you can pull the secrets out of a client app, while somehow claiming that OAuth 2 is secure against such attacks.
I use and enjoy OAuth2, and I'm not trying to bag on it; you're absolutely right in that it's up to the server to do things Right (and few people do; the fact that nearly nobody uses the state parameter is evidence enough of that!). However, I do think it's ridiculously faulty to hold Instagram's bearer token authorization up as the "secure way" to do things in contrast to OAuth1.
I think that both OAuth and OAuth2 are plenty secure in most use cases. TLS provides Good Enough(tm) protection for the vast majority of bearer token transactions, and as you point out, there's always MAC if you don't trust the integrity of the transport. But I do think it's ignorant to claim that OAuth 1 is insecure because you can pull the secrets out of a client app, while somehow claiming that OAuth 2 is secure against such attacks.
To quote from the page you linked to:
> If you’re building an app that does not have a server component (a purely javascript app, for instance), you’ll notice that it’s impossible to complete step three above to receive your access_token without also having to ship your client secret.
I guess I've misspoken here. Instagram uses OAuth for authentication, but actual calls to API endpoints are sugned by appending your access_token, not signing each request with OAuth.
> If you’re building an app that does not have a server component (a purely javascript app, for instance), you’ll notice that it’s impossible to complete step three above to receive your access_token without also having to ship your client secret.
I guess I've misspoken here. Instagram uses OAuth for authentication, but actual calls to API endpoints are sugned by appending your access_token, not signing each request with OAuth.
OAuth (1) requests are signed with a combination of access token and shared secret. I can't impersonate you (as a user) just by sucking the OAuth secrets out of the app.
OAuth 2 requests are identified by a bearer token, and have no shared secret signing.
OAuth 2 requests are identified by a bearer token, and have no shared secret signing.
Thanks for the info - I've updated the post according to your feedback. I think this is more an article discussing why you shouldn't use OAuth 1 when OAuth 2 is available.
With all due respect, it needs some work, then. You've framed it in the context of security, and there's been no compelling reason presented for as to why OAuth 1 is an inferior solution to OAuth 2 from a security perspective. Both use access tokens. OAuth2 has implicit flow, which serves to keep my server-side client secret out of the hands of mobile users, and which I can achieve in OAuth 1 by using a separate client secret for my mobile distribution than I do for my server distribution.
At the end of the day, all information on the client is subject to compromise. Period, paragraph, end of story. Any identification system that relies on a shared secret is subject to compromise as long as that shared secret is stored on a client-controlled device or ever entered into memory. That's true for OAuth, OAuth2, basic auth, pubkey authentication, passwords, biometrics, and literally every other single-factor identification scheme on the planet.
At the end of the day, all information on the client is subject to compromise. Period, paragraph, end of story. Any identification system that relies on a shared secret is subject to compromise as long as that shared secret is stored on a client-controlled device or ever entered into memory. That's true for OAuth, OAuth2, basic auth, pubkey authentication, passwords, biometrics, and literally every other single-factor identification scheme on the planet.
> actual calls to API endpoints are sugned by appending your access_token, not signing each request with OAuth
That's... how OAuth works. Plus, later on in the same paragraph you quoted from, that alternate flow is described as being part of the OAuth spec.
Might want to understand the system before bashing it.
That's... how OAuth works. Plus, later on in the same paragraph you quoted from, that alternate flow is described as being part of the OAuth spec.
Might want to understand the system before bashing it.
In your post, you state that Instagram does not use OAuth. But then, you link to their API page.
First sentence I read was: "Instagram’s API uses the OAuth 2.0 protocol for simple, but effective authentication and authorization."
First sentence I read was: "Instagram’s API uses the OAuth 2.0 protocol for simple, but effective authentication and authorization."
They offer different authentication mechanisms depending on whether you're writing a client or web app.
Can you point to anywhere that documents that?
"Instagram’s API uses the OAuth 2.0 protocol for simple, but effective authentication and authorization." seems pretty clear. So's this bit:
> Client-Side (Implicit) Authentication
> If you’re building an app that does not have a server component (a purely javascript app, for instance), you’ll notice that it’s impossible to complete step three above to receive your access_token without also having to ship your client secret. You should never ship your client secret onto devices you don’t control. Then how do you get an access_token? Well the smart folks in charge of the OAuth 2.0 spec anticipated this problem and created the Implicit Authentication Flow.
"Instagram’s API uses the OAuth 2.0 protocol for simple, but effective authentication and authorization." seems pretty clear. So's this bit:
> Client-Side (Implicit) Authentication
> If you’re building an app that does not have a server component (a purely javascript app, for instance), you’ll notice that it’s impossible to complete step three above to receive your access_token without also having to ship your client secret. You should never ship your client secret onto devices you don’t control. Then how do you get an access_token? Well the smart folks in charge of the OAuth 2.0 spec anticipated this problem and created the Implicit Authentication Flow.
In the article Ash writes:
> Basic HTTPS auth makes it easy to crack the protocol's encryption and get the username and password.
Does anyone know what he is referring to?
He also says:
> However, getting [a value] isn't difficult; it's easily accessible by a malicious user using an HTTPS proxy.
That, I am fairly certain, is not a serious concern because HTTPS uses a certificate chain to prevent the use of proxys. Sure, someone capable of generating bogus certificates (the NSA, for instance, and probably several other powerful governments) can insert a proxy without your knowing, but if they can do that then they can ALSO undermine the entire world financial infrastructure. Anyone capable of doing that is probably NOT going after YOUR app.
> Basic HTTPS auth makes it easy to crack the protocol's encryption and get the username and password.
Does anyone know what he is referring to?
He also says:
> However, getting [a value] isn't difficult; it's easily accessible by a malicious user using an HTTPS proxy.
That, I am fairly certain, is not a serious concern because HTTPS uses a certificate chain to prevent the use of proxys. Sure, someone capable of generating bogus certificates (the NSA, for instance, and probably several other powerful governments) can insert a proxy without your knowing, but if they can do that then they can ALSO undermine the entire world financial infrastructure. Anyone capable of doing that is probably NOT going after YOUR app.
Repeated username/combo requests over HTTPS produce patterns over multiple requests that can make cracking the encryption easier. Additionally, there's the issue of having to store usernames and passwords somewhere in the app (hopefully not plaintext, and hopefully somewhere inaccessible).
As for proxies, I'm talking about someone with physical access to a device and network, which I believe would work for extracting unencrypted HTTP headers from HTTPS requests (that's why an OAuth signature is itself encrypted by the consumer secret and user authentication token). However, I'm not a network security expert, so maybe I am mistaken.
As for proxies, I'm talking about someone with physical access to a device and network, which I believe would work for extracting unencrypted HTTP headers from HTTPS requests (that's why an OAuth signature is itself encrypted by the consumer secret and user authentication token). However, I'm not a network security expert, so maybe I am mistaken.
> Repeated username/combo requests over HTTPS produce patterns over multiple requests that can make cracking the encryption easier.
Interesting! Do you have any references where I can read more?
> As for proxies, I'm talking about someone with physical access to a device and network
HTTPS really does protect against someone with physical access to the network, by encrypting the data streem and preventing man-in-the-middle attacks (except by attackers who can subborn a trusted root authority). It does NOT protect against someone with full access to the "device" where the client app is running -- someone with such access can, more-or-less by definition, view all values that the program sends (including credentials).
Interesting! Do you have any references where I can read more?
> As for proxies, I'm talking about someone with physical access to a device and network
HTTPS really does protect against someone with physical access to the network, by encrypting the data streem and preventing man-in-the-middle attacks (except by attackers who can subborn a trusted root authority). It does NOT protect against someone with full access to the "device" where the client app is running -- someone with such access can, more-or-less by definition, view all values that the program sends (including credentials).
I'm either missing the reasons being backed up by Instagram's documentation or my sarcasm meter is completely broken this morning.
1) Dissent against OAuth; "OAuth sucks", "Don't use OAuth"
2) Focus on the fact that Instagram doesn't use OAuth
3) Link to Instagram documentation which says they do and it's awesome:
> Instagram’s API uses the OAuth 2.0 protocol for simple, but effective authentication and authorization
> Well the smart folks in charge of the OAuth 2.0 spec anticipated this problem and created the Implicit Authentication Flow
4) ???
What'd I miss?
1) Dissent against OAuth; "OAuth sucks", "Don't use OAuth"
2) Focus on the fact that Instagram doesn't use OAuth
3) Link to Instagram documentation which says they do and it's awesome:
> Instagram’s API uses the OAuth 2.0 protocol for simple, but effective authentication and authorization
> Well the smart folks in charge of the OAuth 2.0 spec anticipated this problem and created the Implicit Authentication Flow
4) ???
What'd I miss?
Yeah, sorry about that. I was mistaken and have udpated the article.
Updated with pictures of cats!
I think the more important lesson here is: don't use light grey text on a white background.
The question here is: who is responsible for user behavior, the user or the application? If the user is solely responsible then just using client tokens is fine, because you can ban the user by invalidating her tokens. But how to you ban an app? There's no good way to solve that problem if everything is client side.
The Stack Overflow question I link to offers an interesting point: OAuth would work fine if tokens and secrets were passed out on a per-app, per-install basis. That way you could ban a developer of an app, or an individual, if their token/secret combo becomes compromised. Something like federated key management: http://www.scmagazine.com/federated-key-management-as-the-ba...
The problem is that to do per-install tokens, one needs a secure side channel between the server and client over which to exchange these tokens, or a secure side channel to some kind of key management/federation server. That's fine and good, but it completely defeats the point of OAuth 1, which was to provide a request signing method that didn't depend on any other secure side-channels to operate.
With OAuth 2, of course, the point is mooted a bit by the decision to go with HTTPS as the secure channel, and such a scheme seems much more plausible.
With OAuth 2, of course, the point is mooted a bit by the decision to go with HTTPS as the secure channel, and such a scheme seems much more plausible.
What are some OAuth alternatives that you guys know of or have used in the past? I only know of two-way SSL and SAML.
wat.
Instagram uses OAuth2. It's right there in their doc: http://instagram.com/developer/authentication/
Second: OAuth uses access tokens, just like OAuth2. It also imposes request digests including a timestamp parameter, which prevents replays and doesn't permit forged requests if you manage to intercept an unencrypted request.
OAuth2 is arguably less secure than OAuth, because as it's being used by Instagram, the whole kit and kaboodle is wrapped up in the bearer token, which is wholly reliant on TLS for its secrecy.
Corporate network with a custom CA installed? Your account is theirs (seriously, your employer doesn't have to ask for your Facebook password to spy on you, they just have to make sure their proxy's CA is installed on your work-issued machine, and they can crack your Facebook account open like a pinata). Cert issued from a bad CA anywhere between you and the target server? Your account is theirs. Any breach in the host's enforcing of TLS? you've just leaked full access to your account to anyone that's listening. Hell, even an XSS breach can result in a leaked bearer token.
Oh, and guess what? You can still suck an auth token out of memory and use it to forge requests. And you can still suck the OAuth2 keys out of the package or memory or whatever and use them to forge authentication requests. The exact same issue exists for OAuth2 (and Instagram's usage of it) that exists for OAuth. Implicit authentication flow is great, but the core problem of "I can crack open your app, take your client ID, and use it to create authentication requests for my app while masquerading as you" still exists. With OAuth, you also have to steal a client secret in addition to a client ID, but the end result is the same.
OAuth2 is a lot more friendly than OAuth for client developers, I'll grant that, but it's just flat wrong to argue that it has some mystical protections against the problem that aren't present in OAuth.