Skip to content

IAM Fundamentals

Identity and Access Management (IAM) is a fundamental security framework that controls who can access what resources in your application and what actions they can perform. Understanding IAM concepts is crucial for implementing secure, scalable access control systems.

IAM encompasses two core security functions:

“Who are you?” - Verifying the identity of users, services, or systems

  • Login credentials (username/password)
  • Multi-factor authentication (MFA)
  • OAuth providers (Google, GitHub, etc.)
  • API keys and tokens
  • Biometric verification

“What can you do?” - Determining what authenticated entities are allowed to access

  • Permission checking
  • Access control policies
  • Resource-level restrictions
  • Role-based access control (RBAC)

An identity (also called a principal) represents an entity that can be authenticated and granted permissions. Identities include:

Real people with accounts in your system:

{
"id": "user_12345",
"email": "alice@company.com",
"name": "Alice Johnson",
"type": "user"
}

Applications or automated systems:

{
"id": "service_backup_system",
"name": "Backup Service",
"type": "service_account"
}

Programmatic access tokens:

{
"id": "api_key_67890",
"name": "Mobile App API Key",
"type": "api_key"
}

Collections of users:

{
"id": "group_engineering",
"name": "Engineering Team",
"members": ["user_12345", "user_67890"],
"type": "group"
}

Resources are the objects, data, or services you want to protect. Everything that requires access control is a resource.

  • Servers and infrastructure
  • Database instances
  • Storage systems
  • Network devices
  • Files and documents
  • Database records
  • API endpoints
  • Applications and services
  • Projects and workspaces
  • Organizations and teams
  • Workflows and processes
  • Configurations and settings

Resources are identified using Resource URIs - hierarchical identifiers that uniquely specify each resource:

/organization/acme
├── /organization/acme/project/web-app
│ ├── /organization/acme/project/web-app/environment/production
│ ├── /organization/acme/project/web-app/environment/staging
│ └── /organization/acme/project/web-app/database/users
├── /organization/acme/project/mobile-app
│ ├── /organization/acme/project/mobile-app/api/v1
│ └── /organization/acme/project/mobile-app/api/v2
└── /organization/acme/billing
├── /organization/acme/billing/invoices
└── /organization/acme/billing/payments

Permissions define specific actions that can be performed on resources. They represent the most granular level of access control.

document.read - View document content
document.write - Create or modify documents
document.delete - Remove documents
document.share - Share documents with others
create - Add new resources
read - View existing resources
update - Modify existing resources
delete - Remove resources
admin.users.create - Create new user accounts
admin.users.suspend - Suspend user accounts
admin.billing.view - View billing information
admin.logs.access - Access system logs
deploy.staging - Deploy to staging environment
deploy.production - Deploy to production environment
database.backup - Create database backups
support.tickets - Access support tickets

Roles are collections of permissions that can be assigned as a group. They simplify access management by grouping related permissions together.

Viewer Role

{
"name": "viewer",
"description": "Read-only access to resources",
"permissions": [
"read",
"list",
"view"
]
}

Editor Role

{
"name": "editor",
"description": "Can view and modify resources",
"permissions": [
"read",
"write",
"update",
"create"
]
}

Admin Role

{
"name": "admin",
"description": "Full control over resources",
"permissions": [
"read",
"write",
"update",
"create",
"delete",
"manage",
"configure"
]
}

Create roles specific to your application’s needs:

Content Manager

{
"name": "content_manager",
"description": "Manages content creation and publication",
"permissions": [
"content.create",
"content.edit",
"content.publish",
"content.review",
"media.upload"
]
}

DevOps Engineer

{
"name": "devops_engineer",
"description": "Manages infrastructure and deployments",
"permissions": [
"deploy.staging",
"deploy.production",
"infrastructure.configure",
"monitoring.access",
"logs.view"
]
}

Policies define the rules that govern access control. They specify which principals can perform which actions on which resources under what conditions.

{
"principal": "user_alice",
"resource": "/project/web-app/database/users",
"permissions": ["read", "write"],
"effect": "allow"
}
{
"principal": "group_developers",
"resource": "/project/*/environment/staging",
"permissions": ["deploy"],
"effect": "allow",
"conditions": {
"time_of_day": "09:00-17:00",
"source_ip": "10.0.0.0/8"
}
}

Resource owners control access to their resources:

  • User-controlled: Individual users set permissions
  • Flexible: Easy to share and delegate access
  • Scalability issues: Difficult to manage at scale
  • Security risks: Users may grant excessive permissions

Example: File system permissions where file owners can set read/write permissions for other users.

