When aclErrorStatus is set to 403, it fails one use case, when the accessToken is supplied but invalid.
Consider the following use cases:
- attempt to access a protected resource without creds (missing token): 401(a auth/login failure)
- attempt to access a protected resource with invalid creds (fake token): 401 (a auth/login failure)
- attempt to access a protected resource with expired creds (old token): 401 (a auth/login failure)
- attempt to access a protected resource with valid creds (valid token) that requires an elevated permission (higher role) : 403 (access denied)
Out of these 4 use cases, # 2 and # 3 fail to return 401 and instead return 403. This is because in application.js, the logic that returns 401 does not check for a valid token (i.e. if the token has a valid userId), leaving further ACL failures to default to aclErrorStatus, which is set to 403. See annotated code below:
application.js (line 343)
var errStatusCode = modelSettings.aclErrorStatus || app.get('aclErrorStatus') || 401;
/////// HANDLE 401 USE CASES
if (!req.accessToken) { // <- this lets a fake or expired token get away from a 401
errStatusCode = 401;
}
////// LAST CHANCE FOR 401 USE CASES ENDS HERE
////// EVERYTHING BELOW USES errStatusCode
if (Model.checkAccess) {
...
}
Suggested fix:
var errStatusCode = modelSettings.aclErrorStatus || app.get('aclErrorStatus') || 401;
if (!req.accessToken || !req.accessToken.userId) { // Checks both the presence and validity of a token
errStatusCode = 401;
}
if (Model.checkAccess) {
...
}
When aclErrorStatus is set to 403, it fails one use case, when the accessToken is supplied but invalid.
Consider the following use cases:
Out of these 4 use cases, # 2 and # 3 fail to return 401 and instead return 403. This is because in application.js, the logic that returns 401 does not check for a valid token (i.e. if the token has a valid userId), leaving further ACL failures to default to aclErrorStatus, which is set to 403. See annotated code below:
application.js (line 343)
Suggested fix: