Logging in to a RESTful API

279 views
Skip to first unread message

Ell Vee Aitch

unread,
Nov 27, 2011, 4:06:48 PM11/27/11
to API Craft
Hi.

I'm building a REST API to be consumed by a few frontends. These are
completely statically served, and are basically a bunch of HTML/CSS/JS
that teaches a browser how to consume the REST API. They are all
essentially identical from the APIs point of view: they just look
different :)

I'm wondering about how to handle logins. I want to use access tokens
instead of the user credentials for two reasons: 1) static frontends
don't have to hold on to the credentials longer than necessary, 2)
verifying credentials is slow.

I could do everything over the REST API, but that would be pretty
slow. I could use HTTP Basic auth all the time, but that would be even
slower: a securely stored password takes work to verify. I could use
OAuth, but there's a bit of an impedance mismatch. The users don't
know or care at first that they're signing up for something that will
work on a whole network of sites. It's not that we're actively trying
to hide this, but there's just little value in the minibrowser that
shows them registering on the Whatever Platform Network rather than
the site they actually think they're on (quietly ignoring the fact
that that might confuse, scare and dissuade many users since they have
never heard of my platform).

I've distilled my thoughts in the following blog post:
http://b.lvh.cc/designing-a-rest-api-logging-in

From what I've gathered from the screencasts and this newsgroup, I'm
going to guess that the preferences are, in order:

1. OAuth
2. Option 2b (API purity + shortcuts)

I think the blog post explains why I think OAuth isn't a great fit.
I'd love to hear your thoughts on this specific case.


thanks in advance for your replies,
lvh

Sam Ramji

unread,
Nov 27, 2011, 11:35:13 PM11/27/11
to api-...@googlegroups.com
It sounds like you are in control of all of the clients ("frontends") and therefore don't need OAuth.  Is that right?

To be OAuth-ready (as you indicate in your post), option 1 makes sense to me - that way you are building the REST API to be the right construct, and separating the token-granting mechanism early on.  

You can replace or augment the token-granting mechanism later on.  Presumably you will pass all your tokens (early/custom and eventual/OAuth) in the HTTP header, so even your proxies/web infrastructure can be trained from an early age to behave well.

Cheers,

Sam

Ell Vee Aitch

unread,
Nov 28, 2011, 7:46:19 AM11/28/11
to API Craft
On Nov 28, 5:35 am, Sam Ramji <sra...@apigee.com> wrote:
> It sounds like you are in control of all of the clients ("frontends") and
> therefore don't need OAuth. Is that right?

Yep. They're static sites being served by us. Basically we're teaching
browsers how to consume the API.

> To be OAuth-ready (as you indicate in your post), option 1 makes sense to
> me - that way you are building the REST API to be the right construct, and
> separating the token-granting mechanism early on.

Cool. That sounds reasonable. I can always move to 2b (minus the part
where the REST API ever understands HTTP Basic Auth) later on that
way.

> You can replace or augment the token-granting mechanism later on.
> Presumably you will pass all your tokens (early/custom and eventual/OAuth)
> in the HTTP header, so even your proxies/web infrastructure can be trained
> from an early age to behave well.

Yep.

I considered OAuth because they do explicitly support a flow for user-
agent-based clients, but it just seems to complicated right now since
we're not interested in allowing third parties to use the API just
yet, plus since we control everything it should be easy to transition
later (and not have an other OAuthpocalypse).

> Cheers,
>
> Sam

cheers
lvh

Jeff Schmidt

unread,
Nov 28, 2011, 9:25:13 AM11/28/11
to API Craft
Hi lvh:

I think it's best to keep separate the authentication/authorization
mechanism from the RESTful API. That is, the code you consider being
the top-level of the API (that which receives the HTTP requests and
then calls your various services etc. to formulate the response)
should not care how it was called. If the security layer above it used
OAuth, HTTP basic authentication, some other funky mechanism, you API
is agnostic. It only cares about GET, POST, PUT etc., resources, and
perhaps some request parameters to fullfill its contract.

