Authorization & authentication via web services

I am working on web api that should allow user to authorize and authenticate via this services(both SOAP and RESTful services).

Idea is that users should login first via web services, and I would return sessionId to client, and client would use this sessionId in all upcoming request.

On server side, I would check if user provided sessionId, and if yes, I would start new session with this sessionId(off course I would add some protection latter against session hijack, like storing ip adress together with session).

So, to do this I would extend CWebUser, change init() method and add new method called restoreFromSession(), that would be similar like restoreFromCookie method. All this sound good, but the problem is that I planned that sessionId to be sent via Rest or SOAP content, so it need to be parsed, and to extract this parameter, and that happen after WebUser component is initialized, and it should be before, because session_id, must be set before session_start(or Yii::app()->getSession()->open()).

I could solve this issue, but it looks like it will require many modifications, so maybe my approach is wrong.

So, my finall question is, can somebody suggest better idea, how to authenticate/authorized users for accessing web api?

Maybe this post from tri gives you some idea - http://www.yiiframework.com/forum/index.php?/topic/7106-authentication-web-service/page__view__findpost__p__36247

Thanks for link, but in post user are sending username/password with every request to server(so they need to store username/password in their client), and I want to avoid that(if possible).

I know that this post is old but I have the same issue as Ivica and there is hardly any information out there on how to solve this elegantly with Yii. The idea is to write a huge part of my app to solely serve JSON to do client side rendering after initial pages were rendered server side. This would be done by calling a Yii REST api via JS. I don’t want to send username/password on each request. Has anyone build something like that with Yii already? I would highly appreciate any information or opinion on this.

Thanks,

Hannes

I searched for solutions for this problem when I was playing with a REST extension some time ago. Basically, you have to send something to the server on each request. This might be Username/Password, a digest hash or a session id (or whatever else you think is appropriate). Question is where to put that information.

I my opinion, it shouldn’t affect the API:




  // Bad

  public function actionGreet( $authHash )

  {

    return $this->validateUser( $authHash )

      ? 'Hi ' . Yii::app()->user->name . '!'

      : "Hello, do we know each other?";

  }



And it also shouldn’t be part of the Url:




  // also bad

  https://yourdomain.com/service/greet/?authHash=abcdef12345



So, what else can you do? Obviously, there is http auth, but first: I really liked this answer on stackoverflow: restful-authentication

It basically suggests not to use http auth, because of the problem that you can’t “log out” and because of the ugly browser generated login windows which you cannot customize (the related question is specifically about browser clients). Instead, it suggests to use cookies. The cookie content can be set by the server, and the client will send it back to server with each request, without modifying request url.

If you’re planning to write a javascript client, you can control if the auth headers will be set for the request. And you can also generate a nice login dialog. So these points might not affect you. Only drawback might be, that you not only had to configure your web service, but also your webserver. If you want to avoid that, the cookies approach might be worth a try. If you don’t mind configuring your web server for the service, I’d stay with http auth.

Important thing is only to keep auth related stuff away from your service implementation, both to keep service impl. clean and you have the chance to change auth mechanism later.

Removing auth info (whatever it is - user/pass, hash, …) from message body and putting it into http headers or cookie also eliminates the problems ivica faced. Particularly when using cookies, CWebUser might work as is, since it already provides the restoreFromCookie() method.

Hi Ben and thanks for your reply and your link to the stackoverflow thread.

When using the app via browser it would work like this:

1.) Initial request to app => classic server side authentication as always, complete page gets rendered with auth info stored in cookie.

2.) Using Backbone.js on the client side to update parts of the page by calling the REST API (auth stuff sent via header on every request over https) which will respond with JSON.

But I also want to make the API public from the first day which would lead to API keys etc. and this is where things get complicated. Here’s another good article on how to secure your REST API without the complexity of OAuth: http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication. It seems to be a pretty interesting approach.

EDIT: As mentioned in the article I linked to above this basically works like 2-legged OAuth. There hardly is any information on how to use 2-legged OAuth with PHP despite this example using PDO: http://code.google.com/p/oauth2-php/source/browse/#hg%2Fserver%2Fexamples%2Fpdo%3Fstate%3Dclosed

I guess one could create an OAuth server this way

Jep, I remember that article. Also stumbled over it when searching for REST auth. ^^

But honestly, I’m not sure how much the added complexity is worth. Considering that your API is much more likely to be used when it is easy to be used, just stick with user/password or sessionId or something else very simple. At least if you can make you web service available through https only. If the whole connection is secure, you don’t have to worry about user/passwords being sent as “plain text” (it will be encrypted anyways).

If you plan to communicate over plain http, this is obviously another story. ;)