Fixing Cognito Identity Pool 'No Authentication Provider Mapping' Error: Root Cause & Complete Solution
Threat/Impact Level: HIGH | Exploitability/Downtime Risk: HIGH | Time to Fix: 15 mins
TL;DR
- What broke: Your Cognito Identity Pool has no authentication provider mapped to it — no User Pool, no OIDC, no SAML. Every call to
GetIdorGetCredentialsForIdentityfails withNotAuthorizedExceptionor silently falls through to unauthenticated role (if enabled), granting wrong-scoped AWS credentials to callers. - How to fix it: Add the correct
CognitoIdentityProvidersblock (for User Pool federation) or the appropriateSupportedLoginProviders/OpenIdConnectProviderARNsentry matching your IdP. Verify the IAM role trust policy allowscognito-identity.amazonaws.comwith the correctamrcondition. - Use our Client-Side Sandbox above to auto-refactor this. Paste your broken Terraform or CloudFormation Identity Pool block and get a corrected config without sending your ARNs to a third-party server.
▼ 🔍 Root Cause Breakdown & Kernel Diagnostics [Click to Expand Deep Dive]
The Incident (What Does the Error Mean?)
Raw error surface — what you see in CloudWatch or your SDK:
NotAuthorizedException: Identity pool <us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx> does not have a provider configured for login provider <cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXXX>or silently:
{
"__type": "NotAuthorizedException",
"message": "Access to Identity '<identity-id>' is forbidden."
}Immediate consequence: cognitoidentity:GetId cannot resolve the incoming JWT issuer to a known provider entry in the pool. The identity broker has no mapping to evaluate, so it either rejects the token outright or — worse — falls back to the unauthenticated role if AllowUnauthenticatedIdentities is true. That second case is the silent production killer: your users get credentials, but they're the wrong credentials scoped to the unauth role, and you won't know until an IAM policy boundary blocks a real operation downstream.
▼ 🔍 Detailed Impact & Blast Radius Analysis [Click to Expand Deep Dive]
The Attack Vector / Blast Radius
This is not just a configuration nuisance. The blast radius depends on your AllowUnauthenticatedIdentities setting:
Scenario A — Unauthenticated identities disabled (correct posture): All federated logins hard-fail. Full auth outage. Every user hitting GetCredentialsForIdentity gets a 403. Your React/mobile app cannot bootstrap AWS SDK clients. S3 uploads, API Gateway SigV4 calls, AppSync subscriptions — all dead.
Scenario B — Unauthenticated identities enabled (dangerous posture): Callers presenting a valid-but-unmapped JWT token silently receive unauthenticated role credentials. If that unauth IAM role is over-permissioned (a common misconfiguration), an attacker can present any token from any issuer, get AWS credentials, and pivot laterally. The Cognito Identity Pool becomes an open credential vending machine. This is a real attack path against misconfigured multi-tenant SaaS deployments.
The core problem: CognitoIdentityProviders (for User Pool) or SupportedLoginProviders (for social/OIDC) is either completely absent from the Identity Pool definition, or the ProviderName string does not exactly match the JWT iss claim — a single character mismatch causes the same failure.
How to Fix It
Basic Fix — Terraform
The cognito_identity_pool resource is missing its provider block entirely or has a wrong provider_name.
resource "aws_cognito_identity_pool" "main" {
identity_pool_name = "my-app-identity-pool"
- allow_unauthenticated_identities = true
+ allow_unauthenticated_identities = false
- # No provider block — this is the root cause
+ cognito_identity_providers {
+ client_id = aws_cognito_user_pool_client.app.id
+ provider_name = "cognito-idp.${var.aws_region}.amazonaws.com/${aws_cognito_user_pool.main.id}"
+ server_side_token_check = true
+ }
}Critical: provider_name must exactly equal the iss claim in the Cognito User Pool JWT — format is cognito-idp.<region>.amazonaws.com/<UserPoolId>. No trailing slash. No https:// prefix for this field (unlike OIDC).
Enterprise Best Practice — Role Mapping with Token-Based Disambiguation
For multi-IdP pools, use Rules-based role mapping with token claim conditions instead of a single default authenticated role. This enforces least-privilege per identity source.
resource "aws_cognito_identity_pool_roles_attachment" "main" {
identity_pool_id = aws_cognito_identity_pool.main.id
roles = {
- "authenticated" = aws_iam_role.cognito_auth.arn
- "unauthenticated" = aws_iam_role.cognito_unauth.arn
+ "authenticated" = aws_iam_role.cognito_auth_default.arn
}
+ role_mapping {
+ identity_provider = "cognito-idp.${var.aws_region}.amazonaws.com/${aws_cognito_user_pool.main.id}:${aws_cognito_user_pool_client.app.id}"
+ ambiguous_role_resolution = "Deny"
+ type = "Rules"
+
+ mapping_rule {
+ claim = "cognito:groups"
+ match_type = "Contains"
+ value = "admin"
+ role_arn = aws_iam_role.cognito_admin_role.arn
+ }
+
+ mapping_rule {
+ claim = "cognito:groups"
+ match_type = "Contains"
+ value = "readonly"
+ role_arn = aws_iam_role.cognito_readonly_role.arn
+ }
+ }
}Set ambiguous_role_resolution = "Deny" always. Never use AuthenticatedRole as the ambiguous fallback in production — it defeats the purpose of role mapping entirely.
Also verify the IAM trust policy on every role includes the amr condition:
{
"Effect": "Allow",
"Principal": { "Federated": "cognito-identity.amazonaws.com" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
- "cognito-identity.amazonaws.com:aud": "<identity-pool-id>"
+ "cognito-identity.amazonaws.com:aud": "${aws_cognito_identity_pool.main.id}"
},
+ "ForAnyValue:StringLike": {
+ "cognito-identity.amazonaws.com:amr": "authenticated"
+ }
}
}💡 Tired of pasting proprietary infrastructure configs into public LLMs? Generic AI interfaces log your company's ARNs, connection strings, and private keys. StackEngine enforces client-side zero-trust boundaries—the sandbox above executes 100% locally in your browser. Drop your broken manifest above to redact secrets locally and synthesize deterministic patch drafts with your own API key.
(For CI/CD pipeline automation, install via
npm i -g stackengine).
▼ 🔍 Continuous Pipeline Governance & CI/CD Guardrails [Click to Expand Deep Dive]
Prevention in CI/CD
1. Checkov — catch missing provider blocks at plan time:
Checkov rule CKV_AWS_212 flags Identity Pools with allow_unauthenticated_identities = true. Add to your pipeline:
checkov -d . --check CKV_AWS_212 --framework terraformWrite a custom check for missing cognito_identity_providers blocks:
# checkov custom check skeleton
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckResult, CheckCategories
class CognitoIdentityPoolHasProvider(BaseResourceCheck):
def __init__(self):
super().__init__(
name="Ensure Cognito Identity Pool has at least one auth provider",
id="CKV_CUSTOM_COGNITO_001",
categories=[CheckCategories.IAM],
supported_resources=["aws_cognito_identity_pool"]
)
def scan_resource_conf(self, conf):
providers = conf.get("cognito_identity_providers", [])
oidc = conf.get("openid_connect_provider_arns", [])
saml = conf.get("saml_provider_arns", [])
if not any([providers, oidc, saml]):
return CheckResult.FAILED
return CheckResult.PASSED2. OPA/Conftest policy for Terraform plan JSON:
package cognito.identity_pool
deny[msg] {
r := input.resource_changes[_]
r.type == "aws_cognito_identity_pool"
r.change.after.allow_unauthenticated_identities == true
msg := sprintf("Identity pool '%v' allows unauthenticated identities — prohibited in production.", [r.name])
}
deny[msg] {
r := input.resource_changes[_]
r.type == "aws_cognito_identity_pool"
count(r.change.after.cognito_identity_providers) == 0
count(r.change.after.openid_connect_provider_arns) == 0
count(r.change.after.saml_provider_arns) == 0
msg := sprintf("Identity pool '%v' has no authentication provider configured.", [r.name])
}3. AWS Config Rule: Enable cognito-identity-pool-no-unauthenticated managed rule. Pair it with an SSM Automation remediation document that sets AllowUnauthenticatedIdentities to false on violation detection.
4. Integration test in your pipeline: After terraform apply in staging, run a canary that calls GetId with a valid test JWT and asserts 200 OK. A missing provider mapping will surface in < 2 seconds before it hits production.
Official Grounding & Normative Specifications
The technical diagnostics, error recovery protocols, and prevention patterns in this specification are grounded in official vendor documentation and standards:
Federal security guidelines for secret exfiltration prevention, automated integrity checks, and peer sign-offs.
Core memory subsystem controls, pressure stall information (PSI), and kernel OOM invocation mechanics.
Industry-standard specification for container execution boundaries and POSIX namespace isolation.