Identity and Access Management (IAM)

How enterprise identity actually works: the joiner-mover-leaver lifecycle, SAML and OIDC, token validation, RBAC versus ABAC, workload identity, privileged access, and the failure modes that leave standing admin behind.

Identity and Access Management (IAM) is the foundational system for establishing who users are, what they are allowed to do, and how they prove their identity across a distributed application ecosystem. It matters when users, services, and machines must securely access resources with consistent policies, especially in cloud-native, multi-tenant, or microservices environments.

User Identity Lifecycle

Creating and managing user identities begins with provisioning, which establishes a persistent identity record in the system. This typically involves creating a user in a directory service such as LDAP or a relational database.

INSERT INTO users (id, email, name, created_at, status)
VALUES ('u-12345', '[email protected]', 'Alice Johnson', '2024-01-15 10:30:00', 'active');

User attributes such as department, hire_date, and manager_id are stored in a schema that supports query and filtering. These attributes are used to drive role assignment, access policies, and conditional access rules.

User identity is established through a principal — an entity that can authenticate and be authenticated. A principal may be a human user, a service account, or a machine. The identity is validated via authentication, which typically involves presenting a credential (e.g., password, token, certificate) to a system.

After authentication, the system issues a token — a structured, signed payload — that contains identity claims. The most common format is JSON Web Token (JWT):

{
  "sub": "u-12345",
  "email": "[email protected]",
  "name": "Alice Johnson",
  "roles": ["admin", "finance"],
  "department": "engineering",
  "exp": 1705453200,
  "iss": "https://iam.company.com"
}

This token is used across services to establish identity without re-authentication.

Authentication Methods

Authentication is the process of verifying identity. It starts when a client sends credentials to an authentication endpoint.

Password-Based Authentication

A client sends a POST request to /auth/login with username and password:

POST /auth/login HTTP/1.1
Host: iam.company.com
Content-Type: application/json

{
  "username": "[email protected]",
  "password": "secret123"
}

The server responds with a JWT in the Authorization header:

HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: auth_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx; Path=/; HttpOnly; Secure

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx",
  "expires_in": 3600,
  "refresh_token": "rt-abc123"
}

The client stores the access_token and uses it in subsequent requests:

GET /api/users/123 HTTP/1.1
Host: api.company.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx

Multi-Factor Authentication (MFA)

MFA adds a second layer of verification. After a password, the user receives a one-time code via SMS, email, or an authenticator app.

The system supports a challenge-response flow:

  1. Client sends username and password to /auth/login.
  2. Server responds with challenge_id and method (e.g., sms, totp).
  3. Client presents the second factor (e.g., code: 784213).
  4. Server validates and returns a JWT.
POST /auth/login HTTP/1.1
Host: iam.company.com
Content-Type: application/json

{
  "username": "[email protected]",
  "password": "secret123"
}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "challenge_id": "ch-98765",
  "method": "totp",
  "message": "Enter code from your authenticator app"
}
POST /auth/challenge HTTP/1.1
Host: iam.company.com
Content-Type: application/json

{
  "challenge_id": "ch-98765",
  "code": "784213"
}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx",
  "refresh_token": "rt-abc123"
}

MFA is often enabled per user or per role. The failure mode: users forget their second factor, leading to auth drift — a user authenticates but the system does not recognize their MFA device, requiring re-enrollment.

Authorization and Access Control

Once a user is authenticated, the system determines what they can do: authorization. This is governed by policies that map identities to actions on resources.

Role-Based Access Control (RBAC)

RBAC assigns permissions to roles. A role is a named collection of permissions. Users are assigned to one or more roles.

A role definition is stored as a JSON object:

{
  "name": "admin",
  "description": "Full access to all systems",
  "permissions": [
    "users:read",
    "users:write",
    "users:delete",
    "reports:generate",
    "settings:edit"
  ]
}

A user is assigned a role via a user_roles table:

INSERT INTO user_roles (user_id, role_name, assigned_by, assigned_at)
VALUES ('u-12345', 'admin', 'system', '2024-01-16 09:00:00');

The system evaluates access using a permission matrix. For a request to GET /api/users, the system checks if the user’s roles include users:read.

Attribute-Based Access Control (ABAC)

ABAC extends RBAC by incorporating attributes of the user, resource, and environment.

A policy might look like:

{
  "name": "finance-team-access",
  "description": "Finance team can edit reports only during business hours",
  "conditions": [
    {
      "key": "user.department",
      "value": "finance",
      "operator": "eq"
    },
    {
      "key": "resource.type",
      "value": "report",
      "operator": "eq"
    },
    {
      "key": "time.hour",
      "value": [9, 10, 11, 12, 13, 14, 15, 16],
      "operator": "in"
    }
  ],
  "actions": ["read", "write"]
}

The system evaluates policies at runtime. A request is evaluated against all policies, and the result is a set of granted actions.

Policy Evaluation and Decision

The access decision is made by a policy decision point (PDP). The PDP receives a request and returns a decision:

{
  "allowed": true,
  "reason": "User is in finance department and request is during business hours",
  "granted_actions": ["read", "write"],
  "policy_id": "finance-team-access"
}

