Restful authentication for non browser consumers

2019-09-19 05:25发布

问题:

I have a web service written as an ASP MVC application which basically uses rolling cookies as its authentication mechanism. So someone sends their username and password over https to the service, it then verifies them and issues them a cookie containing a token, user identifier and timestamp as HTTPONLY and SECURE. Then whenever the users need to access pages which require authentication the cookie is sent over and verified with the timestamp and the token against the user, assuming that passes it then issues a new timestamp and sends it back down to the user.

This method works to date and although there are still possibilities of CSRF (reduced by the rolling timestamp) and a few other vulnerabilities it is a risk that the current project team are willing to live with, there is a big technical debt card to look into better ways, but thats for another discussion, as our main goal was a stateless service so it could scale easily.

Anyway that all to one side, the issue now is that we have been asked to expose data to other 3rd parties from the service. They however wont be consuming this data like a normal user with a browser, but as an application of some kind on any sort of platform. So now I am wondering if there is some better way for application based consumers authenticate themselves, as currently they would need to send a http request to authenticate, then take the returned cookie, and send it over for restricted requests. However the other 3rd parties then need to keep juggling this cookie whenever they want to get data from our system, which seems a bit of a pain for them.

So is there another way I cannot see to accomplish this? as the 2 ways I can see to keep it stateless are to send some token over on the querystring each time, which again would require them to authenticate and store it, and would make the querystring a bit less clean. Then the other way is as we currently do it using cookies as the state mechanism.

回答1:

If you're genuinely concerned with keeping your API RESTful, sending credentials on the querystring is definitely a no-no, since in REST the whole URI is an opaque identifier for a resource, and using cookies is an unnecessary coupling between the service and HTTP. The correct way to authenticate would be whatever is allowed and standardized by the protocol, so, in your case, through the WWW-Authenticate and Authorization headers. The clients should send their username and password in an Authorization: Basic header on every request (always use SSL, of course).

If you really want to use a token after the client is authenticated with username:password, you can also accept it as a custom authorization scheme, in the same header. For instance, something like:

Authorization: MyCompany apitoken="12k9023nd02890382n8902"

Whenever you're in doubt about what's the RESTful way to do something, just think what's the standard for the protocol you're using. That's one of the constraints behind REST. Whenever you have to document something that is replacing an standardized functionality, you're doing it wrong. If the standard isn't enough for your needs, it's fine to add something, like the custom auth scheme with the token here.