Skip to content

💡 Looking for a reliable Keycloak?

Cloud-IAM offers secure, scalable Keycloak hosting, deploy yours.

Explore Plans

SAML Clock Skew in Keycloak

Overview

In SAML 2.0 authentication, the Identity Provider (IdP) issues assertions that contain timestamps defining a strict validity window. The Service Provider (SP) validates these timestamps against its own system clock.

When the clocks of the IdP and SP are not perfectly synchronized — even by a few seconds — valid assertions can be rejected, causing authentication failures. This time difference is called clock skew.

Clock skew is one of the most common and frustrating issues encountered in SAML deployments. It can appear intermittently, making it difficult to diagnose, and often manifests as vague error messages like "assertion expired" or "assertion not yet valid".

How SAML timestamps work

Every SAML assertion contains a <Conditions> element with two critical attributes:

  • NotBefore — the assertion is not valid before this timestamp
  • NotOnOrAfter — the assertion expires at this timestamp
xml
<saml:Conditions
    NotBefore="2025-03-26T10:00:00Z"
    NotOnOrAfter="2025-03-26T10:05:00Z">
    ...
</saml:Conditions>

When the SP receives the assertion, it checks:

NotBefore ≤ current time < NotOnOrAfter

If the SP's clock is ahead or behind the IdP's clock, the SP's "current time" may fall outside this window, and the assertion is rejected.

What causes clock skew

Clock skew occurs when two servers have different system times. Common causes include:

  • NTP misconfiguration — one or both servers are not synchronizing time via NTP, or are using different NTP sources
  • Virtual machine clock drift — hypervisors can introduce clock drift, especially after VM suspend/resume cycles
  • Container environments — containers share the host clock, but if the host drifts, all containers drift with it
  • Geographic distribution — servers in different regions may sync to different NTP pools with slightly different offsets
  • Cloud provider clock variance — while generally minimal, clock differences between cloud providers or regions can occur

The impact of clock skew on SAML authentication

Consider a scenario where the IdP issues an assertion at 10:00:00 with a 5-minute validity window:

Assertion valid: 10:00:00 → 10:05:00

SP clock is 3 minutes ahead

The SP thinks it is 10:03:00 when the real time is 10:00:00. The assertion was just issued, but from the SP's perspective, 3 minutes have already passed. With a 5-minute window, this still works — but the margin is thin.

SP clock is 6 minutes ahead

The SP thinks it is 10:06:00. The assertion's NotOnOrAfter is 10:05:00, so the SP considers it expired and rejects it.

SP clock is 2 minutes behind

The SP thinks it is 09:58:00. The assertion's NotBefore is 10:00:00, so the SP considers it not yet valid and rejects it.

How allowedClockSkew fixes the problem

The allowedClockSkew setting (also called allowedClockDrift in some libraries) extends the assertion validity window on both sides:

Effective start  = NotBefore    − allowedClockSkew
Effective end    = NotOnOrAfter + allowedClockSkew

For example, with a 2-minute allowed skew and the original window of 10:00:00 → 10:05:00:

Extended window: 09:58:00 → 10:07:00

This gives the SP a tolerance buffer, so small clock differences do not cause failures.

Visual representation

Without allowedClockSkew:

    NotBefore                    NotOnOrAfter
        |                            |
  ──────┼────────────────────────────┼──────── time
        |      valid window          |


With allowedClockSkew = 2 minutes:

  NB − 2min                          NOA + 2min
     |                                    |
  ───┼────────────────────────────────────┼─── time
     |         extended valid window      |

Configuring allowed clock skew in Keycloak

As an Identity Provider

When Keycloak acts as the IdP, the assertion validity window is controlled by the SAML client settings. You can adjust:

  1. Open Keycloak Admin Console
  2. Navigate to Clients and select your SAML client
  3. Go to the Advanced tab
  4. Find Assertion Lifespan — this controls how long the assertion is valid (the window between NotBefore and NotOnOrAfter)

A longer assertion lifespan provides more tolerance for clock differences, but also increases the replay window.

TIP

A typical assertion lifespan of 5 minutes (300 seconds) is a good balance between security and usability. Very short lifespans (30-60 seconds) are more susceptible to clock skew issues.

As a Service Provider (IdP Broker)

When Keycloak acts as a Service Provider (brokering authentication from an external IdP), you can configure the allowed clock skew:

  1. Open Keycloak Admin Console
  2. Navigate to Identity Providers
  3. Select your SAML Identity Provider
  4. Scroll to Allowed clock skew
  5. Set the value in seconds (e.g., 30 for 30 seconds of tolerance)

WARNING

Avoid setting allowedClockSkew to very large values (e.g., more than 5 minutes). A large skew tolerance weakens replay attack protection, as expired assertions would still be accepted within the tolerance window.

Best practices

Fix the root cause first

allowedClockSkew is a safety net, not a solution. The root cause of clock skew is unsynchronized clocks. Always ensure:

  • NTP is enabled on all servers involved in the SAML flow (IdP, SP, and any intermediaries)
  • The same NTP source is used across all servers when possible
  • NTP status is monitored — clock drift can reoccur if NTP synchronization breaks

Use a reasonable tolerance

A good allowedClockSkew value is 30 to 120 seconds. This covers:

  • Minor NTP jitter (typically < 1 second)
  • Network propagation delays
  • Occasional NTP sync gaps

Monitor for clock skew issues

Watch for these error messages in your SP or Keycloak logs:

  • "Could not validate timestamp: expired" — SP clock is ahead of IdP
  • "Could not validate timestamp: not yet valid" — SP clock is behind IdP
  • "A valid SubjectConfirmation was not found" — can also indicate clock skew affecting the SubjectConfirmationData timestamps

If these errors appear intermittently, clock skew is the most likely cause.

Hands-on demo

We provide an interactive Docker-based demo that lets you experiment with clock skew in a real SAML flow. The demo includes a Keycloak IdP and a Flask-based SP where you can:

  • Simulate clock drift by adjusting the SP's clock offset
  • Configure the allowed clock skew tolerance
  • See a visual timeline of assertion validity
  • Observe exactly how and why authentication succeeds or fails

The demo is available at: github.com/cloud-iam/demo-saml-skew

Conclusion

Clock skew is a common but preventable cause of SAML authentication failures. By ensuring proper NTP synchronization and configuring a reasonable allowedClockSkew value, you can eliminate these issues while maintaining the security guarantees of SAML timestamp validation.

When troubleshooting SAML failures, always check the timestamps in the assertion against the SP's system clock — the answer is usually in the difference.