The system may cache decisions to avoid re-evaluation. A common failure: policy staleness — a user changes department, but the cached decision remains valid for an hour, during which they cannot access a resource.

Identity Federation and Single Sign-On (SSO)

IAM systems support identity federation, where one system (the identity provider, or IdP) authenticates users for multiple relying parties (service providers, or SPs).

A typical SSO flow uses SAML 2.0 or OpenID Connect (OIDC).

OpenID Connect SSO Flow

An application (SP) redirects a user to the IdP’s authorization endpoint:

GET /authorize?
  client_id=app-xyz
  &redirect_uri=https://app.company.com/callback
  &response_type=code
  &scope=openid profile email
  &state=abc123
HTTP/1.1
Host: iam.company.com

The IdP responds with a login form. After authentication, the IdP redirects back to the application:

HTTP/1.1 302 Found
Location: https://app.company.com/callback?code=auth-code-abc&state=abc123

The application exchanges the code for a JWT:

POST /token HTTP/1.1
Host: iam.company.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=auth-code-abc
&redirect_uri=https://app.company.com/callback
&client_id=app-xyz
&client_secret=client-secret-xyz
HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx",
  "expires_in": 3600,
  "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx",
  "refresh_token": "rt-xyz789"
}

The id_token contains user claims and is used to establish identity in the SP.

SSO Session Management

After login, the user is issued a session cookie. The IdP maintains session state, and the SP can check the session status via a session validation endpoint.

GET /session/check HTTP/1.1
Host: iam.company.com
Cookie: session_id=abc123
HTTP/1.1 200 OK
Content-Type: application/json

{
  "valid": true,
  "user_id": "u-12345",
  "expires_at": "2024-01-16T12:00:00Z"
}

The SP may use session binding, where it checks the session_id against the IdP’s session state. A failure: the user logs into the IdP from a different device, but the SP still uses the old session, leading to session drift.

Token Management and Lifecycle

Tokens are the core currency of IAM. The system must manage their lifecycle: issuance, validation, renewal, and revocation.

Token Validation

A service validates a JWT by verifying its signature, checking iss, aud, exp, and nbf claims.

Example validation logic:

func validateToken(token string, expectedAudience string) (Claims, error) {
    // Parse JWT
    claims, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method")
        }
        return []byte("shared-secret-key"), nil
    })

    if err != nil {
        return nil, err
    }

    // Check claims
    if claims.Get("aud") != expectedAudience {
        return nil, fmt.Errorf("invalid audience")
    }
    if claims.Get("exp").(float64) < time.Now().Unix() {
        return nil, fmt.Errorf("token expired")
    }

    return claims, nil
}

A common failure: clock skew — the service clock is off by 10 seconds, leading to false expiration errors.

Token Refresh and Reuse

A client uses an access_token until it expires. It can renew it using a refresh_token:

POST /auth/refresh HTTP/1.1
Host: iam.company.com
Content-Type: application/json

{
  "refresh_token": "rt-abc123"
}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx",
  "expires_in": 3600,
  "refresh_token": "rt-xyz789"
}

The system may allow token reuse: a token can be used multiple times. But if the system does not track token usage, a token may be used twice, leading to double-usage — a request is processed twice, causing inconsistent state.

Token Revocation

A client or system can revoke a token. The revocation is often done via a token revocation endpoint:

POST /auth/revoke HTTP/1.1
Host: iam.company.com
Content-Type: application/json

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx"
}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "success": true,
  "message": "Token revoked"
}

The system maintains a revocation list — a table of expired, revoked, or invalidated tokens. A service checks this list on each request, adding latency and complexity. A failure mode: revocation list not updated — a token is revoked, but the service continues to accept it for hours.

Service Identity and Machine-to-Machine (M2M) Access

IAM also manages identities for services and machines.

A service is provisioned with a service account — a user-like identity with its own credentials.

The service uses a client credentials flow to obtain a token:

POST /auth/token HTTP/1.1
Host: iam.company.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=svc-data-pipeline
&client_secret=secret-abc123
&scope=api:read api:write
HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx",
  "expires_in": 3600,
  "token_type": "Bearer"
}

The service uses this token to call other APIs. The token may be stored in a file, environment variable, or key vault.

A common failure: service account expiration — the client_secret is rotated, but the service is not updated, leading to token invalidation.

Identity Governance and Auditing

IAM systems maintain audit logs of identity changes and access events.

A typical log entry:

{
  "timestamp": "2024-01-16T10:30:00Z",
  "event": "user.created",
  "user_id": "u-12345",
  "actor": "system",
  "details": {
    "email": "[email protected]",
    "name": "Alice Johnson",
    "source": "onboarding-app"
  }
}

A user provisioning workflow might include:

  1. HR system sends user.created event.
  2. IAM system creates user in directory.
  3. IAM assigns default roles.
  4. IAM sends welcome email with login link.
  5. IAM logs the event.

The system can generate reports: “Users created in the last 30 days”, “Users with expired MFA”, “Top 10 accessed resources”.

An audit log is essential for compliance. A failure: log retention gap — logs are written every 10 minutes, but a system outage lasts 37 minutes, during which no logs are written. The audit trail has a gap, making it hard to trace events.

This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.