REST API Security Essentials

REST API Security isn’t an afterthought. It has to be an integral part of any development project and also for REST APIs. Lets discuss the security principles for REST.

REST API Security isn’t an afterthought. It has to be an integral part of any development project and also for REST APIs.

There are multiple ways to secure a RESTful API e.g. basic auth, OAuth, etc. but one thing is sure that RESTful APIs should be stateless – so request authentication/authorization should not depend on sessions.

Instead, each API request should come with some sort of authentication credentials that must be validated on the server for every request.

1. REST Security Design Principles

The paper “The Protection of Information in Computer Systems” by Jerome Saltzer and Michael Schroeder, put forth eight design principles for securing information in computer systems, as described in the following sections:

  • Least Privilege: An entity should only have the required set of permissions to perform the actions for which they are authorized, and no more. Permissions can be added as needed and should be revoked when no longer in use.
  • Fail-Safe Defaults: A user’s default access level to any resource in the system should be “denied” unless they’ve been granted a “permit” explicitly.
  • The economy of Mechanism: The design should be as simple as possible. All the component interfaces and the interactions between them should be simple enough to understand.
  • Complete Mediation: A system should validate access rights to all its resources to ensure that they’re allowed and should not rely on the cached permission matrix. If the access level to a given resource is being revoked, but that isn’t reflected in the permission matrix, it would violate the security.
  • Open Design: This principle highlights the importance of building a system in an open manner—with no secret, confidential algorithms.
  • Separation of Privilege: Granting permissions to an entity should not be purely based on a single condition, a combination of conditions based on the type of resource is a better idea.
  • Least Common Mechanism: It concerns the risk of sharing state among different components. If one can corrupt the shared state, it can then corrupt all the other components that depend on it.
  • Psychological Acceptability: It states that security mechanisms should not make the resource more difficult to access than if the security mechanisms were not present. In short, security should not make worse the user experience.

2. Best Practices to Secure REST APIs

Below given points may serve as a checklist for designing the security mechanism for REST APIs.

2.1. Keep it Simple

Secure an API/System – just how secure it needs to be. Every time you make the solution more complex “unnecessarily,” you are also likely to leave a hole.

2.2. Always Use HTTPS

By always using SSL, the authentication credentials can be simplified to a randomly generated access token. The token is delivered in the username field of HTTP Basic Auth. It’s relatively simple to use, and you get a lot of security features for free.

If you use HTTP 2, to improve performance – you can even send multiple requests over a single connection, that way you avoid the complete TCP and SSL handshake overhead on later requests.

2.3. Use Password Hash

Passwords must always be hashed to protect the system (or minimize the damage) even if it is compromised in some hacking attempts. There are many such hashing algorithms that can prove really effective for password security e.g. PBKDF2, bcrypt, and scrypt algorithms.

2.4. Never expose information on URLs

Usernames, passwords, session tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them easily exploitable.

https://api.domain.com/user-management/users/{id}/someAction?apiKey=abcd123456789  //Very BAD !!

The above URL exposes the API key. So, never use this form of security.

2.5. Consider OAuth

Though basic auth is good enough for most of the APIs and if implemented correctly, it’s secure as well – yet you may want to consider OAuth as well.

The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its behalf.

2.6. Consider Adding Timestamp in Request

Along with other request parameters, you may add a request timestamp as an HTTP custom header in API requests.

The server will compare the current timestamp to the request timestamp and only accepts the request if it is after a reasonable timeframe (30 seconds, perhaps).

This will prevent very basic replay attacks from people who are trying to brute force your system without changing this timestamp.

2.7. Input Parameter Validation

Validate request parameters on the very first step, before it reaches application logic. Put strong validation checks and reject the request immediately if validation fails.

In API response, send relevant error messages and examples of correct input format to improve user experience.

Comments

Subscribe
Notify of
guest
36 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
sycrido

“In API response, send relevant error messages and example of correct input format to improve user experience.”

Probably better to make this generic with an error code. Admin can look up the code and decipher what went wrong, and provide help to a legitimate user. I malicious user is unlikely to request help and be stuck with “it didn’t work”, rather than “this is why it didn’t work” and then the opportunity to work around the security implemented.

Captain Buzz

