{"record":{"id":"725235109f4a4450","repo":"instructure/canvas-lms","slug":"user-is-from-unacceptable-tenant-tenant","errorCode":null,"errorMessage":"User is from unacceptable tenant %{tenant}.","messagePattern":"User is from unacceptable tenant %(.+?)\\.","errorType":"validation","errorClass":"OAuthValidationError","httpStatus":null,"severity":"error","filePath":"app/models/authentication_provider/microsoft.rb","lineNumber":106,"sourceCode":"    false\n  end\n\n  def login_attribute\n    raw_login_attribute || \"tid+oid\"\n  end\n\n  def unique_id(token)\n    id_token = claims(token)\n    allowed_tenants = mapped_allowed_tenants\n    if allowed_tenants.empty? || allowed_tenants.include?(\"common\") || settings[\"skip_tenant_verification\"]\n      # allow anyone\n    elsif allowed_tenants.delete(\"guests\")\n      # just check the issuer\n      unless allowed_tenants.find { |tenant| id_token[\"iss\"] == \"https://login.microsoftonline.com/#{tenant}/v2.0\" }\n        raise OAuthValidationError, t(\"User is from unacceptable issuer %{issuer}.\", issuer: id_token[\"iss\"].inspect)\n      end\n    elsif !allowed_tenants.include?(id_token[\"tid\"])\n      raise OAuthValidationError, t(\"User is from unacceptable tenant %{tenant}.\", tenant: id_token[\"tid\"].inspect)\n    end\n\n    ids = id_token.as_json\n    ids[\"tid+oid\"] = \"#{ids[\"tid\"]}##{ids[\"oid\"]}\" if ids[\"tid\"] && ids[\"oid\"]\n    ids.slice(\"tid\", *self.class.login_attributes)\n  end\n\n  # always process through the multi-valued setter\n  def tenant=(value)\n    self.tenants = value\n  end\n\n  def tenants=(value)\n    value = value.split(\",\") if value.is_a?(String)\n    value = value.filter_map(&:strip).uniq\n    value << \"microsoft\" if value.delete(MICROSOFT_TENANT)\n    value = [\"common\"] if value.include?(\"common\")\n    self[\"tenant\"] = value.first","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/authentication_provider/microsoft.rb#L88-L124","documentation":"Raised by the Microsoft authentication provider's unique_id when allowed_tenants is configured (non-empty, not 'common', skip_tenant_verification off) and the 'guests' branch is not taken, but the ID token's tid (tenant ID) claim is not in the allowed tenant list. The user authenticated with Microsoft but belongs to a tenant the Canvas admin did not allow.","triggerScenarios":"unique_id runs during Microsoft OAuth callback with a fixed allow-list of tenants; id_token['tid'] (user's home tenant GUID) is not one of the configured allowed_tenants values, so the elsif fails and raises.","commonSituations":"User signs in with a personal or different-org Microsoft account; admin allow-list contains tenant domain names instead of tenant GUIDs (tid is a GUID); org migrated to a new tenant ID after rebranding/merger.","solutions":["Compare the tid in the error to the configured tenant list and add the missing tenant GUID.","Use the directory's tenant GUID (Azure portal > Azure AD > Overview), not the domain name, in the allowed tenants config.","Set skip_tenant_verification or include 'common' if all Microsoft users should be permitted.","Ask the user to sign in with an account from an allowed tenant."],"exampleFix":"# before\nallowed_tenants: \"contoso.onmicrosoft.com\"\n# after\nallowed_tenants: \"72f988bf-86f1-41af-91ab-2d7cd011db47\"","handlingStrategy":"validation","validationCode":"tid = id_token[\"tid\"]\nallowed = provider_settings[\"allowed_tenants\"].split(\",\").map(&:strip)\nraise \"tenant #{tid} not allowed\" unless allowed.empty? || allowed.include?(\"common\") || allowed.include?(tid)","typeGuard":null,"tryCatchPattern":"begin\n  user.unique_id\nrescue OAuthValidationError => e\n  Rails.logger.warn(\"Microsoft tenant rejected: #{e.message}\")\n  render json: { error: \"tenant_not_allowed\" }, status: :forbidden\nend","preventionTips":["Use directory GUIDs (Azure portal > Overview > Tenant ID), not domain names","Re-check the allow-list after tenant migrations/mergers","Log the tid claim on rejections to ease allow-list updates"],"tags":["oauth","microsoft","sso","tenant-validation"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}