OIDC Login Fails After Upgrade to 2.34.2+: email_verified Claim Now Fail-Closed (CVE Fix)

Last updated: June 25, 2026

Last updated: June 23, 2026

Status: Resolved in Coder 2.34.2+

Category: Security / Authentication

Issue

After upgrading to Coder 2.34.3 or later, OIDC login attempts fail with an authentication error page. Users cannot authenticate via your identity provider (IdP), even though their credentials are correct and login was working in previous versions.

The rejection occurs during OIDC claim validation, before the user is logged in.

Affected Versions

  • Vulnerable: Coder 2.34.2 (silently accepted invalid claims)
  • Breaking change introduced: Coder 2.34.2 (now rejects invalid claims)
  • Current behavior: Coder 2.34.3+ (strict validation enforced)

What Happened

The Coder OIDC integration validates the email_verified claim to ensure user emails have been verified at the identity provider level, rather than relying on Coder's own email verification. This is an important security control.

Prior to Coder 2.34.2, the email_verified OIDC claim was validated using a loose Go type assertion that silently failed under certain conditions. If your IdP:

  • Omitted the email_verified claim entirely, OR
  • Sent it as a string ("true" / "false") instead of a JSON boolean, OR
  • Sent it as a number (1 / 0) instead of a JSON boolean

The assertion would silently fail, and the email would be implicitly treated as verified. This was a security vulnerability.

After the patch in version 2.34.2, validation became fail-closed: anything that isn't a proper JSON boolean true (or a string/number that coerces to true) is rejected. This is correct behavior, but it breaks compatibility with IdPs sending the claim in non-standard formats.

Who is affected

This issue primarily affects users whose OIDC issuer URLs differ from the one currently active in the Coder deployment.

As part of the security fix, Coder restricted OIDC email fallback to first-time account linking only. Prior to this change, any account that was already linked could be bypassed by an email address lookup, even if the OIDC issuer URL was different. Now:

  • First-time account linking: Uses email verification from the OIDC claim (strict validation)
  • Existing accounts with mismatched issuer URLs: Receive the authentication error because the security restriction prevents fallback lookup by email

If your Coder deployment recently changed its OIDC issuer URL, or if users have accounts linked to a different issuer than the one currently configured, they will encounter this error.

Common Questions

Why did this work before if it was a security issue?

The loose type assertion in Coder 2.34.2 silently accepted invalid claim formats, implicitly treating missing or malformed claims as verified. This was a security gap. The patch closed that gap, but breaks compatibility with IdPs sending non-standard formats.

Why are only some of my users affected?

This issue primarily affects users whose OIDC issuer URL in their account record differs from the one currently configured in your Coder deployment. Prior to the security fix, these mismatched accounts could be accessed via email fallback. Now, the stricter validation prevents this fallback, causing the authentication error.

If your Coder deployment recently changed its OIDC issuer URL (e.g., switching IdP providers or changing the IdP configuration), existing user accounts linked to the old issuer URL will be affected.

Do all OIDC providers send email_verified as a boolean?

Most standards-compliant OIDC providers do. However, some IdP implementations may have bugs or legacy behavior that sends it as a string or number. Contact your IdP vendor if you're unsure of their implementation.

What if our IdP doesn't support sending email_verified at all?

If the claim is missing and cannot be sent, you have three options:

  1. Request the feature from your IdP vendor
  2. Implement email verification at the Coder application level via a different mechanism
  3. Use the temporary workaround below (only after consulting with your security team)

Next Steps

  1. Run the diagnostic queries in the Solution section to understand which users are affected
  2. Contact your IdP support team with the query results
  3. Request they send email_verified as a JSON boolean
  4. Once the IdP is fixed, affected users should be able to log in normally

Solution

Recommended Fix: Update Your IdP

Configure your identity provider to send email_verified as a proper JSON boolean (true or false), not as a string or number.

Step 1: Identify affected users

Run this query against your Coder database to see which users are affected and how:

SELECT
    u.username,
    u.email,
    jsonb_typeof(ul.claims->'merged_claims'->'email_verified') AS claim_type,
    ul.claims->'merged_claims'->'email_verified'                AS claim_value,
    ul.claims->'merged_claims'->>'iss'                          AS issuer
FROM user_links ul
JOIN users u ON u.id = ul.user_id
WHERE ul.login_type = 'oidc'
  AND u.deleted = FALSE
  AND (
        NOT (ul.claims->'merged_claims' ? 'email_verified')
     OR jsonb_typeof(ul.claims->'merged_claims'->'email_verified') NOT IN ('boolean','string','number')
     OR (jsonb_typeof(ul.claims->'merged_claims'->'email_verified') = 'boolean'
         AND (ul.claims->'merged_claims'->>'email_verified')::boolean = FALSE)
     OR (jsonb_typeof(ul.claims->'merged_claims'->'email_verified') = 'string'
         AND lower(ul.claims->'merged_claims'->>'email_verified') IN ('false','0','f','no',''))
     OR (jsonb_typeof(ul.claims->'merged_claims'->'email_verified') = 'number'
         AND (ul.claims->'merged_claims'->>'email_verified')::numeric = 0)
  )
ORDER BY u.email;

This query shows you:

  • Which users have invalid email_verified claims
  • What format they're in (missing, string, number, or boolean false)
  • Which IdP issued them

Step 2: Count total affected users

To understand the scope, run:

SELECT
    CASE
        WHEN claims->'merged_claims' ? 'email_verified' = FALSE
            THEN 'missing'
        WHEN jsonb_typeof(claims->'merged_claims'->'email_verified') = 'boolean'
            AND (claims->'merged_claims'->>'email_verified')::boolean = FALSE
            THEN 'bool_false'
        WHEN jsonb_typeof(claims->'merged_claims'->'email_verified') = 'string'
            AND lower(claims->'merged_claims'->>'email_verified') IN ('false','0','f','no')
            THEN 'string_false'
        WHEN jsonb_typeof(claims->'merged_claims'->'email_verified') = 'string'
            AND lower(claims->'merged_claims'->>'email_verified') IN ('true','1','t','yes')
            THEN 'string_true_OK'
        WHEN jsonb_typeof(claims->'merged_claims'->'email_verified') = 'number'
            AND (claims->'merged_claims'->>'email_verified')::numeric = 0
            THEN 'number_zero'
        WHEN jsonb_typeof(claims->'merged_claims'->'email_verified') NOT IN ('boolean','string','number')
            THEN 'unexpected_type'
        ELSE 'other_truthy'
    END AS email_verified_state,
    COUNT(*) AS user_count
FROM user_links
WHERE login_type = 'oidc'
GROUP BY 1
ORDER BY user_count DESC;

Step 3: Fix at the IdP

Work with your IdP administrator to ensure email_verified is sent as a JSON boolean for all users. Once corrected, affected users should be able to log in without any Coder configuration changes.

Workaround

⚠️ Security Notice: The following workaround disables an important security check. Do not implement this without first consulting with your company's security team. This should only be used as a temporary measure while you coordinate with your IdP to send email_verified as a JSON boolean.

If you need immediate access while fixing the IdP configuration, after obtaining security approval, you can temporarily bypass the email verification check:

CODER_OIDC_IGNORE_EMAIL_VERIFIED=true

Once you have implemented the fix at your IdP (sending email_verified as a JSON boolean), remove this flag immediately:

CODER_OIDC_IGNORE_EMAIL_VERIFIED=false

Or unset the environment variable entirely.