{"record":{"id":"4b510a8614d63bf9","repo":"bitwarden/server","slug":"externalauthenticationerror","errorCode":null,"errorMessage":"ExternalAuthenticationError","messagePattern":"ExternalAuthenticationError","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"bitwarden_license/src/Sso/Controllers/AccountController.cs","lineNumber":273,"sourceCode":"            throw new Exception(_i18nService.T(\"InvalidSsoToken\"));\n        }\n\n        if (!Guid.TryParse(scheme, out var schemeOrgId) || tokenable.OrganizationId != schemeOrgId)\n        {\n            throw new Exception(_i18nService.T(\"SsoOrganizationIdMismatch\"));\n        }\n    }\n\n    [HttpGet]\n    public async Task<IActionResult> ExternalCallback()\n    {\n        // Read external identity from the temporary cookie\n        var result = await HttpContext.AuthenticateAsync(\n            AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme);\n\n        if (!result.Succeeded)\n        {\n            throw new Exception(_i18nService.T(\"ExternalAuthenticationError\"));\n        }\n\n        // See if the user has logged in with this SSO provider before and has already been provisioned.\n        // This is signified by the user existing in the User table and the SSOUser table for the SSO provider they're using.\n        var (possibleSsoLinkedUser, provider, providerUserId, claims, ssoConfigData) = await FindUserFromExternalProviderAsync(result);\n\n        // We will look these up as required (lazy resolution) to avoid multiple DB hits.\n        Organization? organization = null;\n        OrganizationUser? orgUser = null;\n\n        // The user has not authenticated with this SSO provider before.\n        // They could have an existing Bitwarden account in the User table though.\n        if (possibleSsoLinkedUser == null)\n        {\n            // FIXME: Update this file to be null safe and then delete the line below\n#nullable disable\n            // If we're manually linking to SSO, the user's external identifier will be passed as query string parameter.\n            var userIdentifier = result.Properties.Items.Keys.Contains(\"user_identifier\")","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/bitwarden_license/src/Sso/Controllers/AccountController.cs#L255-L291","documentation":"Thrown in AccountController.ExternalCallback (line 273) when HttpContext.AuthenticateAsync against the BitwardenExternalCookieAuthenticationScheme does not return a successful result. The temporary external cookie is set during the Challenge redirect and must be present and valid when the IdP redirects back.","triggerScenarios":"The external authentication cookie is missing, expired, corrupted, or the IdP returned an error that prevented a valid cookie from being set.","commonSituations":"Cookie blocked by browser privacy settings; user took too long and the temp cookie expired; load balancer or proxy stripping cookies; IdP returned an error response instead of a valid auth code; the callback URL was accessed directly without going through the Challenge flow.","solutions":["Ensure the user navigates through the full Challenge → IdP → Callback flow; do not bookmark or directly visit the ExternalCallback URL.","Check browser cookie settings and SameSite configuration for the external auth cookie.","Verify the IdP redirect URI matches the configured callback exactly.","Inspect the IdP's response for errors (check IdP logs and browser network tab)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await ExternalCallback(); }\ncatch (Exception ex) when (ex.Message.Contains(\"ExternalAuthenticationError\"))\n{\n    _logger.LogError(ex, \"External auth failed during SSO callback\");\n    return Redirect($\"/login?error=sso_external_error\");\n}","preventionTips":["Ensure the user reaches ExternalCallback only through the full Challenge → IdP → redirect flow.","Configure SameSite and Secure attributes on the external auth cookie correctly.","Set an appropriate timeout on the external cookie to cover IdP login latency.","Monitor IdP health and surface IdP errors to users clearly."],"tags":["sso","authentication","idp","cookie","callback","configuration"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}