Deny by Default Authorization
Deny-by-default authorization rejects access unless an explicit rule grants the required permission. It reduces accidental exposure when a permission is missing, misconfigured, or not yet defined.
In an authorization system, the application first identifies the requested resource and action, such as `orders:read` or `admin:delete`. A deny-by-default policy treats the absence of a matching allow rule as a denial.
This is different from authentication. Authentication establishes who the caller is, while authorization determines what that caller may do. After authentication, the authorization layer evaluates the user's roles, permissions, attributes, or other policy inputs.
In Java backends, deny-by-default can be implemented through framework security rules, method-level annotations, or application-specific policy checks. The important property is that protected operations require an explicit authorization path rather than becoming accessible merely because no rule was written for them.
A useful implementation also distinguishes an authorization failure from an authentication failure. A caller who is not authenticated may receive `401 Unauthorized`, while an authenticated caller lacking the required permission commonly receives `403 Forbidden`, depending on the API's security design.
Key points
- No matching allow rule means access is denied.
- Authentication answers who the caller is; authorization answers what they can do.
- New or forgotten endpoints should remain protected until explicitly permitted.
- Use explicit permissions or roles for protected operations rather than relying on omission to grant access.
Interview questions
How would you implement deny by default in a Java backend?
I would establish protected security rules at the framework or application-policy layer and require explicit permissions for sensitive operations. For example, an operation such as deleting an order could require `orders:delete`. I would also test that callers without that permission receive a rejection, including users whose roles or permissions are missing or incomplete.
What does deny by default mean in authorization?
It means an operation is not permitted unless an authorization rule explicitly grants access. If the system cannot find a matching grant, it returns an authorization failure. This makes newly added or incorrectly configured functionality protected until someone deliberately permits it.
Why is deny by default safer than allow by default?
A missing rule under deny-by-default results in rejection rather than exposure. This is particularly useful when new endpoints or resources are introduced and their security configuration has not yet been added. The developer must explicitly decide who should receive access.
What is the difference between fail-closed authorization and simply returning false from a permission check?
Returning `false` from one check is only an implementation detail. Fail-closed authorization is the broader security property that uncertainty or the absence of an authorization decision does not result in access. The system should therefore make denied access the default outcome across the relevant authorization path, not just in one helper method.
How would you design tests for a deny-by-default authorization system?
I would test both positive and negative cases for every protected capability. Negative cases should include unauthenticated callers, authenticated users without the permission, incomplete role mappings, and unknown resources or actions. I would also add regression tests for newly introduced endpoints so that an absent policy cannot accidentally expose them.