Recently I've got into an argument with a colleague in regards to what HTTP status to return.
The way our API works right now: you need to be auth...
For further actions, you may consider blocking this person and/or reporting abuse
Let's imagine you try to implement a connection with a new API. You get your token. You read the docs, written with many sections and subresources for each large aspect of the new platform. You combine the request. You add the API version to path, headers, userID, whatnot else and finally send out the request and get back 404.
You remove the API version. You change the base to api.domain.co and again 404. Repeat and the same. You check the HTTP library docs of language/package/framework used and still no luck. You try adding and removing
Content-Type: application/json
,Accept
etc. and still no luck.In the end it turns out it was copy-pasta mistake since the JWT token is so long, the last part didn't copy fully and it was just auth mistake.
I would look from the point what is more valuable to the user - hey you made a mistake or GTFO.
I think you misunderstood what I was trying to ask. We are not debating whether we should replace 401 with 404 for authentication errors. The question is which goes first - evaluating that the requested route exists or validating the token.
Approach 1:
If we validate the token first then any calls without a valid token will return 401, because that's the exact error - the call is unauthenticated and it doesn't matter if the route exists.
Calls with valid token:
GET /exists - 200
GET /not-exists 404
Calls without a valid token:
GET /exists - 401
GET /not-exists - 401
Approach 2:
We evaluate if route exists first and only then check for a valid token. Then API would return like this:
Calls with valid token:
GET /exists - 200
GET /not-exists - 404
Calls without a valid token:
GET /exists - 401
GET /not-exists - 404
Ok, I see.
If we talk about API with auth, then there are a high chance of dynamic routing, user-specific and global resources. Maybe at some scale, there will be an API gateway first, then it forwards requests to one of the services at the backend even not knowing detailed list what backend can have.
Even more so on API with authentication then let's not forget also about authorization.
If user X can have file Y, then user Z cannot have file Y. So, the response depends on finished authentication and authorization steps.
It's like someone knocking on your door, first you want to know who he is before you let him in and let watch your TV. Not the other way around - let in, he takes the TV and on the way out you try to explain that he cannot have it.
If you don't even let him in, you get very suspicious when he asks if you have an HD TV with HDR and Dolby sound...
I believe that auth makes sense to do early as possible so it is never forgotten as middle or last step or accidentally bypassed by a cache... not that anyone could imagine possible bug scenario here...
I would go with approach 1). You shouldn't tell your enemies your endpoints.
If someone wants to e.g. Check an endpoint for security breaches, so they can hack you, they wouldn't know where to start with approach 1).
Consider this: An attacker finds a way (and eventually he or she would) to walk through the entire API and find all the endpoints. Then move to craft a token and try to bypass authentication.
Or, would it be harder to first craft the authentication and then find the endpoints.
Which would, if successful, damage your product the most? Which would, if successful, be detected first?
I don't know anything about your product but those are, I believe, interesting questions to go through.
I don't think API endpoints themselves are a huge secret. But if we require a valid token first, then it will be easy to see which user is trying to scan the API. Due to the nature of our business, the users are linked to real identities, so it would be easy to track which real person is doing the scanning (or who's account was compromised).
I think I kinda answered my own question here. Thank you for formulating the right questions for me to ask.
My pleasure! Keep it up!
I think your colleague is right, but I think it is a small security issue because you may can evaluate which routes exist but not seem like a big issue to me. At the end both works if you design your Frontend in a way that fits.
My thoughts exactly on the security. Even though security through obscurity is not a good practice, if we return 401 for all unauthenticated requests, then we're hiding which routes exist if the user is not authenticated.
Yeah on a security aspect it makes totally sense.
Authentication before routing.
It makes little sense otherwise. The outcome of routing isn't to tell whether a route exists but to delegate to route handler. If you have a an authentication Middleware, it stands to reason to trigger it early (with the added benefit of not giving away route existence - mostly because there's really no upside to this, there is nothing to gain by triggering authentication late).
So unless you have a strong need to delegate authentication to specific handlers, it should go first.