見出し画像

Cognito × ALBで実装した時のerror=redirect_mismatchを解決する #486

Cognitoでアプリケーションへの認証機能を追加しようとして、ハマったので対応方法をメモしておきます。

ALBのリスナールールにCognitoを追加してルーティングするところまでは難なく終わったのですが、ルーティングした先でerror=redirect_mismatchが出てしまい認証ページまで飛べませんでした。

基本構成

参考ブログにある「以下のアーキテクチャ図の通り、Cognitoだけで認証機能を追加しました。アプリケーション側には何も追加していません。

EC2とALBでコンテンツを配信している環境にCognitoで認証を追加してみました


起きたこと

以下のようにAn error was encountered with the requested page.が表示され、Cognitoの認証画面に遷移できませんでした。

また、APIレスポンスを見ると以下のようなエラーが返って来ていました。

error=redirect_mismatch


原因

色々と調べると、これはCognitoのcallback_urlsの設定が間違っていたことが原因でした。

当初はユーザープールクライアントを以下のように実装していました(Terraformで一部抜粋)。

resource "aws_cognito_user_pool_client" "my_client" {
  name         = "${var.project}-user-pool-client"
  user_pool_id = aws_cognito_user_pool.my_pool.id
  generate_secret = true

  ~ 中略 ~

  callback_urls                        = ["${var.login_url}/] # 認証後にリダイレクトするURL
  logout_urls                          = ["${var.login_url}/no-use/"] # 利用しないためダミーのURLを指定
  explicit_auth_flows                  = ["ALLOW_USER_SRP_AUTH", "ALLOW_REFRESH_TOKEN_AUTH"]
  prevent_user_existence_errors        = "ENABLED"
  supported_identity_providers         = ["COGNITO"]

  ~ 中略 ~

}

ALBのリスナールールで以下の流れを組んでおり、callback_urlsはCognitoで認証後のURLであるため、ALBに戻す意図でアプリケーションのURLをそのまま指定していました。

アプリケーションのURLでリクエスト → ALB → Cognito → ALB → アプリケーション(ECS)

しかしCognito経由後にALBに戻す場合、この指定方法ではダメだったのです。


解決方法

callback_urlsに「/oauth2/idpresponse」というパスを追加すればOKです。Cognito認証後に再度ALBに戻す場合、このようにする必要があるみたいでした。

resource "aws_cognito_user_pool_client" "my_client" {
  name         = "${var.project}-user-pool-client"
  user_pool_id = aws_cognito_user_pool.my_pool.id
  generate_secret = true

  ~ 中略 ~

  callback_urls                        = ["${var.login_url}/oauth2/idpresponse"] # 認証後にリダイレクトするURL(ALBに戻すには左記のパスにする)
  logout_urls                          = ["${var.login_url}/no-use/"]            # 利用しないためダミーのURLを指定
  explicit_auth_flows                  = ["ALLOW_USER_SRP_AUTH", "ALLOW_REFRESH_TOKEN_AUTH"]
  prevent_user_existence_errors        = "ENABLED"
  supported_identity_providers         = ["COGNITO"]

  ~ 中略 ~

}

(参考)ALBの実装例

resource "aws_lb_listener" "main" {
  port            = "443"
  protocol        = "HTTPS"
  depends_on      = [aws_lb_target_group.grpc, aws_lb_target_group.http]
  certificate_arn = var.certificate_arn

  load_balancer_arn = aws_lb.main.arn

  default_action {
    type = "authenticate-cognito"
    authenticate_cognito {
      user_pool_arn       = var.cognito_user_pool_arn
      user_pool_client_id = var.cognito_user_pool_client_id
      user_pool_domain    = var.cognito_user_pool_domain
    }
  }

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.grpc.arn
  }
}


ここまでお読みいただきありがとうございました!!


参考


いいなと思ったら応援しよう!