Of course, the client must deal with the security issues that must be
met in order to interact with your API. I strongly believe that this
where where a standard such as OAuth or HTTP basic authentication
will benefit you. Perhaps you're in control of the client/frontends
today, but will you be tomorrow? You will open up your beautiful,
useful RESTful API one day, and a non-standard authentication
mechanism will be a turn off.

Another important consideration is to keep your API, and identity
mechanism, stateless. HTTP basic is a natural, since the client must
provide the credentials with each request. Just avoid the overhead of
creating an HTTP session on the server side. An OAuth token, or any
other token, must be recognized by all hosts to which an API request
may be sent (i.e. via a load balancer), so the use of some common
persistent mechanism such a relational database or no-sql store works.
But, in either case, the server must be able to verify the
credentials, and in the OAuth case, requests bearing tokens, the token
must be verified to see that it has not expired, or become invalid for
some other reason.

I think your option 1 is best. Do not mix authentication into your
API. Think of your API having to understand "NO kind of token". The
fact the API code gets invoked means the authentication mechanism is
happy. During your development, your authentication mechanism may be
nothing. At some point though, the mechanism could be HTTP basic
authentication. Your API code does not care, though your clients will
have to provide the credentials - in a standard way. If it makes sense
to move to OAuth, then again, you don't have to change the API look
for and deal with, say, the bearer_token parameter, the authentication
mechanism does so. Your API code is blissfully ignorant.

Also, regarding your option 1, with basic authentication, there is no
additional non-restful RPC-ish call to be made. With OAuth 2, you
post credentials to the authorization URL and receive a JSON response,
then you can just use that token for future requests to your API. I
assume given it's the web 2+ world that your clients will be using
JavaScript and Ajax. In that case, the OAuth 2.0 bearer token is very
useful in that no credentials need to be present in the user agent.
See:

https://groups.google.com/group/api-craft/browse_thread/thread/66207a833da3d332

I don't know what server-side technologies you're using, but given
your many quotes from Zen of Python on your blog post, I'm guessing
Python. :):) I've very little experience there though, but I'm sure
there must be appropriate mechanisms for working with OAuth, and
certainly for HTTP basic. :)

Good luck!

Jeff

Jack Repenning

unread,
Nov 28, 2011, 4:46:24 PM11/28/11
to api-...@googlegroups.com
On Nov 27, 2011, at 1:06 PM, Ell Vee Aitch wrote:

> I've distilled my thoughts in the following blog post:
> http://b.lvh.cc/designing-a-rest-api-logging-in

I think there's a third possibility, although you might see this as just a variant of "REST with shortcuts." What we do is this:

1. Every REST call can potentially include user credentials. If they're provided, we check 'em.
2. Whenever credentials pass the check, we add a one-time key to the session block (just a verifiable, non-spoofable hash).
3. If an incoming request has no credentials, we look for the key, and trust it.

In this way, there's no explicit requirement for a separate log-on activity: any request achieves that. We actually do provide a login function, but it's really redundant; within our framework (Rails), it's a null function that gets the universal "check credentials" before_hook, and then does nothing. Violates your quoted Pythonic koan "only one obvious way" rule, of course, but it's been amazingly complicated to explain to users "you don't need to log in"!

Your blog includes some comments on the difference between user-ID-as-email, and user-ID-as-generated-token. This is a real complication, of course, but I think it's independent of the authentication protocol. Certainly, the objection that this means the API needs to understand two auth algorithms holds very little water: the focus of an API needs to be the convenience of the user, not the API! If there's a natural way to generate and issue these tokens within the work flow of the user's initial establishment of relationship, then issuing a token works (we have "partners," who go through marketing reconciliation and contract dickering and signatures in blood long before they get to anything so picayune as API details, so issuing them a token works, and we do that, and allow that as "user ID" in the credentials). If it's end users flitting through on their way to YouTube, then an extra turn-around to request the token, and some necessity to write it in a Post Note on the monitor, and all that, are unreasonable; let 'em use what they know, their email, and provide a Profile Edit page somewhere to update the email.

-==-
Jack Repenning

There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
- C.A.R. Hoare


Sam Ramji