System-wide policies control access:

  • Centrally controlled: Administrators set all permissions
  • Security focused: Strong security guarantees
  • Inflexible: Difficult to adapt to changing needs
  • Complex: Requires detailed security classifications

Example: Military security systems with Top Secret, Secret, and Confidential classifications.

Access based on user roles within the organization:

  • Role-centric: Permissions assigned to roles, not individuals
  • Scalable: Easy to manage large numbers of users
  • Organizational alignment: Reflects real-world job functions
  • Standard approach: Widely adopted in business applications
Users ──→ Roles ──→ Permissions ──→ Objects/Resources
│
└─────→ Sessions ──→ Roles

Users → assigned to → Roles → granted → Permissions → on → Resources

Alice (User) → Editor Role → [read, write, publish] → /blog/posts/*
Bob (User) → Viewer Role → [read] → /blog/posts/*
Carol (User) → Admin Role → [read, write, delete, manage] → /blog/*

Dynamic access based on attributes:

  • Context-aware: Considers user, resource, and environmental attributes
  • Fine-grained: Very precise access control
  • Complex: Requires sophisticated policy engines
  • Flexible: Adapts to complex business rules
{
"policy": "Allow access if user is manager AND resource is in their department AND current time is business hours",
"user_attributes": {
"role": "manager",
"department": "engineering",
"clearance_level": "3"
},
"resource_attributes": {
"department": "engineering",
"classification": "internal",
"data_type": "source_code"
},
"environment_attributes": {
"time": "14:30",
"day_of_week": "Tuesday",
"location": "office_network"
}
}

Resources often exist in hierarchical relationships where permissions granted at higher levels automatically apply to lower levels:

/organization/acme ← Admin permissions here
├── /organization/acme/project/web ← apply to all projects
│ ├── /environment/staging ← and all environments
│ └── /environment/production ← within those projects
└── /organization/acme/project/api
├── /environment/staging
└── /environment/production

Systems differ in how they combine inherited and explicit grants. Some support explicit denies or “closest parent wins” rules.

Given these permission assignments:

[
{
"principal": "alice",
"resource": "/organization/acme",
"permissions": ["read"]
},
{
"principal": "alice",
"resource": "/organization/acme/project/web",
"permissions": ["write"]
},
]

Alice’s effective permissions:

  • /organization/acme and everything beneath it: read
  • /organization/acme/project/web and everything beneath it: read + write (inherited + explicit)

Grant the minimum permissions necessary for users to perform their job functions:

// Good: Specific permissions
{
"role": "content_editor",
"permissions": [
"articles.create",
"articles.edit",
"articles.publish",
"media.upload"
]
}
// Avoid: Overly broad permissions
{
"role": "content_editor",
"permissions": [
"admin.*",
"system.*"
]
}

Design roles that mirror your organization structure:

{
"engineering_roles": [
"software_engineer",
"senior_engineer",
"engineering_manager",
"principal_engineer"
],
"product_roles": [
"product_manager",
"product_owner",
"product_analyst"
],
"operations_roles": [
"devops_engineer",
"site_reliability_engineer",
"system_administrator"
]
}

Create logical resource hierarchies that support inheritance:

Terminal window
# Good: Logical hierarchy
/company/departments/engineering/teams/platform/projects/auth-service
# Avoid: Flat structure
/auth-service-engineering-platform-team

Implement periodic reviews of permissions:

  • Quarterly access reviews: Review all role assignments
  • Project completion: Remove project-specific access
  • Role changes: Update permissions when people change roles
  • Offboarding: Immediately revoke all access when people leave

Track all access control decisions:

{
"timestamp": "2024-01-15T10:30:00Z",
"principal": "alice@company.com",
"resource": "/project/web-app/database/users",
"action": "read",
"result": "allowed",
"reason": "role:database_reader"
}

Prevent conflicts of interest by separating incompatible functions:

// Finance roles - separate creation from approval
{
"expense_creator": ["expense.create", "expense.submit"],
"expense_approver": ["expense.approve", "expense.reject"],
"expense_payer": ["payment.create", "payment.execute"]
}
// Development roles - separate development from production
{
"developer": ["code.write", "deploy.staging"],
"release_manager": ["deploy.production", "rollback.production"]
}

Effective IAM is critical for application security and requires careful planning and implementation. Key takeaways:

  • Start simple: Begin with basic RBAC and expand as needed
  • Think hierarchically: Design resource structures that support inheritance
  • Follow best practices: Implement least privilege, separation of duties, and regular reviews
  • Monitor continuously: Track access patterns and audit permissions regularly
  • Choose the right tools: Select IAM solutions that fit your architecture and scale

Ready to try it? The Quickstart takes you from sign-up to a working permission check.