Cognito × ALBで実装した時のerror=redirect_mismatchを解決する #486
Cognitoでアプリケーションへの認証機能を追加しようとして、ハマったので対応方法をメモしておきます。
ALBのリスナールールにCognitoを追加してルーティングするところまでは難なく終わったのですが、ルーティングした先でerror=redirect_mismatchが出てしまい認証ページまで飛べませんでした。
基本構成
参考ブログにある「以下のアーキテクチャ図の通り、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
}
}
ここまでお読みいただきありがとうございました!!