{"record":{"id":"5deafe6b3da714fb","repo":"instructure/canvas-lms","slug":"no-issuer-configured-for-openid-connect-provider","errorCode":null,"errorMessage":"No issuer configured for OpenID Connect provider","messagePattern":"No issuer configured for OpenID Connect provider","errorType":"validation","errorClass":"OAuthValidationError","httpStatus":null,"severity":"error","filePath":"app/models/authentication_provider/open_id_connect.rb","lineNumber":288,"sourceCode":"    end\n\n    def claims(token)\n      token.options[:claims] ||= begin\n        id_token = unverified_id_token(token)\n\n        unless (missing_claims = %w[aud iss iat exp nonce] - id_token.keys).empty?\n          raise OAuthValidationError, t({ one: \"Missing claim %{claims}\", other: \"Missing claims %{claims}\" },\n                                        count: missing_claims.length,\n                                        claims: missing_claims.join(\", \"))\n        end\n\n        unless Array(id_token[\"aud\"]).include?(client_id)\n          raise OAuthValidationError, t(\"Invalid JWT audience: %{audience}\", audience: id_token[\"aud\"].inspect)\n        end\n\n        if self.class.validate_issuer?\n          if issuer.blank?\n            raise OAuthValidationError, t(\"No issuer configured for OpenID Connect provider\")\n          end\n          unless issuer === id_token[\"iss\"] # rubocop:disable Style/CaseEquality -- may be a string or a RegEx\n            raise OAuthValidationError, t(\"Invalid JWT issuer: %{issuer}\", issuer: id_token[\"iss\"])\n          end\n        end\n        unless id_token[\"nonce\"] == token.options[:nonce]\n          raise OAuthValidationError, t(\"Invalid nonce claim in ID Token\")\n        end\n\n        if (signature_error = validate_signature(id_token))\n          raise OAuthValidationError, t(\"Invalid signature: %{signature_error}\", signature_error:)\n        end\n\n        # we have a userinfo endpoint, and we don't have everything we want,\n        # then request more\n        if userinfo_endpoint.present? && !(requested_claims - id_token.keys).empty?\n          userinfo = token.get(userinfo_endpoint).parsed\n          debug_set(:userinfo, userinfo.to_json) if instance_debugging","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/authentication_provider/open_id_connect.rb#L270-L306","documentation":"Raised in claims() when issuer validation is enabled (self.class.validate_issuer?) but the provider has no issuer configured (issuer is blank). Canvas refuses to validate an ID token against an unknown issuer, so it fails closed instead of trusting the token.","triggerScenarios":"An OpenID Connect authentication provider with validate_issuer enabled is saved/used without an issuer value in its settings; the first login calls claims() via unique_id/provider_attributes and hits the blank-issuer check.","commonSituations":"Admin enabled strict issuer validation but left the issuer field empty; issuer was never set because the provider was created via API/import with partial settings; upgrade turned on issuer validation by default for existing providers missing the setting.","solutions":["Set the issuer on the provider (e.g. https://idp.example.com or the realm's issuer URL from the IdP's discovery document /.well-known/openid-configuration).","If issuer validation is not wanted, disable validate_issuer for the provider.","Verify the issuer string matches exactly what the IdP puts in the iss claim (scheme, host, path, trailing slash)."],"exampleFix":"# before\nprovider.settings = { \"client_id\" => \"abc\" }\n# after\nprovider.settings = { \"client_id\" => \"abc\", \"issuer\" => \"https://idp.example.com/realms/main\" }","handlingStrategy":"validation","validationCode":"raise \"issuer missing on OIDC provider\" if provider.settings[\"issuer\"].blank?\n# fetch authoritative value:\nissuer = JSON.parse(Net::HTTP.get(URI(\"#{base_url}/.well-known/openid-configuration\")))[\"issuer\"]","typeGuard":null,"tryCatchPattern":"begin\n  provider.claims(token)\nrescue OAuthValidationError => e\n  Rails.logger.error(\"OIDC issuer not configured: #{e.message}\")\n  flash[:error] = \"OpenID Connect provider misconfigured; contact an admin.\"\nend","preventionTips":["Always set issuer when creating OIDC providers via API or SIS import","Copy issuer from the discovery document, never guess","Validate provider settings at save time"],"tags":["oidc","sso","configuration","issuer-validation"],"backgroundTag":"missing-required-config-field","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"}