unread,
Nov 30, 2011, 3:43:18 PM11/30/11
to API Craft
"The focus of an API needs to be the convenience of the user, not the
API!" - J. Repenning

Now there is the perfect quote. This is the core philosophical
difference between the APIs that are awesome and those that are
terrible. There's little middle ground in practice.

On Nov 28, 1:46 pm, Jack Repenning <repenning.j...@gmail.com> wrote:
> ... Certainly, the objection that this means the API needs to understand two auth algorithms holds very little water: the focus of an API needs to be the convenience of the user, not the API!
>
> -==-
> Jack Repenning

Mike Kelly

unread,
Nov 30, 2011, 3:55:11 PM11/30/11
to api-...@googlegroups.com
Focusing on convenience is not always the right approach, it depends
on the context in which your application is being consumed and what
the long/short term objectives are.

Short-run conveniences can actually degrade into significant costs
over time, and end up stifling the evolution of your API. Whether or
not this is important to you is very dependent on your context.

Cheers,
Mike

Peter Monks

unread,
Nov 30, 2011, 11:14:35 PM11/30/11
to api-...@googlegroups.com
Conversely, if your API isn't sufficiently convenient to use, it may not make it to the long term.

Cheers,
Peter

 

Jack Repenning

unread,
Dec 1, 2011, 12:30:32 AM12/1/11
to api-...@googlegroups.com

On Nov 30, 2011, at 12:55 PM, Mike Kelly wrote:

> Short-run conveniences can actually degrade into significant costs
> over time, and end up stifling the evolution of your API.

Which would be very inconvenient for all.

I still hold that empowering the use of the API is why the API exists. "Enlightened, far-thinking, prophetic, optimal, faultless, complete" empowerment is, of course, so much the better.

Jack Repenning

The best way that a man could test his readiness to encounter the common variety of mankind would be to climb down a chimney into any house at random, and get on as well as possible with the people inside. And that is essentially what each one of us did on the day that he was born.

-- G. K. Chesterton, "Heretics"

Mike Kelly

unread,
Dec 1, 2011, 3:20:50 AM12/1/11
to api-...@googlegroups.com
For sure.

My point was just that 'focusing on user convenience' is not really an
effective rule of thumb because your API design should be a tradeoff
of a number of factors, weighed up in context.

Cheers,
Mike

Mike Kelly

unread,
Dec 1, 2011, 3:21:21 AM12/1/11
to api-...@googlegroups.com
For sure.
My point was just that 'focusing on user convenience' is not really
aneffective rule of thumb because your API design should be a
tradeoffof a number of factors, weighed up in context.

Cheers,Mike
On Thu, Dec 1, 2011 at 4:14 AM, Peter Monks <pmo...@alfresco.com> wrote:

Gabor

unread,
Oct 8, 2012, 10:44:56 AM10/8/12
to api-...@googlegroups.com
Hi Ell,

The link you provided seems to be broken. Would you care sharing a working one, please? I'm very interested in what you came up with.

Thanks,

Gabor

Steven Goff

unread,
Oct 8, 2012, 2:45:58 PM10/8/12
to api-...@googlegroups.com
On Monday, November 28, 2011 3:46:24 PM UTC-6, Jack Repenning wrote:
On Nov 27, 2011, at 1:06 PM, Ell Vee Aitch wrote:

> I've distilled my thoughts in the following blog post:
> http://b.lvh.cc/designing-a-rest-api-logging-in

I think there's a third possibility, although you might see this as just a variant of "REST with shortcuts." What we do is this:

1. Every REST call can potentially include user credentials. If they're provided, we check 'em.
2. Whenever credentials pass the check, we add a one-time key to the session block (just a verifiable, non-spoofable hash).
3. If an incoming request has no credentials, we look for the key, and trust it.

 Jack do you mind elaborating on #2?  After basic auth is the key returned to the client for subsequent calls to the API?  Do you then compare that to what you have stored for the user?  I'm not familiar with the term 'session block', is this http session or is it some state on the client?  I imagine you just have this key expire after x minutes of inactivity?
Thanks working on refining my first API and want to confirm I'm understanding correctly.
Reply all
Reply to author
Forward
0 new messages