実現したいこと
メールのリンク押下時に認証成功&指定したURLにリダイレクトしたい
SPAなのでリダイレクト先はNext.js
発生している問題・分からないこと
Devise + Devise Token Authを認証に使ったSPAで、サインアップ後に送信される認証メールのリンク押下すると500エラーになり認証が失敗する。尚、このエラーは本番環境でのみ発生し、開発環境では成功する。
本番環境はAWSのECS Fargateにデプロイ。タスク1つにつきNginx(リバースプロキシ)とRailsの構成でそれぞれコンテナ化しています。流れはRoute53 → ALB → Nginx → Railsとなり、Route53にサブドメインとしてAレコードでapi.my-service.netのように登録し、ALBに向けています。
メール内の認証リンクを押すとhttps://api.my-service.net/api/v1/auth/confirmation?config=default&confirmation_token=hogefugabar
にリダイレクトされ、500エラーになります(URLが左記のものが残ったまま)。期待しているのはGET /api/v1/auth/confirmationで認証が処理された後、https://my-service.net/account_confirmation_success=true
にリダイレクトされることです。
エラーメッセージ
error
1500 Internal Server Error 2 3Nginxコンテナのログ(CloudWatch) 4 5# サインアップ 6"POST /api/v1/auth/confirmation HTTP/1.1" 200 119 "https://www.my-service.net/" 7 8# 認証リンク押下 9"GET /api/v1/auth/confirmation?config=default&confirmation_token=ZhpLxqjmVbs4kgxS_QfH HTTP/1.1" 500 26 "-" 10 11# 認証リンク押下と同時刻に出ているログ 12[error] 14#14: *99 open() "/app/public/404.html" failed (2: No such file or directory), client: 10.0.1.23, server: localhost, request: "GET /favicon.ico HTTP/1.1", upstream: "http://unix:///app/tmp/sockets/puma.sock/favicon.ico", host: "api.my-service.net", referrer: "https://api.my-service.net/api/v1/auth/confirmation?config=default&confirmation_token=ZhpLxqjmVbs4kgxS_QfH"
該当のソースコード
confirmation_instructions.html.erb
1<p><%= @email %> さん、</p> 2 3<p>アカウント登録ありがとうございます!</p> 4 5<p>以下のリンクを押して、本登録を完了してください。</p><br> 6 7<p> 8 <%= link_to "アカウントを認証する", confirmation_url(@resource, { 9 confirmation_token: @token, 10 config: message['client-config'].to_s, 11 }).html_safe %> 12</p> 13 14<p>リンクの有効期間は3日間です。お早めにご対応ください。</p><br>
production.rb
1config.action_mailer.default_url_options = { host: "https://api.my-service.net" } 2config.hosts << "api.my-service.net"
user.rb
1devise :database_authenticatable, :registerable, 2 :recoverable, :validatable, :confirmable 3# :lockable, :timeoutable, :trackable, :omniauthable, :rememberable 4 5include DeviseTokenAuth::Concerns::User
devise_token_auth.rb
1config.default_confirm_success_url = ENV["DEFAULT_CONFIRM_SUCCESS_URL"] || "http://localhost:3000" 2config.default_password_reset_url = ENV["DEFAULT_PASSWORD_RESET_URL"] || "http://localhost:3000/password-reset" 3 4config.redirect_whitelist = [ 5 "https://www.my-service.net", 6 "https://www.my-service.net/password-reset" 7]
## Nginxの設定 # Pumaとの通信に Unixドメインソケット を利用 upstream api { server unix:///app/tmp/sockets/puma.sock; } server { listen 80; server_name localhost; # ログ出力先 access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # 静的ファイルのルート(Railsの /public を参照) root /app/public; # クライアントがアップロード可能な最大リクエストサイズ(m = MB) client_max_body_size 100m; keepalive_timeout 5; # ALBからのヘルスチェックエンドポイント location = /healthcheck { access_log off; return 200 "OK"; add_header Content-Type text/plain; } # エラーページ指定 error_page 404 /404.html; error_page 502 503 504 505 /500.html; # エラーページへの直接アクセスをブロック location = /404.html { internal; } location = /500.html { internal; } # リクエストファイル($uri)が存在すれば返し、なければRailsへルーティング try_files $uri @api; # リバースプロキシ設定 location @api { proxy_pass http://api; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_intercept_errors on; } }
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
本番環境で使うDEFAULT_CONFIRM_SUCCESS_URLはタスク定義に環境変数として渡しています。
Devise Token Authのconfirmations_controller.rbのコードも見たが500エラーになる理由が不明。
補足
Ruby: 3.3.7 Rails: 7.2.2.1
RailsはAPIモード
検証していませんが、同じ理由で本番でパスワードリセットリンクを踏んでも失敗すると想像しています
追記:
開発:Next.js, Nginx, Rails, Postgresをコンテナ化して疎通
本番:Vercel(Next.js), Route53 → ALB → ECS Fargate(Nginx/Rails)→ RDS
環境は上記です。S3はまだ未設置のためALBのログなし、Railsログはマイグレーションや起動成功したことのみログに出ています。クライアントからRailsへの他リクエストやRDSとの疎通は問題ありません。Nginxのエラーログはこのタイミングで初めて出ましたが今回のエラーと関係あるかは不明。
本番用の環境変数はタスク定義で渡しています。何度も確認したので設定値に誤りはないと思います。
回答1件
あなたの回答
tips
プレビュー