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
相关产品推荐
相关产品推荐

