
Secure Your REST API - chunsaker
https://www.stormpath.com/blog/secure-your-rest-api-right-way
======
tptacek
You should probably disregard this advice. Instead:

[Late addition:

* Do not use passwords as API authentication. The user of an API is a computer program, not a human. Issue single-purpose random credentials for API access.]

* Make sure that your API is accessible only over HTTPS; test the API endpoint to ensure requests aren't honored over unencrypted HTTP.

* Use the simplest API authentication mechanism that (a) works and (b) you understand. You should probably degrade the capabilities of your API before you try to adopt an authentication system that you don't completely, fully, absolutely grok.

This means, if you don't need delegation right away (for instance, if you
don't have 3rd party applications making calls to your API on behalf of your
users), don't bother with anything like OAuth.

Contrary to the implications in this article, HTTP Basic Auth is not less
secure than OAuth if your endpoints all require HTTPS. If you allow HTTP calls
to an API, you have bigger problems than your auth token scheme.

Semantic mismatches between API endpoints and web UI endpoints (ie, semantic
differences between API auth and cookie-based authentication) are a classic,
pervasive, hard- to- eradicate source of serious security flaws. Don't make
things any more complicated than they need to be.

 _[Late edit: I didn't think I needed to make the first point, but I clearly
did need to. Sorry.]_

~~~
redblacktree
Even if you use HTTPS, aren't you vulnerable to lazy devs who put the password
in the URL?

If I use <https://username:password@example.com/>, doesn't that URL show up in
server logs all over the internet?

~~~
tptacek
Don't ever use passwords for API authentication. It's an API, not a browser.
The users of an API are other programs, not people. Issue single-purpose
random credentials.

I didn't think this was something I had to point out about API authentication,
but apparently it is.

~~~
CodeMage
I have a stupid question: how do you do this with HTTP Basic auth?

~~~
tptacek
Generate random long passwords.

