Best Practices for securing a REST API / web service
When designing a REST API or service are there any established best practices for dealing with security (Authentication, Authorization, Identity Management) ?
When building a SOAP API you have WS-Security as a guide and much literature exists on the topic. I have found less information about securing REST endpoints.
While I understand REST intentionally does not have specifications analogous to WS-* I am hoping best practices or recommended patterns have emerged.
Any discussion or links to relevant documents would be very much appreciated. If it matters, we would be using WCF with POX/JSON serialized messages for our REST API's/Services built using v3.5 of the .NET Framework.
As tweakt said, Amazon S3 is a good model to work with. Their request signatures do have some features (such as incorporating a timestamp) that help guard against both accidental and malicious request replaying.
The nice thing about HTTP Basic is that virtually all HTTP libraries support it. You will, of course, need to require SSL in this case because sending plaintext passwords over the net is almost universally a bad thing. Basic is preferable to Digest when using SSL because even if the caller already knows that credentials are required, Digest requires an extra roundtrip to exchange the nonce value. With Basic, the callers simply sends the credentials the first time.
Once the identity of the client is established, authorization is really just an implementation problem. However, you could delegate the authorization to some other component with an existing authorization model. Again the nice thing about Basic here is your server ends up with a plaintext copy of the client's password that you can simply pass on to another component within your infrastructure as needed.
Read more... Read less...
There are no standards for REST other than HTTP. There are established REST services out there. I suggest you take a peek at them and get a feel for how they work.
For example, we borrowed a lot of ideas from Amazon's S3 REST service when developing our own. But we opted not to use the more advanced security model based on request signatures. The simpler approach is HTTP Basic auth over SSL. You have to decide what works best in your situation.
Also, I highly recommend the book RESTful Web Services from O'reilly. It explains the core concepts and does provide some best practices. You can generally take the model they provide and map it to your own application.
You may also want to take a look at OAuth, an emerging open protocol for token-based authorization specifically targeting http apis.
There is a great checklist found on Github:
Don't reinvent the wheel in Authentication, token generation, password storage. Use the standards.
Max Retryand jail features in Login.
Use encryption on all sensitive data.
JWT (JSON Web Token)
Use a random complicated key (JWT Secret) to make brute forcing the token very hard.
Don't extract the algorithm from the payload. Force the algorithm in the backend (HS256 or RS256).
Make token expiration (
RTTL) as short as possible.
Don't store sensitive data in the
JWTpayload, it can be decoded easily.
redirect_uriserver-side to allow only whitelisted URLs.
Always try to exchange for code and not tokens (don't allow
Use state parameter with a random hash to prevent
Define the default scope, and validate scope parameters for each application.
Limit requests (Throttling) to avoid DDoS / brute-force attacks.
Use HTTPS on server side to avoid MITM (Man In The Middle Attack)
HSTSheader with SSL to avoid SSL Strip attack.
Use the proper HTTP method according to the operation:
DELETE(to delete a record), and respond with
405 Method Not Allowedif the requested method isn't appropriate for the requested resource.
Validate content-type on request
Acceptheader (Content Negotiation) to allow only your supported format (e.g.
application/json, etc) and respond with
406 Not Acceptableresponse if not matched.
content-typeof posted data as you accept (e.g.
Validate User input to avoid common vulnerabilities (e.g. XSS, SQL-Injection, Remote Code Execution, etc).
Don't use any sensitive data (credentials, Passwords, security tokens, or API keys) in the URL, but use standard
Use an API Gateway service to enable caching,
Rate Limitpolicies (e.g. Quota, Spike Arrest, Concurrent Rate Limit) and deploy APIs resources dynamically.
Check if all the endpoints are protected behind authentication to avoid broken authentication process.
User own resource ID should be avoided. Use /me/orders instead of /user/654321/orders.
Don't auto-increment IDs. Use UUID instead.
If you are parsing XML files, make sure entity parsing is not enabled to avoid XXE (XML external entity attack).
If you are parsing XML files, make sure entity expansion is not enabled to avoid Billion Laughs/XML bomb via exponential entity expansion attack.
Use a CDN for file uploads.
If you are dealing with huge amount of data, use Workers and Queues to process as much as possible in background and return response fast to avoid HTTP Blocking.
Do not forget to turn the DEBUG mode OFF.
Content-Security-Policy: default-src 'none'header.
Remove fingerprinting headers -
content-typefor your response, if you return
application/jsonthen your response content-type is
Don't return sensitive data like credentials, Passwords, security tokens.
Return the proper status code according to the operation completed. (e.g.
400 Bad Request,
405 Method Not Allowed, etc).
I'm kind of surprised SSL with client certificates hasn't been mentioned yet. Granted, this approach is only really useful if you can count on the community of users being identified by certificates. But a number of governments/companies do issue them to their users. The user doesn't have to worry about creating yet another username/password combination, and the identity is established on each and every connection so communication with the server can be entirely stateless, no user sessions required. (Not to imply that any/all of the other solutions mentioned require sessions)
Everyone in these answers has overlooked true access control / authorization.
If for instance your REST APIs / web services are about POSTing / GETing medical records, you may want to define access control policie about who can access the data and under which circumstances. For instance:
- doctors can GET the medical record of a patient they have a care relationship with
- no one can POST medical data outside practice hours (e.g. 9 to 5)
- end-users can GET medical records they own or medical records of patients for whom they are the guardian
- nurses can UPDATE the medical record of a patient that belongs to the same unit as the nurse.
In order to define and implement those fine-grained authorizations, you will need to use an attribute-based access control language called XACML, the eXtensible Access Control Markup Language.
The other standards here are for the following:
- OAuth: id. federation and delegation of authorization e.g. letting a service act on my behalf on another service (Facebook can post to my Twitter)
- SAML: identity federation / web SSO. SAML is very much about who the user is.
- WS-Security / WS-* standards: these focus on the communication between SOAP services. They are specific to the application-level messaging format (SOAP) and they deal with aspects of messaging e.g. reliability, security, confidentiality, integrity, atomicity, eventing... None cover access control and all are specific to SOAP.
XACML is technology-agnostic. It can be applied to java apps, .NET, Python, Ruby... web services, REST APIs, and more.
The following are interesting resources: