Definition
- Authentication – Proving who you are by verifying credentials such as a console password, an access key signature (SigV4), or an STS session token.
- Authorization – Deciding what a proven identity is allowed to do by evaluating all applicable IAM policies against the requested action and resource.
- Explicit Deny – A policy statement that says
"Effect": "Deny"for a matching action; it always wins over any Allow. - Explicit Allow – A policy statement that says
"Effect": "Allow"for a matching action; it grants access only if no explicit Deny exists. - Implicit Deny – The default outcome when no policy matches the request; everything is denied unless explicitly allowed.
At National Bank of India, authentication is the guard checking Rajesh's ID card at the entrance to confirm he really is Rajesh. Authorization is the rulebook that then decides which rooms his badge may open. Even if his ID is genuine, a note in the rulebook saying this person must never enter the vault overrides every permission – that is the explicit deny winning. If no rule mentions a room at all, the default is that the door stays locked – that is the implicit deny.
Understanding the Concepts
What is authentication in AWS?
Authentication in AWS happens before any policy is read. For a human it is a console password, optionally with multi-factor authentication. For a program it is a cryptographic signature (SigV4) on the request made with access keys, or a session token from STS. If the signature or token is invalid, the request is rejected immediately with an authentication error – authorization is never even consulted.
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.model.GetCallerIdentityRequest;
public class AuthenticationCheck {
public static void main(String[] args) {
// If credentials are invalid, this throws an authentication error
// Authorization is never reached
StsClient sts = StsClient.create();
var identity = sts.getCallerIdentity(
GetCallerIdentityRequest.builder().build());
System.out.println("Authenticated as: " + identity.arn());
}
}
What is authorization in AWS?
Once authenticated, AWS performs authorization. It gathers every policy that applies to the request: identity-based policies on the User, Group, and Role; resource-based policies on the target such as an S3 bucket policy; permission boundaries; service control policies at the organization level; and session policies. It then evaluates them with a strict order of precedence.
Policies gathered for evaluation:
1. Identity-based policies (on the User, Group, Role)
2. Resource-based policies (S3 bucket policy, SQS queue policy)
3. Permission boundaries (ceiling on a Role or User)
4. Service control policies (organization-wide ceiling)
5. Session policies (passed during assumeRole)
How does policy evaluation work?
The order is the part interviewers test. First, if any policy contains an explicit deny that matches the action and resource, the request is denied, full stop – nothing can override an explicit deny. Second, if there is no explicit deny but at least one policy contains a matching allow, the request is permitted. Third, if nothing matches at all, the default is an implicit deny, so the request is refused. In short, everything is denied by default, an allow opens it, and an explicit deny slams it shut again.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAllS3OnStatements",
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::nbi-statements/*"
},
{
"Sid": "NeverAllowDelete",
"Effect": "Deny",
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::nbi-statements/*"
}
]
}
In this policy the holder can do everything on the statements bucket except delete objects, because the explicit deny on s3:DeleteObject overrides the broad allow.
How is authentication different from authorization?
| Aspect | Authentication | Authorization |
|---|---|---|
| Question answered | Who are you? | What may you do? |
| When it happens | First, before any policy check | Second, after identity is confirmed |
| Mechanism | Password, SigV4 signature, STS token, MFA | IAM policy evaluation |
| Failure result | 403 AuthenticationFailed | 403 AccessDenied |
| Can you be authenticated but unauthorized? | Yes, your identity is valid but the action is denied | N/A |
public class AuthVsAuthz {
// Authentication: proving Rajesh is Rajesh
// Valid password + MFA = authenticated
// Invalid password = rejected before policies are even checked
// Authorization: can authenticated Rajesh delete statements?
// Policy says Deny s3:DeleteObject = request denied
// Rajesh is real, but the rulebook says no
}
What are the rules of policy evaluation?
The rules follow a strict precedence that never changes:
- If any applicable policy has an explicit Deny matching the action and resource, the request is denied. Nothing overrides this.
- If there is no explicit Deny but at least one applicable policy has an explicit Allow, the request is permitted.
- If nothing matches at all, the result is an implicit Deny.
Additionally, for cross-account access, both the identity-based policy in the source account and the resource-based policy in the target account must allow the action. For same-account access, either an identity-based or a resource-based Allow is sufficient.
public class PolicyEvaluationOrder {
enum Decision { EXPLICIT_DENY, EXPLICIT_ALLOW, IMPLICIT_DENY }
public static Decision evaluate(boolean hasExplicitDeny, boolean hasExplicitAllow) {
if (hasExplicitDeny) return Decision.EXPLICIT_DENY; // always wins
if (hasExplicitAllow) return Decision.EXPLICIT_ALLOW; // access granted
return Decision.IMPLICIT_DENY; // default: denied
}
}
What is a service control policy and how does it fit?
In AWS Organizations a service control policy (SCP) acts as a ceiling – it filters the maximum permissions that any identity in an account can have. Even if an account's own policy allows an action, the request fails if the SCP does not permit it. SCPs do not grant anything by themselves; they only restrict.
This is how the bank's cloud team ensures that no account can, for example, create resources outside the Mumbai Region, regardless of what individual developers allow in their own policies.
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyNonMumbaiRegions",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": ["ap-south-1", "us-east-1"]
}
}
}]
}
What are common mistakes?
The first mistake is assuming an Allow overrides a Deny. It never does. If you have a broad Allow and a targeted Deny, the Deny wins. Many teams are surprised when they add an Allow but the request is still denied because a boundary or SCP has a Deny.
The second mistake is forgetting the NACL-like evaluation for cross-account access, where both sides must allow. An identity policy in account A that allows s3:GetObject and a bucket policy in account B that does not mention account A means the request is denied.
The third mistake is using inline policies everywhere instead of managed policies. Inline policies are harder to audit, version, and reuse.
public class PolicyMistakes {
// WRONG: expecting Allow to override Deny
// Policy 1: Allow s3:*
// Policy 2: Deny s3:DeleteObject
// Result: DeleteObject is DENIED (Deny always wins)
// WRONG: cross-account missing bucket policy
// Account A identity policy: Allow s3:GetObject
// Account B bucket policy: (no mention of Account A)
// Result: DENIED (both sides must allow for cross-account)
}
What about permission boundaries?
A permission boundary is a managed policy attached to a User or Role that sets the maximum permissions it can have. The effective permissions are the intersection of the identity policy and the boundary. If the identity policy allows s3:* but the boundary only allows s3:GetObject, the effective permission is only s3:GetObject.
Banks use permission boundaries to let development teams create their own Roles without being able to escalate privileges beyond the boundary.
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "BoundaryForDevTeam",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"dynamodb:GetItem",
"dynamodb:PutItem"
],
"Resource": "arn:aws:*:ap-south-1:123456789012:*"
}]
}
What should a senior engineer know?
A senior engineer understands that identity policies, resource policies, permission boundaries, SCPs, and session policies all feed into the same deny-beats-allow-beats-implicit-deny evaluation. They know that SCPs apply to every principal in the account except the root user of the management account, that permission boundaries are the intersection with the identity policy, and that session policies further narrow permissions during an assumeRole call.
They also know how to use IAM Policy Simulator to test policies before deploying, and how to read CloudTrail logs to diagnose AccessDenied errors by matching the event's error code to the specific policy that caused the denial.
# Test a policy without deploying it
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:role/SettlementRole \
--action-names s3:GetObject s3:DeleteObject \
--resource-arns arn:aws:s3:::nbi-statements/*
# Output shows which actions are allowed and which are denied
Visual Overview
┌──────────── IAM Policy Evaluation Flow ────────────┐ │ │ │ API Request arrives │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ Authentication │ Password / SigV4 / STS token │ │ │ (Who are you?) │ │ │ └────────┬────────┘ │ │ │ valid? │ │ YES │ NO → 403 AuthenticationFailed │ │ ▼ │ │ ┌─────────────────┐ │ │ │ Gather Policies │ │ │ │ Identity-based │ │ │ │ Resource-based │ │ │ │ Boundaries │ │ │ │ SCPs │ │ │ │ Session policies │ │ │ └────────┬────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ Explicit Deny? │───YES──→ REQUEST DENIED │ │ └────────┬────────┘ │ │ NO │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ Explicit Allow? │───YES──→ REQUEST ALLOWED │ │ └────────┬────────┘ │ │ NO │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ Implicit Deny │───────→ REQUEST DENIED │ │ │ (default) │ (nothing matched) │ │ └─────────────────┘ │ └─────────────────────────────────────────────────────┘
Key Takeaway
Authentication and authorization are two separate steps that people often blur together. Authentication is proving who you are – for a human it is a password with multi-factor, and for a program it is a cryptographic signature on the request or a session token from STS. If that fails, AWS rejects the request immediately and never even looks at permissions. Authorization is the second step: now that AWS knows who you are, it decides what you are allowed to do by evaluating the IAM policies that apply.
The evaluation follows a strict and memorable order of precedence. AWS gathers every applicable policy – the identity policies on the User, Group, and Role, any resource policy like an S3 bucket policy, permission boundaries, and organization service control policies – and then it applies three rules. First, if any policy has an explicit deny that matches, the request is denied and nothing can override it. Second, if there is no explicit deny but at least one allow matches, the request is permitted. Third, if nothing matches at all, the default is an implicit deny. So everything is denied by default, an allow opens the door, and an explicit deny slams it shut no matter what.
In banking this precedence is extremely useful. At National Bank of India our back-office service needs broad read and write access to the statements bucket so it can generate and update PDFs, but it must be impossible for it to delete a statement, because a deleted statement is an audit and compliance disaster. So we write one policy that allows all S3 actions on the bucket and a second statement that explicitly denies the delete action. The explicit deny overrides the broad allow, giving us wide access with a surgical exception.
One senior point is about AWS Organizations. A service control policy acts as a ceiling, not a grant – if the SCP does not permit an action, it fails even when the account's own policy allows it, but the SCP never grants anything by itself. Understanding that identity policies, resource policies, and SCPs all feed into the same deny-beats-allow-beats-implicit-deny evaluation is what shows an interviewer you understand how real access decisions are made across a whole banking organization.
Remember one sentence: Explicit Deny always wins over Allow, Allow wins over silence, and silence means Denied.
---