You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Cognito集成出现redirect_mismatch错误求助

AWS Cognito集成EC2应用时redirect_mismatch错误排查

问题现象

访问部署在EC2实例上的应用时,触发Cognito认证流程后出现错误:

An error was encountered with the requested page

错误URL为:https://my-domain/error?error=redirect_mismatch&client_id=(client ID)

当前Cognito用户池客户端配置的登录/登出回调URL为https://<EC2-IP>/auth/sign_in和https://<EC2-IP>/auth/sign_out(注:原描述中https:ec2-ip存在格式错误,应为https://<EC2-IP>)。应用通过Docker容器部署在EC2上,预期能正常跳转至Cognito登录页面。

相关代码片段

Auth_Controller.rb

def signin
    unless params[:code]
      render :nothing => true, :status => :bad_request
      return
    end

    resp = lookup_auth_code(params[:code])
    unless resp
      redirect_to '/'
      return
    end

    ActiveRecord::Base.transaction do
      user = User.where(subscriber: resp.id_token[:sub]).first
      if user.nil?
        user = User.create(subscriber: resp.id_token[:sub],
                           email: resp.id_token[:email])

          render file: "#{Rails.root}/public/user_taken.html", layout: false
          return
        end
      end

      cognito_session = CognitoSession.create(user: user,
                                              expire_time: resp.id_token[:exp],
                                              issued_time: resp.id_token[:auth_time],
                                              audience: resp.id_token[:aud],
                                              refresh_token: resp.refresh_token)
      session[:cognito_session_id] = cognito_session.id
    end
  end

  def signout
    if cognito_session_id = session[:cognito_session_id]
      cognito_session = CognitoSession.find(cognito_session_id) rescue nil
      cognito_session.destroy if cognito_session
      session.delete(:cognito_session_id)
    end

    session[:current_queries] = nil

    redirect_to '/'
  end

  def lookup_auth_code(code)
    client = new_cognito_client()
    client.get_pool_tokens(code)
  end
end

Session_Controller.rb

class SessionsController < ApplicationController
  skip_before_action :redirect_to_signin
  def signin
    redirect_to cognito_signin_url
  end

  def signout
    redirect_to cognito_signout_url
  end

  def signup
    redirect_to cognito_signup_url
  end

private

  def cognito_signin_url
    CognitoUrls.login_uri(ENV['AWS_COGNITO_APP_CLIENT_ID'],
                          signin_redirect_uri)
  end

  def cognito_signup_url
    CognitoUrls.signup_uri(ENV['AWS_COGNITO_APP_CLIENT_ID'],
                           signin_redirect_uri)
  end

  def cognito_signout_url
    CognitoUrls.logout_uri(ENV['AWS_COGNITO_APP_CLIENT_ID'],
                           signout_redirect_uri)
  end

  def signin_redirect_uri
    auth_sign_in_url
  end

  def signout_redirect_uri
    auth_sign_out_url
  end
end

Routes.rb

require 'sidekiq/web'
require 'sidekiq/cron/web'

Rails.application.routes.draw do
  get '/sign_in', as: 'signin', to: 'sessions#signin'
  get '/sign_out', as: 'signout', to: 'sessions#signout'
  get '/sign_up', as: 'signup', to: 'sessions#signup'

  get 'auth/sign_in', to: 'auth#signin'
  get 'auth/sign_out', to: 'auth#signout'

Cognito_URL.rb

class CognitoUrls
  AUTHORIZE_PATH = "/oauth2/authorize"
  TOKEN_PATH = "/oauth2/token"
  LOGIN_PATH = "/login"
  LOGOUT_PATH = "/logout"
  SIGNUP_PATH = "/signup"

  class << self
    @base_oauth_uri = nil
    @base_idp_uri = nil

    def init(domain, region)
      @base_oauth_uri = ENV['OAUTH_URL']
      # @base_oauth_uri = "https://%s.auth.%s.amazoncognito.com" % [domain, region]
      @base_idp_uri = "https://cognito-idp.%s.amazonaws.com" % [region]
    end

    def jwks_uri(pool_id)
      path = "/%s/.well-known/jwks.json" % [pool_id]
      URI.join(@base_idp_uri, path).to_s
    end

    def refresh_token_uri
      @base_idp_uri
    end

    def authorize_uri
      URI.join(@base_oauth_uri, AUTHORIZE_PATH).to_s
    end

    def token_uri
      URI.join(@base_oauth_uri, TOKEN_PATH).to_s
    end

    def force_https(url)
      uri = URI.parse(url)
      uri.scheme = "https"
      uri.to_s
    end

    def login_uri(app_client_id, redirect_uri)
      if Rails.env == 'production'
        redirect_uri = force_https(redirect_uri)
      end
      path = "%s?response_type=code&client_id=%s&redirect_uri=%s" %
        [LOGIN_PATH, app_client_id, redirect_uri]
      URI.join(@base_oauth_uri, path).to_s
    end

    def logout_uri(app_client_id, redirect_uri)
      if Rails.env == 'production'
        redirect_uri = force_https(redirect_uri)
      end
      path = "%s?response_type=code&client_id=%s&logout_uri=%s" %
        [LOGOUT_PATH, app_client_id, redirect_uri]
      URI.join(@base_oauth_uri, path).to_s
    end

    def signup_uri(app_client_id, redirect_uri)
      if Rails.env == 'production'
        redirect_uri = force_https(redirect_uri)
      end
      path = "%s?response_type=code&client_id=%s&redirect_uri=%s" %
        [SIGNUP_PATH, app_client_id, redirect_uri]
      URI.join(@base_oauth_uri, path).to_s
    end
  end
end

排查建议

  • 精确匹配回调URL:Cognito要求回调URL必须完全一致,包括协议、IP/域名、路径。检查Cognito客户端配置的URL是否和auth_sign_in_url、auth_sign_out_url生成的地址完全匹配,注意修正原配置中https:ec2-ip的格式错误为https://<EC2-IP>。
  • 检查URL生成逻辑:在Rails控制台执行Rails.application.routes.url_helpers.auth_sign_in_url(host: '<EC2-IP>'),确认生成的URL是否符合预期,同时验证ENV['OAUTH_URL']是否指向正确的Cognito用户池域名。
  • 修正登出参数错误:CognitoUrls.logout_uri中多余的response_type=code参数需移除,登出流程不需要该参数,会导致Cognito解析异常。
  • 确认EC2访问协议:如果EC2应用使用HTTP,Cognito回调URL不能配置为HTTPS,需保持协议一致;生产环境建议为EC2配置HTTPS(如通过负载均衡或SSL证书)。
  • 检查Docker端口映射:确认容器端口映射正确,外部访问的EC2端口对应容器内应用端口,避免因端口不匹配导致回调URL无效。

内容的提问来源于stack exchange,提问作者Josh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 00:48:10