mirror of
https://github.com/coder/coder.git
synced 2026-06-06 06:28:20 +00:00
d5b0e93c6c
## Problem The OIDC callback checks `email_verified` via a Go type assertion (`verifiedRaw.(bool)`). When an IdP returns the claim as a string (`"false"`), a number, or omits it entirely, the assertion fails silently and the email is implicitly treated as verified. Several real IdPs (SAML-to-OIDC bridges, certain Azure AD B2C configurations) emit string-typed booleans, making this reachable in practice. ## Fix Add `coerceEmailVerified()` to handle `bool`, `string` (`"true"`/`"false"`/`"1"`/`"0"` via `strconv.ParseBool`), `float64`, `json.Number`, and `int`/`int64` variants. Rewrite the check to be fail-closed: an absent claim, an unrecognized type, or any non-truthy value is treated as unverified and rejected. The existing `IgnoreEmailVerified` config option remains as an escape hatch. Fixes https://linear.app/codercom/issue/PLAT-228 > Generated with [Coder Agents](https://coder.com) by @f0ssel <details><summary>Implementation plan</summary> ### Production code (`coderd/userauth.go`) - Added `encoding/json` import - Added `coerceEmailVerified(v interface{}) (verified bool, ok bool)` helper near EOF - Replaced the type-assertion block (lines ~1342-1363) with fail-closed logic that uses `coerceEmailVerified` ### Unit tests (`coderd/userauth_internal_test.go`, new file) - Table-driven test covering: `bool`, `string` (`"true"`, `"false"`, `"1"`, `"0"`, `"TRUE"`, `"t"`, `"f"`, `"invalid"`, `""`), `json.Number`, `float64`, `int`, `int64`, `nil`, `[]string{}`, `map[string]string{}` ### Integration tests (`coderd/userauth_test.go`, `coderd/users_test.go`) - Added 3 new test cases: `EmailVerifiedMissingIgnored` (200), `EmailVerifiedAsStringTrue` (200), `EmailVerifiedAsStringFalse` (403) - Updated existing test cases that omitted `email_verified` and expected success to include `"email_verified": true` ### FakeIDP (`coderd/coderdtest/oidctest/idp.go`) - `encodeClaims` now defaults `email_verified` to `true` (like `exp`, `aud`, `iss`) so tests that don't care about the verification flow are unaffected </details>