{"record":{"id":"07f26f749d0a5d4b","repo":"xai-org/grok-build","slug":"oidcerror-pinnedprincipalmismatch","errorCode":null,"errorMessage":"OidcError::PinnedPrincipalMismatch","messagePattern":"OidcError::PinnedPrincipalMismatch","errorType":"exception","errorClass":"OidcError","httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-shell/src/auth/oidc/protocol.rs","lineNumber":201,"sourceCode":"        }\n        Some(ForceLoginTeam::AnyOf(ids)) => ids,\n    };\n    if let Some(actual) = actual\n        && allowed.iter().any(|a| a == actual)\n    {\n        return Ok(());\n    }\n    let expected = if allowed.len() == 1 {\n        format!(\"team {}\", allowed[0])\n    } else {\n        format!(\"one of teams: {}\", allowed.join(\", \"))\n    };\n    tracing::warn!(\n        expected = %expected,\n        actual = ?actual,\n        \"OIDC: login principal does not satisfy required policy; rejecting\"\n    );\n    Err(anyhow::Error::new(OidcError::PinnedPrincipalMismatch {\n        expected,\n        actual: actual.map(str::to_owned),\n    }))\n}\n#[derive(Debug)]\npub(super) struct OidcUserInfo {\n    pub(super) user_id: String,\n    pub(super) email: Option<String>,\n    pub(super) first_name: Option<String>,\n    pub(super) last_name: Option<String>,\n    pub(super) profile_image_asset_id: Option<String>,\n    pub(super) principal_type: Option<String>,\n    pub(super) principal_id: Option<String>,\n    pub(super) team_id: Option<String>,\n    pub(super) team_name: Option<String>,\n    pub(super) team_role: Option<String>,\n    pub(super) organization_id: Option<String>,\n    pub(super) organization_name: Option<String>,","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-shell/src/auth/oidc/protocol.rs#L183-L219","documentation":"OidcError::PinnedPrincipalMismatch is raised by enforce_login_principal when the authenticated user's principal (team UUID) does not satisfy the configured force_login_team_uuid policy. The error carries a pre-formatted `expected` requirement string and the actual principal if known. It blocks logins that succeed at the IdP but fail the local principal pinning check.","triggerScenarios":"run_login_flow_with_config calls enforce_login_principal; the actual team principal from the token is not in the allowed list (Single(id) mismatch, or not a member of AnyOf(ids)), so PinnedPrincipalMismatch { expected, actual } is returned.","commonSituations":"A developer logs in with a personal account or a different team than the one pinned in config; the org changed team IDs; the user picked 'Team' on the consent screen but chose the wrong team.","solutions":["Log in again and select the team whose UUID matches force_login_team_uuid in config","Update force_login_team_uuid to include the team you actually use (or use ForceLoginTeam::AnyOf with several IDs)","Remove the force_login_team_uuid pin if any principal is acceptable"],"exampleFix":"// before\nSome(ForceLoginTeam::Single(\"old-team-id\"))\n// after\nSome(ForceLoginTeam::AnyOf(vec![\"old-team-id\".into(), \"new-team-id\".into()]))","handlingStrategy":"validation","validationCode":"// before login, confirm the expected team pin matches what you will authenticate with\nfn check_pin(expected: &ForceLoginTeam, your_team: &str) -> Result<(), String> {\n    let ok = match expected {\n        ForceLoginTeam::Single(id) => id == your_team,\n        ForceLoginTeam::AnyOf(ids) => ids.iter().any(|i| i == your_team),\n    };\n    if ok { Ok(()) } else { Err(format!(\"login pinned to {expected:?}, your team is {your_team}\")) }\n}","typeGuard":"fn principal_allowed(policy: &ForceLoginTeam, actual: Option<&str>) -> bool {\n    let Some(a) = actual else { return false };\n    match policy {\n        ForceLoginTeam::Single(id) => id == a,\n        ForceLoginTeam::AnyOf(ids) => ids.iter().any(|i| i == a),\n    }\n}","tryCatchPattern":"match run_login_flow().await {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"requires logging into\") => {\n        eprintln!(\"Pinned principal mismatch: {e}; log in with the required team or update config\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep force_login_team_uuid in sync with the team you actually use","Use AnyOf to list all legitimate teams for your deployment","Read the `expected` field in the error; it states the exact requirement"],"tags":["oidc","authorization","principal-pinning"],"backgroundTag":"principal-mismatch","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}