# frozen_string_literal: true module Rodauth Feature.define(:oauth_authorization_code_grant, :OauthAuthorizationCodeGrant) do depends :oauth_authorize_base auth_value_method :use_oauth_access_type?, true private def validate_authorize_params super redirect_response_error("invalid_request") unless check_valid_access_type? && check_valid_approval_prompt? redirect_response_error("invalid_request") if (response_mode = param_or_nil("response_mode")) && response_mode != "form_post" try_approval_prompt if use_oauth_access_type? && request.get? end def validate_oauth_token_params redirect_response_error("invalid_request") if param_or_nil("grant_type") == "authorization_code" && !param_or_nil("code") super end def try_approval_prompt approval_prompt = param_or_nil("approval_prompt") return unless approval_prompt && approval_prompt == "auto" return if db[oauth_grants_table].where( oauth_grants_account_id_column => account_id, oauth_grants_oauth_application_id_column => oauth_application[oauth_applications_id_column], oauth_grants_redirect_uri_column => redirect_uri, oauth_grants_scopes_column => scopes.join(oauth_scope_separator), oauth_grants_access_type_column => "online" ).count.zero? # if there's a previous oauth grant for the params combo, it means that this user has approved before. request.env["REQUEST_METHOD"] = "POST" end def create_oauth_grant(create_params = {}) # Access Type flow if use_oauth_access_type? && (access_type = param_or_nil("access_type")) create_params[oauth_grants_access_type_column] = access_type end super end def do_authorize(response_params = {}, response_mode = param_or_nil("response_mode")) case param("response_type") when "code" response_mode ||= "query" response_params.replace(_do_authorize_code) when "none" response_mode ||= "none" when "", nil response_mode ||= oauth_response_mode response_params.replace(_do_authorize_code) else return super if response_params.empty? end response_params["state"] = param("state") if param_or_nil("state") [response_params, response_mode] end def _do_authorize_code create_params = { oauth_grants_account_id_column => account_id } # Access Type flow if use_oauth_access_type? && (access_type = param_or_nil("access_type")) create_params[oauth_grants_access_type_column] = access_type end { "code" => create_oauth_grant(create_params) } end def authorize_response(params, mode) redirect_url = URI.parse(redirect_uri) case mode when "query" params = params.map { |k, v| "#{k}=#{v}" } params << redirect_url.query if redirect_url.query redirect_url.query = params.join("&") redirect(redirect_url.to_s) when "form_post" scope.view layout: false, inline: <<-FORM