{"record":{"id":"d83e169ca7c0ff25","repo":"instructure/canvas-lms","slug":"user-is-from-unacceptable-issuer-issuer","errorCode":null,"errorMessage":"User is from unacceptable issuer %{issuer}.","messagePattern":"User is from unacceptable issuer %(.+?)\\.","errorType":"validation","errorClass":"OAuthValidationError","httpStatus":null,"severity":"error","filePath":"app/models/authentication_provider/microsoft.rb","lineNumber":103,"sourceCode":"  end\n\n  def self.validate_issuer?\n    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","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/authentication_provider/microsoft.rb#L85-L121","documentation":"Raised by Canvas's Microsoft authentication provider during OAuth login when the admin configured the provider to allow 'guests' tenants plus specific tenant IDs, but the ID token's issuer (iss) does not match https://login.microsoftonline.com/<tenant>/v2.0 for any allowed tenant. It is an OAuthValidationError meaning the user authenticates successfully with Microsoft but is not from an acceptable tenant.","triggerScenarios":"unique_id runs after Microsoft callback: allowed_tenants is non-empty, does not include 'common', skip_tenant_verification is off, and 'guests' was in the configured tenants list; id_token['iss'] (e.g. https://login.microsoftonline.com/9188040d-.../v2.0 for personal MSA accounts) matches none of the allowed tenant issuer URLs.","commonSituations":"Admin adds 'guests' to allowed tenants expecting guest accounts to pass, but the user's issuer is a tenant not explicitly listed (personal Microsoft accounts or guest home tenants). Azure AD tenant ID changes or issuer URL version differs (v2.0 vs v1.0). Typos in tenant IDs in the allowed list.","solutions":["Add the exact tenant ID(s) whose users should be allowed to the provider's allowed_tenants config so the issuer URL matches.","Verify the configured tenant IDs match the 'tid' claim shown in the rejected issuer URL in the error message.","If any Microsoft account should be allowed, set skip_tenant_verification (or include 'common') in the provider settings.","Confirm the issuer version: the check expects the /v2.0 endpoint; ensure the provider uses the v2.0 endpoints."],"exampleFix":"# before\nsettings[\"microsoft_tenant\"] = \"guests,contoso.onmicrosoft.com\"\n# after (use the tenant GUID or ensure issuer matches)\nsettings[\"allowed_tenants\"] = \"guests,00000000-0000-0000-0000-000000000000\"","handlingStrategy":"validation","validationCode":"iss = id_token[\"iss\"]\nallowed = provider_settings[\"allowed_tenants\"].split(\",\")\nunless allowed.empty? || allowed.include?(\"common\") || provider_settings[\"skip_tenant_verification\"]\n  raise \"unacceptable issuer #{iss}\" if allowed.include?(\"guests\") && !allowed.grep_v(\"guests\").any? { |t| iss == \"https://login.microsoftonline.com/#{t}/v2.0\" }\nend","typeGuard":null,"tryCatchPattern":"begin\n  user.unique_id\nrescue OAuthValidationError => e\n  Rails.logger.warn(\"Microsoft tenant rejected: #{e.message}\")\n  redirect_to login_path, alert: \"Your Microsoft account is not from an allowed tenant.\"\nend","preventionTips":["Always use Azure tenant GUIDs in the allowed tenants list","Include 'guests' plus every guest home tenant you expect","Test login with a personal Microsoft account when 'common' is not set","Check the issuer URL version (/v2.0) matches your endpoints"],"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"}