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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions