instructure/canvas-lms · error · Canvas::OAuth::RequestError
authorization_code_not_supplied
authorization_code_not_supplied
Error message
authorization_code_not_supplied
What it means
Canvas::OAuth::GrantTypes::AuthorizationCode#validate_type raises Canvas::OAuth::RequestError with code :authorization_code_not_supplied when the token request opts lack :code. The OAuth authorization-code grant fundamentally requires the code parameter returned from the authorize step.
Solutions
- Include the code parameter from the authorize redirect in the token request
- Handle Canvas::OAuth::RequestError with error code authorization_code_not_supplied and surface a 400 with that code to the client
- Do not reuse/retry token exchange with a consumed code; store the code before exchange and only exchange once
- Check the request body encoding (form vs query) so code isn't dropped by your HTTP client
Example fix
// before curl -d grant_type=authorization_code -d client_id=... -d client_secret=... /login/oauth2/token // after curl -d grant_type=authorization_code -d client_id=... -d client_secret=... -d code=<authorization_code> -d redirect_uri=... /login/oauth2/token
Defensive patterns
Strategy: validation
Validate before calling
raise 'code missing' if params[:code].blank? && params[:grant_type] == 'authorization_code'
Type guard
const hasCode = typeof params.code === 'string' && params.code.length > 0
Try / catch
begin
token = client.exchange_code_for_token
rescue Canvas::OAuth::RequestError => e
render json: { error: e.error_code || 'authorization_code_not_supplied' }, status: :bad_request
end Prevention
- Always carry the authorize-step code through redirects before exchanging
- Exchange each authorization code exactly once
- Include redirect_uri in the token request to match the authorize step
When it happens
Trigger: POSTing to /login/oauth2/token with grant_type=authorization_code but omitting the code parameter.
Common situations: Client apps exchanging a code twice (code consumed, treated as absent on retry), forgetting to pass the code through a redirect handler, misbuilt token request body, dev tools dropping query params.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- A maximum of 50 assessees can be provided at once
- A maximum of 50 assessors can be provided at once
- A partner ID is required to use Academic Benchmarks
- A partner key is required to use Academic Benchmarks
- An object of type was hidden due to insufficient scopes on…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/b207bcd8e257e8ec.
Report an issue: GitHub.
Appendix: source
Thrown at lib/canvas/oauth/grant_types/authorization_code.rb:13
# frozen_string_literal: true
module Canvas::OAuth
module GrantTypes
class AuthorizationCode < BaseType
def supported_type?
true
end
private
def validate_type
raise Canvas::OAuth::RequestError, :authorization_code_not_supplied unless @opts[:code]
@_token = @provider.token_for(@opts[:code])
raise Canvas::OAuth::RequestError, :invalid_authorization_code unless @_token.is_for_valid_code?
raise Canvas::OAuth::RequestError, :incorrect_client unless [@_token.key.global_id, @_token.key.id].include? @_token.client_id.to_i
end
def generate_token
@_token.create_access_token_if_needed(replace_tokens: Canvas::Plugin.value_to_boolean(@opts[:replace_tokens]))
Canvas::OAuth::Token.expire_code(@opts[:code])
@_token
end
end
end
end
View on GitHub (pinned to 1c9f0bb801)