Skip to content

Function URL with AuthType=NONE: resource policy example is missing lambda:InvokeFunction #494

@monkut

Description

@monkut

Page

https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html — section "Using auth type NONE" / the example resource-based policy.

Issue

The current page shows a single resource-policy statement granting lambda:InvokeFunctionUrl to Principal: "*" as the example for AuthType=NONE Function URLs. In practice this is insufficient — unsigned calls to the Function URL return:

HTTP/1.1 403 Forbidden
x-amzn-ErrorType: AccessDeniedException
{"Message":"Forbidden. For troubleshooting Function URL authorization issues, see: https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html"}

A second statement granting lambda:InvokeFunction to Principal: "*" (no condition) is also required.

Repro

FN=my-test-function

# Following the current docs example exactly:
aws lambda create-function-url-config \
    --function-name $FN --auth-type NONE

aws lambda add-permission \
    --function-name $FN \
    --statement-id FunctionURLAllowPublicAccess \
    --action lambda:InvokeFunctionUrl \
    --principal "*" \
    --function-url-auth-type NONE

# Unsigned GET → 403 AccessDeniedException, no Lambda invocation visible in CloudWatch:
curl -sv "https://<id>.lambda-url.<region>.on.aws/"

The 403 happens at the Function URL authorization layer (no X-Amzn-Trace-Id on the response, no Lambda invocation logged).

Adding the missing statement fixes it immediately:

aws lambda add-permission \
    --function-name $FN \
    --statement-id FunctionURLAllowPublicAccessInvoke \
    --action lambda:InvokeFunction \
    --principal "*"

After that, the same unsigned curl returns HTTP 200 with X-Amzn-Trace-Id headers — the request reaches the Lambda.

Suggested fix

Update the Using auth type NONE example on urls-auth.html to show both statements, e.g.:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "FunctionURLAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:<region>:<account>:function:<function-name>",
      "Condition": {
        "StringEquals": {
          "lambda:FunctionUrlAuthType": "NONE"
        }
      }
    },
    {
      "Sid": "FunctionURLAllowPublicAccessInvoke",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:<region>:<account>:function:<function-name>"
    }
  ]
}

Corroborating evidence

The Zappa project (Python serverless deployment tool) discovered the same requirement and fixed it in zappa/Zappa#1393 (merged 2025-11-04). Their core deploys both statements with Principal: "*" whenever function_url_enabled: true is set with authorizer: NONE. The PR description explicitly references this page as the source of the original (incomplete) example.

Function URLs deployed via Zappa work; Function URLs deployed by hand following the current docs example consistently 403 until the second statement is added. That's a strong signal the docs example is incomplete in practice even if it ever worked at one point.

Environment

  • Region tested: ap-northeast-1
  • Account type: standard (admin role used for setup; unsigned/SigV4 both tested)
  • Affects BUFFERED invoke mode; haven't tested RESPONSE_STREAM.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions