instructure/canvas-lms · error · OAuthValidationError
No issuer configured for OpenID Connect provider
Error message
No issuer configured for OpenID Connect provider
What it means
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.
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).
Example fix
# before
provider.settings = { "client_id" => "abc" }
# after
provider.settings = { "client_id" => "abc", "issuer" => "https://idp.example.com/realms/main" } Defensive patterns
Strategy: validation
Validate before calling
raise "issuer missing on OIDC provider" if provider.settings["issuer"].blank?
# fetch authoritative value:
issuer = JSON.parse(Net::HTTP.get(URI("#{base_url}/.well-known/openid-configuration")))["issuer"] Try / catch
begin
provider.claims(token)
rescue OAuthValidationError => e
Rails.logger.error("OIDC issuer not configured: #{e.message}")
flash[:error] = "OpenID Connect provider misconfigured; contact an admin."
end Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Invalid JWT audience
- Invalid JWT issuer
- Invalid nonce claim in ID Token
- Invalid signature
- Missing claims
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/5deafe6b3da714fb.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/authentication_provider/open_id_connect.rb:288
end
def claims(token)
token.options[:claims] ||= begin
id_token = unverified_id_token(token)
unless (missing_claims = %w[aud iss iat exp nonce] - id_token.keys).empty?
raise OAuthValidationError, t({ one: "Missing claim %{claims}", other: "Missing claims %{claims}" },
count: missing_claims.length,
claims: missing_claims.join(", "))
end
unless Array(id_token["aud"]).include?(client_id)
raise OAuthValidationError, t("Invalid JWT audience: %{audience}", audience: id_token["aud"].inspect)
end
if self.class.validate_issuer?
if issuer.blank?
raise OAuthValidationError, t("No issuer configured for OpenID Connect provider")
end
unless issuer === id_token["iss"] # rubocop:disable Style/CaseEquality -- may be a string or a RegEx
raise OAuthValidationError, t("Invalid JWT issuer: %{issuer}", issuer: id_token["iss"])
end
end
unless id_token["nonce"] == token.options[:nonce]
raise OAuthValidationError, t("Invalid nonce claim in ID Token")
end
if (signature_error = validate_signature(id_token))
raise OAuthValidationError, t("Invalid signature: %{signature_error}", signature_error:)
end
# we have a userinfo endpoint, and we don't have everything we want,
# then request more
if userinfo_endpoint.present? && !(requested_claims - id_token.keys).empty?
userinfo = token.get(userinfo_endpoint).parsed
debug_set(:userinfo, userinfo.to_json) if instance_debuggingView on GitHub (pinned to 1c9f0bb801)