28

I'm building a RESTful API for a project I'm working on and I'd like to make the main application consume the API because:

  1. It will result in having one set of code to maintain
  2. Should we decide to expose the API for 3rd party devs it will already be done
  3. It opens up the possibility to make mobile applications that consume it
  4. I really want to learn how to do it

The API will be hosted on a subdomain https://api.example.com and the main web application will be hosted at the root domain https://example.com.

Conceptually I understand how everything works, but my main question is how the authentication flow will change if, at all. Ordinarily 3rd party apps would:

  1. Obtain a request token from https://api.example.com/request_token
  2. Redirect the user to authenticate on https://api.authenticate.com/authorize
  3. Get redirected back to the 3rd party application
  4. Obtain an access token from https://api.example.com/access_token

Since I control both domains, can I do something similar to:

  1. Obtain a request token when the user lands on the login screen at https://www.example.com
  2. The user authenticates using a form on https://www.example.com that calls the same code as https://api.example.com/authorize
  3. If the credentials are valid, the request token is swapped for the access token
  4. Access token is saved in the session and expires when the user logs out like it normally would

Step 3 feels like it's wrong since there will be duplicate code, but wouldn't it open me up to XSS attacks is the login form on https://www.example.com sent the data to https://api.example.com since they are technically different domains?

Am I overcomplicating this?

Steve
  • 1,112
  • 8
  • 12

2 Answers2

20

I have come across the same issue and solved it like this.

1 For third party apps, using my API, they have to authenticate via OAuth on all requests.

2 For my own third party clients, (mobile, AIR etc) - they use OAuth, with the difference that I allow these to send username and password directly in the authorization step (so I can make a native login dialogue). This is provided that your API is over SSL/HTTPS.

3 For my web application, I use cookie authentication to access the APIs. I.e after having logged in, the user could simply call API:urls and get JSON/XML back. Nice for quick exploring the APIs also (although a real API Console like APIGee does a better job there).

Jon Nylander
  • 8,743
  • 5
  • 34
  • 45
  • 2
    Can you please elaborate on Item 3? When the user logs in are you saving a session id in a cookie, and then using that as a pseudo-access token for when you make an API call, and then looking it up when you receive the API request? That seems like it would be a security vulnerability... – Steve Dec 16 '11 at 19:35
  • 1
    In essence yes. But how is that a vulnerability? I don't use OAuth when calling the APIs from the web app. If you're logged in (as determined by validating the cookie) - then the APIs are accessible by simply calling the URL. I did forget to mention however that I serve the API:s to the web app on the same domain. – Jon Nylander Dec 16 '11 at 20:33
  • I guess as long as you're not solely relying on the session id to identify the user on the server side it's not. I was thinking you might open yourself up to [Session Hijacking](http://en.wikipedia.org/wiki/Session_hijacking), but it's the Friday after school got out and I'm tired. Based on your answers to other questions you're definitely a very knowledgeable fella! Thanks for your help! – Steve Dec 16 '11 at 21:06
  • 1
    No of course, your session cookie should be transmitted over SSL, have a really long and extremely random value that is regenerated every request, expires if a user is inactive for a given time etc etc. But given that you handle session cookies correctly... you should be good to go. – Jon Nylander Dec 16 '11 at 22:07
  • How do you make sure that when using the username password flow that someone won't just decompile your mobile app, steal the keys, and impersonate your app? Is this unavoidable? – untitled Feb 23 '14 at 09:46
  • Uhm yeah, pretty much right? What you can do as a client developer is use the underlying framework's keychain APIs to store accesstokens and secrets - but as long as consumer keys and secrets are to be found in code there is no bullet proof way to stop decompiling etc. I suppose one way to move around it is to rotate consumer keys among your apps periodically. But yeah, pretty much unavoidable. – Jon Nylander Feb 24 '14 at 13:48
  • for item 2, do you use Resource Owner Password Credentials for that case ? – Adi Sembiring Sep 11 '14 at 07:49
0

I would say you're overcomplicating it a little. If your code is seperated properly, you can easily build a thin REST layer over your application's service layer, while having your application's controllers be a thin layer over your service layer as well.

blockhead
  • 9,655
  • 3
  • 43
  • 69
  • 2
    What do you mean by service layer? Is that the models inside the controllers that do all of the heavy lifting? If so, then that's kind of my plan - it's really the authentication bit that's throwing me for a loop. I want to move all of the business logic to a separate API subdomain because we'll need to expose it for mobile app development, and I *think* it will help me with scalability in the sense that I can spin up or down the number of dumb clients connecting to the API and just have the central API handle all of the data caching. I don't know much about scalability yet though... – Steve Dec 16 '11 at 13:22