834

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.

Jakub Kubrynski
  • 12,678
  • 4
  • 56
  • 80
Nathan
  • 12,160
  • 3
  • 25
  • 27

18 Answers18

301

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.

Greg Hewgill
  • 828,234
  • 170
  • 1,097
  • 1,237
  • 3
    SSL is an important part of security, but not all applications require that level of encryption. If someone steals in-transit what you are going to post publicly on Twitter, is that such a significant drawback? For the majority of API's SSL encryption is going to be preferred. The infrastructure requirements of SSL are somewhat higher than with plaintext and no intermediate (read here edge based) caching servers can participate in the caching of repeatedly accessed content. Beware, your scalability may suffer if you absolutely require the encryption offered. – Norman H Jan 01 '13 at 22:19
  • 36
    @NormanH: Your argument is specious, because if somebody can see the entire transaction that I use to post to Twitter, then they could therefore impersonate me and post their own messages under my name. – Greg Hewgill Jan 02 '13 at 00:51
  • @GregHewgill yes, I did consider that, however authentication tokens could be encrypted even though the entire channel is not SSL encrypted. – Norman H Jan 02 '13 at 18:11
  • 3
    Quoting from wikipedia on Digest authentication, "Digest access authentication is one of the agreed-upon methods a web server can use to negotiate credentials with a user's web browser. It applies a hash function to a password before sending it over the network, which is safer than basic access authentication, which sends plaintext." which would be one standard way of accomplishing what I alluded to above. (See http://en.wikipedia.org/wiki/Digest_access_authentication for the details) – Norman H Jan 02 '13 at 18:45
  • @WillSargent The BuzzFeed article is phenomenal - great resource. One gotcha that I hadn't considered is to not put authentication tokens of any sort into the URL or parameters - these could get captured in the server's access logs. – Kevin Day Feb 12 '14 at 03:38
  • 6
    `"sending plaintext passwords over the net is almost universally a bad thing"` - Can you elaborate on the "almost"? When is it not a bad idea? – toniedzwiedz May 29 '14 at 05:23
  • @Tom: Perhaps in situations such as within a private network it might be okay. Also, various systems send plaintext passwords over email all the time (still not a good idea, but it happens). – Greg Hewgill May 29 '14 at 07:46
  • 2
    @GregHewgill even in a private network, I wouldn't want my users to be able to intercept each others' passwords. The only situation I can think of, in which it's OK to send a password over a network is when the user is alone in the network. The fact that such things happen elsewhere is hardly a reason to allow it. – toniedzwiedz May 29 '14 at 08:53
  • 2
    If you use ssl, you don't need to care about replay attacks. See: http://security.stackexchange.com/questions/20105/are-ssl-encrypted-requests-vulnerable-to-replay-attacks – guettli Jul 09 '14 at 10:42
  • @guettli that is not 100% correct. SSL establishes a secure connection but does not prevent to replay messages inside that connection. It prevents to replay a dump collected with a sniffer, but if someone can decrypt the original message (not that hard) then it is possible to rebuild the messages (or create new) and resend the messages, unless some king of message level security is used. SSL by itself is not very secure. – nflash Jun 29 '15 at 15:40
  • 2
    @nflash please provide details. Your quote "SSL by itself is not very secure" is very vague. How can you decrypt the original message? I don't get why you say this is not that hard. – guettli Jun 30 '15 at 19:34
  • @guettli just by using SSL doesn't mean your app is secure. I see lots of (mobile) developers ignoring Certificate Validation... even if they validate the certificate in an environment controlled by others there are ways to go around this and allow a man in the middle (I have seen and done this in a controlled environment with out of the box tools and without much knowledge about the subject). That’s why I say that SSL by itself is not very secure, but is one of the security layers that you should use – nflash Jul 05 '15 at 14:23
  • @nflash I am still missing an explanation of "SSL establishes a secure connection but does not prevent to replay messages inside that connection." and "but if someone can decrypt the original message (not that hard)" – guettli Jul 07 '15 at 07:00
  • @guettli a comment does not allow enough chareters for giving a more detail answer. look for Man in the middle or SSL proxy and you will see how to capture and decrypt messages inside a secure channel (easy with some control over the enviorment). If the messages itself are not authenticated or secured in someway you will be able to reconstruct the message and replay it or even change it and send it. Certitificate validation plays a key role in SSL and if you overcome this then the secure channel is no longer secure. – nflash Aug 21 '15 at 11:10
  • 1
    @nflash I know that it is possible. But it is hard. Running http://mitmproxy.org/ is very easy. But first you need run the proxy between the client and the server. Next you need a valid cert for the requested domain. I wouldn't call this "not that hard". It is possible, but not easy. – guettli Aug 21 '15 at 11:25
  • 1
    @guettli as I said: "I see lots of (mobile) developers ignoring Certificate Validation... even if they validate the certificate in an environment controlled by others there are ways to go around this and allow a man in the middle". If you controll the enviorment you can easly install certificates as trusted. In the cases where certificate validation is ignored you don't even have to do this. – nflash Aug 24 '15 at 09:36
  • 2
    @NormanH: yes, seeing somebody's tweets before they are published is no big deal but with no cryptographic protection, the attacker can also modify them. And that IS a big deal. – Roman Plášil Apr 23 '16 at 02:30
117

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.

Macke
  • 22,774
  • 6
  • 76
  • 108
Mark Renouf
  • 29,573
  • 19
  • 89
  • 120
  • 6
    RESTful Web Services is definitely a great book. A must read in this area. It was downright inspiring. – EdgarVerona Jan 09 '09 at 21:34
  • 6
    How is it that @aehlke has received so many upvotes for that comment considering (1) there is no such thing as a REST specification and (2) the Fielding Dissertation on the Architectural Styles and the Design of Network-based Software Architectures explicitly mentions REST and HTTP in 6.3: REST Applied to HTTP. –  Apr 15 '12 at 00:37
  • 20
    HTTP is not a requirement for REST. – nategood May 16 '13 at 19:21
  • 1
    The RESTful Web Services book is available for free from their website: https://www.crummy.com/writing/RESTful-Web-Services/ – icc97 Jun 05 '18 at 15:08
  • I was planning to read the book and then I realized it is mainly targetted for XML format. Should I use this book considering the popularity of JSON? Or it is not dependent on the Data Interchange Format. Need guidance. – Bhargav Jhaveri Jul 14 '18 at 00:43
  • rest functionality is not coupled with the format of the data – yolob 21 May 31 '19 at 09:46
72

You may also want to take a look at OAuth, an emerging open protocol for token-based authorization specifically targeting http apis.

It is very similar to the approach taken by flickr and remember the milk "rest" apis (not necessarily good examples of restful apis, but good examples of the token-based approach).

John Spurlock
  • 1,703
  • 1
  • 13
  • 12
  • 3
    But it seems that 2-legged oAuth, which i think is what is need here, isn't covered (lack of info) as much as the 3-legged one. – redben Nov 11 '10 at 00:04
  • 4
    OAuth is about delegation of authorization i.e. I the owner of the information / account let service A interact with my data on service B (e.g. I let Twitter write on my facebook). It's not authorization in the broader sense which is about controlling what users can do on resources (data, information, services...). This is where XACML steps in. XACML lets you define authorization policies about who can do what. – David Brossard Sep 24 '13 at 22:15
65

There is a great checklist found on Github:

Authentication

  • Don't reinvent the wheel in Authentication, token generation, password storage. Use the standards.

  • Use Max Retry and 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 (TTL, RTTL) as short as possible.

  • Don't store sensitive data in the JWT payload, it can be decoded easily.

OAuth

  • Always validate redirect_uri server-side to allow only whitelisted URLs.

  • Always try to exchange for code and not tokens (don't allow response_type=token).

  • Use state parameter with a random hash to prevent CSRF on the OAuth authentication process.

  • Define the default scope, and validate scope parameters for each application.

Access

  • Limit requests (Throttling) to avoid DDoS / brute-force attacks.

  • Use HTTPS on server side to avoid MITM (Man In The Middle Attack)

  • Use HSTS header with SSL to avoid SSL Strip attack.

Input

  • Use the proper HTTP method according to the operation: GET (read), POST (create), PUT/PATCH (replace/update), and DELETE (to delete a record), and respond with 405 Method Not Allowed if the requested method isn't appropriate for the requested resource.

  • Validate content-type on request Accept header (Content Negotiation) to allow only your supported format (e.g. application/xml, application/json, etc) and respond with 406 Not Acceptable response if not matched.

  • Validate content-type of posted data as you accept (e.g. application/x-www-form-urlencoded, multipart/form-data, application/json, etc).

  • 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 Authorization header.

  • Use an API Gateway service to enable caching, Rate Limit policies (e.g. Quota, Spike Arrest, Concurrent Rate Limit) and deploy APIs resources dynamically.

Processing

  • 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.

Output

  • Send X-Content-Type-Options: nosniff header.

  • Send X-Frame-Options: deny header.

  • Send Content-Security-Policy: default-src 'none' header.

  • Remove fingerprinting headers - X-Powered-By, Server, X-AspNet-Version etc.

  • Force content-type for your response, if you return application/json then your response content-type is application/json.

  • Don't return sensitive data like credentials, Passwords, security tokens.

  • Return the proper status code according to the operation completed. (e.g. 200 OK, 400 Bad Request, 401 Unauthorized, 405 Method Not Allowed, etc).

Andrejs
  • 8,412
  • 4
  • 38
  • 42
  • 1
    Nice list, though a bit opinionated - and it starts with a nonsense imho: "Don't use Basic Auth Use standard authentication (e.g. JWT, OAuth)." You can't get more standard-y than Basic Auth, and it has its place, especially for APIs where the clients are not browsers (for browsers JWT is usually more suitable). OAuth on the other hand is using a whole other set of compromises for authentication and is not really comparable to Basic Auth and JWT. – johndodo Dec 24 '17 at 19:43
  • You're right, BasicAuth with HTTPS is common, but it is hotly debated - https://security.stackexchange.com/questions/988/is-basic-auth-secure-if-done-over-https . I will remove this point anyway. – Andrejs Dec 28 '17 at 16:38
43

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)

stinkymatt
  • 1,638
  • 11
  • 14
  • We actually do use this for some integrations as well as encrypted vpn tunnels to support older systems that we don't control that can not communicate over https. – Casey Sep 05 '12 at 13:55
  • Client certs can make trouble when you need load balancing... it can be done, but it's less straight-forward. – Jeremy Logan Oct 15 '12 at 18:11
  • 2
    @fiXedd - The opposite has been my experience with client certs because they are truly stateless. Client cert authenticated connections can be load balanced with a dumb load balancer with no regard to connection stickyness because they require absolutely zero shared state between the client and server. – stinkymatt Oct 15 '12 at 19:25
  • 4
    Oh, you can do it.... you can just have the load balancer forward the TCP traffic, but you can't, for instance, have the load balancer be the termination point for the SSL. – Jeremy Logan Oct 19 '12 at 16:12
  • Is it still secure if the client certificates and its root authority are self-signed? The root authority will be imported into the client's trusted root certificate authorities. – Joyce Mar 18 '15 at 17:17
39

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:

David Brossard
  • 12,223
  • 6
  • 42
  • 72
  • 2
    I don't understand why can't you just implement token system that will get the user and his permissions which will essentially be the same thing? – Stan Dec 31 '13 at 15:23
  • You can take a token-based approach. That works well too but you still need the logic that defines which permissions users get, in other words, which permissions to insert inside the token. That's what XACML can help you achieve. It also avoids token bloat. – David Brossard Jan 02 '14 at 07:44
  • 2
    As a side comment, what does "9 to 5" contribute to security? As if attackers are only active at night? Not to speak of the severe usage implications, as if doctors only work "9 to 5". – Roland Jul 11 '16 at 13:43
  • That's a common requirement in healthcare scenarios. Check out HL7 for instance. There are break-the-glass scenarios too in case a doctor does need access outside hours. As for hackers, once they're in all bets are off – David Brossard Jul 11 '16 at 14:44
  • @DavidBrossard If you have not yet, I would have a look at block chain solutions for handling permissions. – Simply G. May 09 '18 at 10:15
  • 1
    Some of my colleagues are investigating that indeed. Thanks @SimplyG. – David Brossard May 09 '18 at 12:00
25

I've used OAuth a few times, and also used some other methods (BASIC/DIGEST). I wholeheartedly suggest OAuth. The following link is the best tutorial I've seen on using OAuth:

http://hueniverse.com/oauth/guide/

Derek Lee
  • 2,852
  • 3
  • 24
  • 32
Rob Ottaway
  • 604
  • 5
  • 9
  • Although this is a very old answer relating to OAuth 1.0, it's worth noting that the author of the link you cite [had this to say about OAuth 2.0](https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529): _"I reached the conclusion that OAuth 2.0 is a bad protocol...When compared with OAuth 1.0, the 2.0 specification is more complex, less interoperable, less useful, more incomplete, and most importantly, less secure."_. To be clear, the comment I am quoting was made several years after you posted your answer. – skomisa Jan 22 '19 at 20:29
17

One of the best posts I've ever come across regarding Security as it relates to REST is over at 1 RainDrop. The MySpace API's use OAuth also for security and you have full access to their custom channels in the RestChess code, which I did a lot of exploration with. This was demo'd at Mix and you can find the posting here.

degnome
  • 253
  • 1
  • 7
  • Thanks for the link (1 RainDrop) - very interesting discussion of security as it relates to SOAP v REST – Nathan Oct 13 '08 at 23:07
15

Thanks for the excellent advice. We ended up using a custom HTTP header to pass an identity token from the client to the service, in preparation for integrating our RESTful API with the the upcoming Zermatt Identity framework from Microsoft. I have described the problem here and our solution here. I also took tweakt's advice and bought RESTful Web Services - a very good book if you're building a RESTful API of any kind.

Community
  • 1
  • 1
Nathan
  • 12,160
  • 3
  • 25
  • 27
  • 1
    This approach sounds fishy to me. What prevents an attacker from using the identity token to masquerade the client? HTTPS doesn't protect the URL or headers the last time I checked... – Gili Oct 03 '08 at 18:10
  • 2
    Hmmm...not sure you're right about that. I believe that except for the few headers required to understand what kind of encryption is required, all other headers are encrypted. – Nathan Oct 29 '08 at 23:23
  • 51
    That is wrong. HTTPS protects EVERYTHING. It goes: TCP handshake... TLS handshake... GET /foo 200 OK... teardown . – Mark Renouf Feb 04 '09 at 13:31
  • I also used custom headers to pass a token. – TarasB Jan 25 '11 at 11:22
  • 1
    Note that you can also pass a token as a cookie (instead of a custom header). This behaves well in browsers as it uses an HTTP header with standard behaviours in most toolkits and applications. On the service side, the cookie does not have to relate to a session, you can use it to communicate any token you wish. – Bruce Alderson Nov 10 '11 at 19:51
  • Nathan, your problem and solution links on the githubs are gone. Do you have planned to post them back somewhere? Thx. – Win Myo Htet Mar 13 '12 at 22:57
  • I'm sorry I don't - I don't work with .NET anymore and let my .NET blog hosting lapse, so alas they are gone forever. Sorry. – Nathan Mar 14 '12 at 18:40
  • 11
    The Wayback Machine is a beautiful thing: [problem description](http://web.archive.org/web/20110525082448/http://www.thefreakparade.com/2008/09/flowing-identity-from-a-client-to-a-service-when-using-restful-wcf-part-1-the-problem/) and [solution](http://web.archive.org/web/20110525082818/http://www.thefreakparade.com/2008/09/flowing-identity-from-a-client-to-a-service-when-using-restful-wcf-part-2-a-solution/) – cjc343 Oct 23 '12 at 20:03
14

OWASP(Open Web Application Security Project) has some cheat sheets covering about all aspects of Web Application development. This Project is a very valuable and reliable source of information. Regarding REST services you can check this: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet

WelsonJR
  • 289
  • 3
  • 5
7

I would recommend OAuth 2/3. You can find more information at http://oauth.net/2/

Abhijit Gaikwad
  • 2,904
  • 25
  • 37
  • 8
    Care to elaborate why would you recommend version 2 when it remains largely incomplete? IMHO, version 1.0a remains a solid solution for most apps. – Butifarra Mar 20 '13 at 22:57
6

I searched a lot about restful ws security and we also ended up with using token via cookie from client to server to authenticate the requests . I used spring security for authorization of requests in service because I had to authenticate and authorized each request based on specified security policies that has already been in DB.

6

The fact that the SOAP world is pretty well covered with security standards doesn't mean that it's secure by default. In the first place, the standards are very complex. Complexity is not a very good friend of security and implementation vulnerabilities such as XML signature wrapping attacks are endemic here.

As for the .NET environment I won't help much, but “Building web services with Java” (a brick with ~10 authors) did help me a lot in understanding the WS-* security architecture and, especially, its quirks.

kravietz
  • 8,571
  • 1
  • 30
  • 24
4

REST itself offers no security standards, but things like OAuth and SAML are rapidly becoming the standards in this space. However, authentication and authorization are only a small part of what you need to consider. Many of the known vulnerabilities relating to web applications apply very much to REST apis. You have to consider input validation, session cracking, inappropriate error messages, internal employee vulnerabilities and so on. It is a big subject.

Robert Morschel
  • 331
  • 2
  • 11
4

I want to add(in line with stinkeymatt), simplest solution would be to add SSL certificates to your site. In other words, make sure your url is HTTPS://. That will cover your transport security (bang for the buck). With RESTful url's, idea is to keep it simple (unlike WS* security/SAML), you can use oAuth2/openID connect or even Basic Auth (in simple cases). But you will still need SSL/HTTPS. Please check ASP.NET Web API 2 security here: http://www.asp.net/web-api/overview/security (Articles and Videos)

Manish Jain
  • 8,990
  • 5
  • 35
  • 39
3

As @Nathan ended up with which is a simple HTTP Header, and some had said OAuth2 and client side SSL certificates. The gist of it is this... your REST API shouldn't have to handle security as that should really be outside the scope of the API.

Instead a security layer should be put on top of it, whether it is an HTTP Header behind a web proxy (a common approach like SiteMinder, Zermatt or even Apache HTTPd), or as complicated as OAuth 2.

The key thing is the requests should work without any end-user interaction. All that is needed is to ensure that the connection to the REST API is authenticated. In Java EE we have the notion of a userPrincipal that can be obtained on an HttpServletRequest. It is also managed in the deployment descriptor that a URL pattern can be secure so the REST API code does not need to check anymore.

In the WCF world, I would use ServiceSecurityContext.Current to get the current security context. You need to configure you application to require authentication.

There is one exception to the statement I had above and that's the use of a nonce to prevent replays (which can be attacks or someone just submitting the same data twice). That part can only be handled in the application layer.

Archimedes Trajano
  • 22,850
  • 10
  • 113
  • 154
3

For Web Application Security, you should take a look at OWASP (https://www.owasp.org/index.php/Main_Page) which provides cheatsheets for various security attacks. You can incorporate as many measures as possible to secure your Application. With respect to API security (authorization, authentication, identity management), there are multiple ways as already mentioned (Basic,Digest and OAuth). There are loop holes in OAuth1.0, so you can use OAuth1.0a (OAuth2.0 is not widely adopted due to concerns with the specification)

java_geek
  • 15,768
  • 29
  • 82
  • 105
2

It's been a while but the question is still relevant, though the answer might have changed a bit.

An API Gateway would be a flexible and highly configurable solution. I tested and used KONG quite a bit and really liked what I saw. KONG provides an admin REST API of its own which you can use to manage users.

Express-gateway.io is more recent and is also an API Gateway.

Matt Bannert
  • 25,237
  • 34
  • 134
  • 195