6

I was thinking about how I can decouple a web-application completely into a server-side and a client-side component. I want to decouple the app to the extent that I can host both components on seperate servers.

So, for example, I would have:

  1. Server 1 (API Server): A server-side component running on Django on something like Heroku or EC2.
  2. Server 2 (Static Server): A client-side component running on AngularJS on a static server like S3 or CloudFront.

The communication between these components will take place using a JSON REST API.

Questions:

  1. Is this approach common? advisable?

    Does a company like Facebook or Twitter mostly utilise the same API for the webapp as it does for its mobile apps or its open API?

  2. Is it a good idea to use oAuth2 for the login process?

    So the user is redirected to a login page on Server 1 (this is the only page on Server 1) and then redirected back to Server 2 with a token if authentication succeeds. Is this the best approach? It seems like I am kinda "breaking the flow" if I do this. Is this normal?

The motivation for this is for me to be able to use the same API for my web, iOS and Android clients.

Thanks!

migrated from stackoverflow.com Mar 11 '14 at 20:19

This question came from our site for professional and enthusiast programmers.

6

JSON/HTTP is a really good decoupling mechanism, and I'll throw out a couple of suggestions that will make it even more loosely coupled.

The rapid industry adoption of JSON/HTTP interfaces really speaks well about how people view the usefulness of that model.

  • Enforce a MUST IGNORE rule.

That is, when parsing the JSON (client or server), the app MUST IGNORE any fields it don't recognize.

XML went in the with idea that the app MUST UNDERSTAND each field or else the document was invalid. But that created problems with versioning, because with almost any change, clients needed to upgrade every time the server did. Even adding an informational field broke the spec. With MUST IGNORE, the server can add new fields any time, and as long as it doesn't remove or change the meaning of other fields (see below). Existing clients can just ignore the new fields. Rather, they MUST IGNORE the new fields.

A search on MUST IGNORE and MUST UNDERSTAND will reveal lots of good articles that talk about that.

  • Minimize breaking changes.

A "breaking change" is a change that will break existing clients. That is, removing a field the clients use. Or changing the meaning of a field (i.e. changing an amount field from dollars to Yen). That is, something that invalidates a client's assumptions about the data it's currently using.

With a breaking change, every client needs to make a change to support the new semantics or stop relying on missing fields. Do don't do that unless its necessary.

The next logical step gets kind of contentious -- but in the extreme you would never make a breaking change. That is, have full backward-compatibility for every release. That may or may not be realistic, and it may require carrying along baggage from early versions, but it will spare a lot of churn for the clients.

  • OAuth 2 is a really good bet for a well-thought out, standardized security protocol. You could sit down and design something simpler, depending on what compromises are OK. But OAuth is a good fleshed-out protocol that has undergone years of industry scrutiny, so they've had lots of time to work out the kinks. And standard libraries are readily available for both client and server. I used an OAuth plugin to DJango for one project and it worked out really well.

  • Because of the ubiquity of JSON parsers, maintaining a single API regardless of client will make life a lot easier. Sometimes it doesn't work out -- sometimes a client can only understand XML or some proprietary protocol, but starting simple & adding complexity makes life easier.

  • 1
    Thanks for that awesome answer. Adding on the the "breaking changes" part of the discussion, why not version your entire API for each release. You could keep the older API alive for some additional time after a new release so that older clients have time to migrate. Example: /api/v1/... and /api/v2/.. stay alive for an overlapping time period. This will avoid cluttering the JSON with too many additional fields to prevent breaking. – nknj Mar 12 '14 at 11:12
3

This is very common and helps with when you want to design a mobile app. Since your application will already be "resource oriented" instead of being focused on generating data with the html/visual layer attached.

I recommend http://django-rest-framework.org/ for the Django side, I've contributed and also use it daily. Helps provide a lot of the building blocks on top of Django that make decoupling easy and powerful.

As for the oAuth, you can, you don't have to. If you check that website it even shows you to how to set up oAuth with the API. You can easily just use Username/Password authentication as it is defaulted to. Just have the angular app send the username/password combo to the endpoint, which will reply with a "token". As long as your app is hosted using good TLS () the token is safe. You can easily add a method for refreshing tokens for more security.

  • Thanks, so what is your recommendation on the login process? If I dont use oAuth what can I use? – nknj Mar 11 '14 at 20:16
  • 2
    I updated my comment with a suggestion. Go ahead and just use what it defaults to. Send in a username/password and get back the token, which you can use for TokenAuthentication across your Django Rest Framework views/viewsets. – stormlifter Mar 11 '14 at 20:19
  • That does sound a lot simpler than oAuth. But I guess there is a reason oAuth does all the things it does. I will look into that. Thanks for the headstart :) – nknj Mar 12 '14 at 11:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.