Team

Great post, makes me think about more and more secure options to use.

I always run 100% Rest API in a harden container “RO” state, with no where to go, docker is great with K8s

The Buzz never stops..

Miguel Alzate

Sensitive information can be exposed on URL if properly encrypted, cannot be?

Bharat Prajapat

Hello, I want to control access of my RestAPI , where i want to setup IP and Domain/Origin Based access where client can only access the API with that Origin/Domain if it is in white list, if he/she not using any Domain/Origin he/she can add IP to white list and access the API.
I need your suggestion, I am doing this right ?

Varun

If you are using JWT tokens for API security, it has pre-defined set of 8 claims. In them, you can use “aud”(audience) claim to set origins, so that if JWT token is received from untrusted source, it will be rejected.

ezzabuzais

Use cors to pre set a set of origins to deal with your server

Kaushal

It’s not safe as origin can be manually changed in the headers

Sejal

CORS with white list with same origin policy

Kaushal

Hi, can you please indicate what approaches you’d taken. I’m on the same path as of now.

Rameez

Adding a timestamp is really helpful …I was missing them in one of my APIs and some people did use replay attacks and we have no away to separate them from valid requests. Thank you so much

Dave Ibeh

Do you have a document on to implement this. Thanks

Christopher K

Great Documentation. We are implementing a sessionless solution where Basic Auth consists of the encoded ‘username:password’. We are limiting the operations to GETs only. We have noted, after working with the developer, that the session is not logged on the server. May I ask if this is common in similar REST features you have reviewed in the past?

Manoj

Hi,

https://api.domain.com/user-management/users/{id}/someAction?apiKey=abcd123456789 //Very BAD !!

I didn’t understand please can you explain this, why is very bad practice. What is correct way.

William Bowen

I know it’s been a few days, but just in case you are still looking for more information, a more correct way is to send the api key as a header. When paired with SSL, this helps ensure the api key is kept hidden from prying eyes.

Ra Ja

please elaborate on how is sending in header is safer. AFAIK all parts of a https layer is encrypted including the url.

Joe

You are right, all parts are encrypted, but the full URL may appear in web server log, which is usually not the case with the header or body.

Amar

HTTPS URL params and path should not be visible in web server access logs.

Eric

Best practice is to set a bearer token in your request header.
Also try not to include username & password in the session/api token, you rather want to generate an unique ID, something that can be easily reset

Ignacio

Great article! Thanks!

I want to do a comment if you allow me.

I think that adding a timestamp with a hash will not help at all if you are using SSL/TLS transmission because that session protocol will take care of reply attacks. Am I right?

Best regards,
Ignacio

Vikki

We can use JWT to securely transfer information

Showemimo Olarewaju

Yes, you can combine JWT token with OAuth 2 for enriched token validation

Narayana katooru

what are the alternatives to exposing key in URL?

Benjamin

Parsing it as a header value.

Chris

Pass it as a POST, data is stored in the request body

Kangkan

Anything that we do not wish to include in URL should be put either as a request body in case of POST/PUT requests or in HTTP Headers for GET or any other HTTP Verb.

Showemimo Olarewaju

in case of applications with UI I think you can use hidden fields, but in rest, better you make use of Headers and/or have it in your post body

Akhilesh Shukla

Good Checklist. Thanks!

Vladimir Lashchev

Adding timestamp to the request seems like a very small security improvement if at all. Unless that timestamp is signed by client and server can check that signature, it won’t help because MITM can inject updated timestamp in every replay.

Amri Shodiq

Add timestamp is actually really helps, if it is combined with a hash. Means, the timestamp parameter should be included into the object to be hashed. This way, a REST API request wouldn’t be fabricated. IMO.

Anonymous

“which can prove really effective for password security e.g. MD5, […]”

You should really omit MD5 and SHA. Not sure about the others.

Mustafa Çağatay Tulun

Well said! We are in 2019 and we should not use any MD (e.g. MD5) or SHA (e.g. SHA-1) algorithm to hash password. PBKDF2, bcrypt and scrypt are good choices.

If @Admin updates the article, it would be great!

Tim Maes

In best practices section, typo: ‘Never expose “informtion” on URLs’.

Great documentation. Thanks!