Secure Error/Exception Handling

Janani Subbiah
codeburst
Published in
5 min readMar 4, 2021

--

Photo by Pablo Merchán Montes on Unsplash

Error and exception handling are integral to every software application, no matter the functionality. Errors need to be meaningful, helpful, simple and help users understand what to do next (if there is something for them to do). But what if I told you that sometimes your error messages need to be presented at a high level without the intricacies of exactly what error occurred?

Securing applications is a Herculean task in and of itself. There really isn’t a one-size-fits-all solution across applications and within the different layers of a single application. When we talk about security, securing applications for happy path scenarios comes to mind first: User makes a request with incorrect credential(s) and application denies the request, if the credentials are correct then the application processes that request. This is important and kind of obvious. But what is less obvious is how we handle errors and exceptions in secure applications. How we handle exceptions also depends on which layer of security the user is at: Have they authenticated yet? Do they have the right permissions? etc.

Ideally, I would have liked to list out generic scenarios with recommendations on how to handle errors and exceptions but I feel like it might be more useful to talk about specific error handling scenarios in secure applications. But before we do that I want to oversimplify and talk about the two layers of security: authentication and authorization.

Layers of Security

Flowchart depicting request processing in a secure application
Request Processing in a Secure Application

Though you may have seen this over a million times, I don’t think I will be doing justice to this post if I do not specify authentication vs authorization. Authentication is verifying if you are who you say who you are and authorization is verifying if you are allowed to make the request you are trying to make (or access the resource you are trying to access).

With any secure software application, authentication is your first defense. If a user makes a request to access a protected resource (meaning valid auth credentials need to be provided for access), valid authentication credentials have to be provided, failing which the user should be denied the request. In the context of a ReST API service, such a request would result in a 401 error status code.

The next layer of defense is your authorization layer: The one where the application validates and verifies that the user (identified by their authentication credentials) can access the resource they are trying to access. This may not apply to all applications and if it did then it could be roles or permissions-based (OWASP’s cheat sheet on access control may come in handy here). In the context of a ReST API service, such a request would result in a 403 error response. It is important to note that authentication failure results in a 401 while an authorization failure results in a 403 and this distinction is extremely important in conveying what needs to be fixed before the request can succeed!

Once a user successfully passes those two layers of defense, then comes all other validations on the incoming request. It is important to note that, in most scenarios, processing the request should be delayed until the user gets through the authentication and authorization layers successfully.

Error/Exception Handling considerations

So with the definition out of the way, let us talk about some important considerations for error/exception handling in secure application:

Generic error message

Error messages in the context of auth errors, in most scenarios, should be generic. Let’s consider login: If a user is trying to login using a username and password, and say they present a username that is valid but the password does not match what is currently stored in the backend, the error message for such a scenario should be generic. So something along the lines of “Login credentials incorrect” or “Username or password incorrect” should be preferred over “Password incorrect”. The latter exposes vital information: whether or not a username exists in the system. This allows a malicious user to use the login page to figure out if a user exists in the system. As an additional defense mechanism, one should consider implementing things like max login attempts, email verification, two-factor auth, etc.

APIs that don’t require any security

Depending on the type of application being built it is possible not all APIs require auth. There could be APIs that don’t require any security, meaning anyone can access these. Such APIs should take extra care to ensure error scenarios don’t result in exposure of secure information.

We can use our login example again here. Most applications do not require any auth to access the login functionality (think about the login page that displays text fields for users to enter a username and password). Users need valid auth to get past the login page but the actual login page itself is accessible to anyone on the internet. Security errors in such scenarios should not only be generic but also should make sure secure information is never exposed.

Logging

Logging is great. Logging is a requirement that allows developers to trace back what happened and figure out why. But, logs should not under any circumstance expose sensitive information in any form. All such information should be masked appropriately or not logged at all!

Permissions should not be exposed

As far as role/permission-based access control goes, it is good practice to let the user know what permissions they have vs what they need to access a resource. Let us consider an example:

  • Say we have four permissions in our system: CAN_READ, CAN_UPDATE, CAN_DELETE and CAN_CREATE.
  • User A has the CAN_READ permission but any of the others.
  • User A tries to create a new resource (for which they would need the CAN_CREATE permission).
  • The error message in this scenario should say something along the lines of “Does not have permissions to perform this operation” and not get into the specifics of why maybe required to perform that task. This is just something to keep in mind and be aware of. There might be scenarios where this does not apply but understanding the risk of exposing permissions helps makes informed decisions. This is also a matter of personal preference: When it comes to security being minimalistic in what is exposed is safer.

Conclusion

These scenarios are NOT an exhaustive list. There are several other security-related error scenarios where extra care is required for error handling. I highly recommend reading OWASP guidelines while building any software application. It is one of the best aggregations of security-related information in a single location. I hope this post can get us all to start thinking about the error and exception handling with regards to security in a new light where sometimes the lesser the information exposed, the more secure (and better) it is for the application!

--

--