REST API Login Pattern

2019-01-12 13:28发布

问题:

I am creating a REST api, closely following apigee suggestions, using nouns not verbs, api version baked into the url, two api paths per collection, GET POST PUT DELETE usage, etc.

I am working on the login system, but unsure of the proper REST way to login users. I am not working on security at this point, just the login pattern or flow. (Later we will be adding 2 step oAuth, with an HMAC, etc)

Possible Options

  • A POST to something like https://api...com/v1/login.json
  • A PUT to something like https://api...com/v1/users.json
  • Something I have not though of...

What is the proper REST style for logging in users?

回答1:

Principled Design of the Modern Web Architecture by Roy T. Fielding and Richard N. Taylor, i.e. sequence of works from all REST terminology came from, contains definition of client-server interaction:

All REST interactions are stateless. That is, each request contains all of the information necessary for a connector to understand the request, independent of any requests that may have preceded it.

This restriction accomplishes four functions, 1st and 3rd are important in this particular case:

  • 1st: it removes any need for the connectors to retain application state between requests, thus reducing consumption of physical resources and improving scalability;
  • 3rd: it allows an intermediary to view and understand a request in isolation, which may be necessary when services are dynamically rearranged;

And now lets go back to your security case. Every single request should contains all required information, and authorization/authentication is not an exception. How to achieve this? Literally send all required information over wires with every request.

One of examples how to archeive this is hash-based message authentication code or HMAC. In practice this means adding a hash code of current message to every request. Hash code calculated by cryptographic hash function in combination with a secret cryptographic key. Cryptographic hash function is either predefined or part of code-on-demand REST conception (for example JavaScript). Secret cryptographic key should be provided by server to client as resource, and client uses it to calculate hash code for every request.

There are a lot of examples of HMAC implementations, but I'd like you to pay attention to the following three:

  • Authenticating REST Requests for Amazon Simple Storage Service (Amazon S3)
  • Answer by Mauriceless on quiestion: "How to implement HMAC Authentication in a RESTful WCF API"
  • crypto-js: JavaScript implementations of standard and secure cryptographic algorithms

How it works in practice

If client knows the secret key, then it's ready to operate with resources. Otherwise he will be temporarily redirected (status code 307 Temporary Redirect) to authorize and to get secret key, and then redirected back to the original resource. In this case there is no need to know beforehand (i.e. hardcode somewhere) what the URL to authorize the client is, and it possible to adjust this schema with time.

Hope this will helps you to find the proper solution!



回答2:

TL;DR Login for each request is not a required component to implement API security, authentication is.

It is hard to answer your question about login without talking about security in general. With some authentication schemes, there's no traditional login.

REST does not dictate any security rules, but the most common implementation in practice is OAuth with 3-way authentication (as you've mentioned in your question). There is no log-in per se, at least not with each API request. With 3-way auth, you just use tokens.

  1. User approves API client and grants permission to make requests in the form of a long-lived token
  2. Api client obtains a short-lived token by using the long-lived one.
  3. Api client sends the short-lived token with each request.

This scheme gives the user the option to revoke access at any time. Practially all publicly available RESTful APIs I've seen use OAuth to implement this.

I just don't think you should frame your problem (and question) in terms of login, but rather think about securing the API in general.

For further info on authentication of REST APIs in general, you can look at the following resources:

  • http://www.infoq.com/news/2010/01/rest-api-authentication-schemes
  • REST API Authentication
  • RESTful API Authentication


回答3:

A big part of the REST philosophy is to exploit as many standard features of the HTTP protocol as possible when designing your API. Applying that philosophy to authentication, client and server would utilize standard HTTP authentication features in the API.

Login screens are great for human user use cases: visit a login screen, provide user/password, set a cookie, client provides that cookie in all future requests. Humans using web browsers can't be expected to provide a user id and password with each individual HTTP request.

But for a REST API, a login screen and session cookies are not strictly necessary, since each request can include credentials without impacting a human user; and if the client does not cooperate at any time, a 401 "unauthorized" response can be given. RFC 2617 describes authentication support in HTTP.

TLS (HTTPS) would also be an option, and would allow authentication of the client to the server (and vice versa) in every request by verifying the public key of the other party. Additionally this secures the channel for a bonus. Of course, a keypair exchange prior to communication is necessary to do this. (Note, this is specifically about identifying/authenticating the user with TLS. Securing the channel by using TLS / Diffie-Hellman is always a good idea, even if you don't identify the user by its public key.)

An example: suppose that an OAuth token is your complete login credentials. Once the client has the OAuth token, it could be provided as the user id in standard HTTP authentication with each request. The server could verify the token on first use and cache the result of the check with a time-to-live that gets renewed with each request. Any request requiring authentication returns 401 if not provided.