------
wereHamster
Please stop using the term UUID when you mean 'random alphanumeric string'.
Because UUIDs have a standardized format (it's not just a random string):
<http://en.wikipedia.org/wiki/Universally_unique_identifier>

~~~
juiceandjuice
UUID v4 is, in fact, random and "alphanumeric" in the sense that it's hex.

That being said, I have a few other issues with their wording as well. They
should just say "we have a custom HMAC-based authentication scheme for our
REST API". Also, it took me about 3 days to realize HMAC over SSL/TLS is about
as secure and easy as you can get for most any language -- If you can send
HTTP requests, you can probably do HMAC. You can add further safety by making
expiring private keys for HMAC and other things, although my use cases are
based on long running (weeklong+) batch computations, and not end users. (i.e.
initial distribution of an expiring private key for HMAC over SSL,
reauthentication schemes, etc...

~~~
welder
It's not just random, it's a standard requiring some hex digits to be non-
random (4, 8, 9, a, b). Otherwise it won't validate as a UUID4.

------
jrochkind1
> Best practices say to encrypt your passwords in the database to limit a
> potential data breach. This increases overhead for each request when
> authenticating a user. Unique API keys authentication skips the hashing step
> and therefore speeds up your calls.

Wait, why can you can skip the hashing step and still be secure? Because
hashing is only neccesary if you call it a 'password', but not if you use it
in the same way but call it an 'api key' instead?

I guess it depends on the purpose for hashing. If it's just about 'data
breaches', then maybe it doesn't matter if your api keys get out... because
they at least won't grant access to any _other_ systems, since they weren't
manually entered by users and re-used accross systems. Is that what you're
thinking?

But don't you still want to avoid a data breach like this for your _own_
service?

And, I think, isn't the other reason hashed passwords are used, to make it
harder to do a brute force attack? Ie, it's quite intentional and deliberate
that it increases request overhead. And doesn't this still apply to an api
key, possibly even MORE so when you have a single api key instead of a
username/pass combo?

~~~
tptacek
If you lose the database for your own service, it does not matter how you
authenticate to that service. Attackers have already fatally bypassed your
credential system. At the same time, API credentials should by definition be
single-use.

~~~
danielweber
> At the same time, API credentials should by definition be single-use.

Could you spell this one out a little bit more? Do you mean only a single
session should be able to use an API credential?

~~~
tptacek
I mean the credential should only be relevant to the service, never shared
across multiple services, because the API generates it for you.

------
knkella
What are your thoughts on Amazon like security scheme? As far as there are no
third party apps involved, I think OAuth is an overkill.

What I mean by Amazon like securtiy is described in this article
[http://www.thebuzzmedia.com/designing-a-secure-rest-api-
with...](http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-
oauth-authentication/)

~~~
lhazlewood
Stormpath's custom scheme is very similar to Amazon's.

But per the blog article, you'd only want to do this if you are willing to
support client libraries/sdks that implement it as well. No one wants to spend
the time to implement non-standard custom HMAC algorithms.

~~~
knkella
We tried this with Pagify <http://pagify.io> And I think supporting client
libraries was not an issue, since we had to provide SDK one way or the other.

~~~
lhazlewood
Totally agree. The key here is that you're doing the work to implement the
algorithms, not your customers. If they had to do it, they probably just
wouldn't use it.

------
alinajaf
Does anyone know of a good reason not to use TLS with client-side certificates
(and you as the CA) for API authentication?

~~~
epochwolf
Yeah, limited library support for client certs.

~~~
dllthomas
Let's fix that...

------
pplante
In my humble opinion, security through obscurity via UUIDS rather than
sequential integers is not great advice. It merely masks the real problem.

~~~
danielweber
Obscurity can be a fine part of being secure. You have to think carefully
about what happens when it fails, and realize that automated bots will tend to
find things humans would consider obscure, but don't let the usually-good
heuristic become a straightjacket.

~~~
dllthomas
Obscurity of the secret is a necessary part of being secure :-P

Security-through-obscurity refers to the notion that your algorithms are a
meaningful part of the key.

------
nicwolff
Shoots down Basic auth without SSL, without mentioning Digest auth, weird.

~~~
lhazlewood
There are many types of digest authentication - OAuth1.0a and Amazon's and
Stormpath's custom schemes are examples. Browser-specific digest
authentication wasn't covered however since the article was about REST APIs
and most REST clients are not browsers.

~~~
bct
I'm pretty sure he means RFC 2617 Digest authentication. There's nothing
browser-specific about it.

~~~
lhazlewood
I gathered as much. But in practice, how often do you see RFC 2617 Digest
authc used in non-browser scenarios? (I'm genuinely curious. I haven't seen it
used much at all outside of web browsers, so I'm curious what others may have
come across).

~~~
bct
I've written Atom Publishing Protocol servers that use it. It's not badly-
suited for non-browser tasks (although yes, SSL and Basic is much simpler - if
you don't mind paying for the certificate). It's unusual, but it's pretty
unusual to use it (or Basic) for web browsers these days, too.

------
cicloid
Didn't oAuth2 support signed requests via MAC token on request?

------
mcavage
I expected something very different from this article based on the headline.
Specifically, I completely disagree with the "leave it to industry standards"
approach, as that doesn't help people understand what they should do, and more
importantly, why.

Request/response protocols (well, many things) really break down into 5 top-
level categories (some sources will say the 6th is Audit):

\- Authentication

\- Authorization

\- Integrity

\- Confidentiality

\- Non-repudiation

It's a far more interesting exercise to walk through what you would get from
each solution. Basic-Auth over TLS, actually gets you quite a ways towards
that goal (specifically, C-I-A (authentication)). Where that, and notably
HMAC, fall over is non-repudiation because they're based on a shared-secret
model; admittedly HMAC keys are better than passwords because you're not
sending the secret on every request, but asymmetric crypto is preferred.
Authorization that the server system does is really out of scope in all of
these protocols, so Basic-Auth over TLS doesn't really impact that one. It can
be as simple as "caller = owner," or as full-featured as a security policy
language [1] (full disclosure: I am the original author of [1]).

OAuth really doesn't differ that much besides specifically solving the
delegated access and website SSO problem(s); but IMO it does so with an overly
baroque protocol that has too many parts. The "long pole" of setting up such a
system (that is, allowing 3rd party sites to act on behalf of my site's users)
isn't the specifics of what my REST api looks like, but really it's all the
"governance" of user decisions, and more-over, key management (in all these
cases, key management is generally the hardest or almost hardest problem).

While it can be debated whether it was right or wrong, we (Joyent) released an
open-source spec to solve straight up authentication of REST requests using
SSH keys [2]. At the end of the day, the user signs the Date header of
requests with their private key (which by definition the server has never
seen), and all requests must be over TLS. Disregarding Authorization, this
scheme gives you Confidentiality (TLS), Integrity (TLS), Authentication
(Signature), Non-Repudiation (asymmetric signature), and adds a "poor man's
nonce," assuming you disallow requests where the clock skew of the date header
is too large. And lastly, SSH solves a lot of key management problems for
humans. Note: I didn't drop that reference to advocate for our specification
here, but rather the security process you should think about when evaluating
whether a protocol is secure.

[1] [http://docs.aws.amazon.com/IAM/latest/UserGuide/policy-
refer...](http://docs.aws.amazon.com/IAM/latest/UserGuide/policy-
reference.html)

[2] [https://github.com/joyent/node-http-
signature/blob/master/ht...](https://github.com/joyent/node-http-
signature/blob/master/http_signing.md)

PS

Mutual-Auth SSL/TLS is a royal PITA, and is basically guaranteed to cause you
grief. The client compatibility matrix might as well be considered an NP hard
problem to assure yourself coverage, and failure modes of the different
browsers/SDKs all differ. As a REST API should have maximum accessibility to
clients (i.e., don't wed yourself to any one language/sdk), this is pretty
much a non-starter.

* edited: copy/paste formatting

~~~
bradleyjg
> Mutual-Auth SSL/TLS is a royal PITA, and is basically guaranteed to cause
> you grief. The client compatibility matrix might as well be considered an NP
> hard problem to assure yourself coverage, and failure modes of the different
> browsers/SDKs all differ. As a REST API should have maximum accessibility to
> clients (i.e., don't wed yourself to any one language/sdk), this is pretty
> much a non-starter.

Given the inconsistent support for mutual-auth TLS, which along with its
direct ancestors has existed for a decade and a half, what makes you think
they'll be widespread and correct support for SAS?

~~~
mcavage
If by SAS you mean SSH, then really it's that there's a much smaller client
surface area (really, openssh), and the fallback is always "use a PKCS#8
private key", which is much more uniform than SSL. SSL mixes in x509, and
protocol, and UX.

That said, you don't have to agree with it. My macro point was really
assessing these things against basic security threat modeling, not whether or
not you agree with our choices of using SSH.

~~~
bradleyjg
Well it's more than SSH. The client library needs to to implement the headers
and do the date signing. Sure it's easier than TLS, but the libraries suffers
more from a lack of dedicated interest than insane complexity I would think.

But I do agree with your basic point that too many people stop at
authentication, instead of considering the full range of concerns.

------
dantiberian
How does using bare api keys over TLS compare to these suggestions? It's less
secure but is it still a recommended option?

~~~
tptacek
The advantage to OAuth over basic-auth is that you can delegate the
credentials, which is to say you can set up your system so that users can give
a limited-use credential to a 3rd party application to perform API calls on
their behalf.

Some very large services have abused OAuth to "delegate" credentials to mobile
devices, which has set up the expectation among developers that OAuth is the
"sophisticated" way of doing all-around credential management of any sort. Not
so. If you don't have delegation to third parties, don't use OAuth.

Most applications do not need delegation.

If you need delegation, there are simpler ways to do it than OAuth that won't
meaningfully sacrifice the security of your controls. At the same time, using
an OAuth solution you don't fully understand (for instance, using OAuth
through a high-level library that hides the details from you) can damage the
integrity of your whole application by creating new classes of mistakes for
you to make.

