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

  1. Include the code parameter from the authorize redirect in the token request
  2. Handle Canvas::OAuth::RequestError with error code authorization_code_not_supplied and surface a 400 with that code to the client
  3. Do not reuse/retry token exchange with a consumed code; store the code before exchange and only exchange once
  4. 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

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


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)