How to Enable JWT Authentication for Amazon Bedrock AgentCore Harness Using Amazon Cognito
Amazon Bedrock AgentCore Harness is a managed way to run a single AI agent in production. You configure the model, instructions, tools, and permissions, and AgentCore runs the agent loop for you. A harness is invoked through the InvokeHarness API, and by default every invocation is authenticated with AWS IAM credentials.
It is important to understand that adding JWT authentication does not replace IAM. The JWT authorizer adds a second way to invoke the harness, for callers who do not have AWS credentials, like application end users. Amazon Cognito acts as the identity provider, it authenticates users and issues JWTs, while the harness validates those tokens before allowing the invocation.
In this post, I will walk through how to enable JWT authentication for a Bedrock AgentCore Harness using Amazon Cognito. We will use the console’s Quick create option to set up the authorizer, review the Cognito resources it provisions, restrict invocation to a Cognito user group, and then invoke the harness with a real JWT. By the end of this guide, you will have a clear picture of how JWT authentication works for harnesses and how to control who can invoke your agents.
Example Use Case: Gating a Support Harness by User Group
To demonstrate JWT authentication, we will use a simple support Q&A harness that answers questions about company policies. The harness will be invoked by support staff from an internal tool. These users do not have AWS credentials, so they will authenticate with Amazon Cognito and call the harness using a JWT. Only members of the support-staff group should be allowed to invoke it.
Create a Harness
Navigate to Amazon Bedrock AgentCore service. Click on the Harness option and choose “Quickly create Harness”. Enter a name such as “companyassist” and create the harness as shown below.
Once the harness is created, open it and edit it to configure the model, instructions, and tools. Select a model available in your region, and enter instructions such as:
You are a concise helper. Answer in plain language, show your work when you compute something, and say so when you don’t know.
Leave memory on its managed default and execution limits at their defaults as those will be covered in later posts of this series.
Configure the JWT Authorizer Using Quick Create
Navigate to the harness, edit it and open the “Inbound Auth” section. Choose “Inbound auth type” as JWT and select Quick create configuration with Cognito (recommended) option as shown below.
Quick create provisions the Cognito resources and wires the authentication for you. Once it finishes, the “Inbound Auth” shows a Discovery URL pointing at a Cognito user pool, with the allowed audience already filled in as shown below. Before changing anything, let us look at what was created.
Review the Cognito Resources Created by Quick Create
Open the Amazon Cognito console. Quick create has provisioned two resources:
- A user pool. This is now the token issuer. The Discovery URL shown on the harness (https://cognito-idp.<region>.amazonaws.com/<user_pool_id>/.well-known/openid-configuration) is how the harness fetches the signing keys used to verify token signatures.
An app client. This represents the application your users authenticate through. Copy the client ID as shown below. This is the same client id which is set up into the harness’s Allowed clients.
Note that Cognito only issues identity here. There is no setting in Cognito that grants permission to invoke the harness — that decision lives in the harness authorizer configuration, which we will tighten next.
Create a Test User and Group
In the user pool, go to user management and create a user named “alice”. Set a password and skip email verification for this test. Then go to Groups and create a group named support-staff, and add Alice to it.
Users created in the console start with a temporary password, which puts the user in a FORCE_CHANGE_PASSWORD state. With a temporary password, the sign-in call returns a NEW_PASSWORD_REQUIRED challenge instead of tokens, so set a permanent password before continuing:
aws cognito-idp admin-set-user-password \
- user-pool-id "<user-pool-id>" \
- username alice \
- password '<choose-a-permanent-password>' \
- permanent \
- region us-east-1Group membership is included in the token as the “cognito:groups” claim. That claim is what the harness will check to decide whether Alice may invoke it.
Add a Group-Based Claim Condition
Return to the harness “Inbound Auth” settings. The JWT authorizer offers four optional gates:
- Allowed audiences — the token’s aud.
- Allowed clients — the token’s client identifier(already set to the app client ID by Quick create).
- Allowed scopes — the token must carry at least one of the listed scopes.
- Customized claims — the token’s claims must match the values you specify.
Under Customized claims, add a condition: claim name “cognito:groups”, String type “String array”, operator “Contains any”, value “support-staff” as shown below.
Obtain a JWT for the Test User
The Cognito console does not display raw tokens, so we obtain one with the AWS CLI. Run these commands in PowerShell. Make sure the AWS CLI is configured with credentials that can call Cognito.
$APP_CLIENT_ID="<app-client-id-from-earlier>"
$ACCESS_TOKEN =$(aws cognito-idp initiate-auth \
- client-id "$APP_CLIENT_ID" \
- auth-flow USER_PASSWORD_AUTH \
- auth-parameters USERNAME=alice,PASSWORD='<password>' \
- query 'AuthenticationResult.AccessToken ' \
- output text - region us-east-1)Get the app client ID from the app client created before, and use the permanent password set for Alice. Run $ACCESS_TOKEN to confirm a token was returned.
Get Shiv Pal Singh Kaundal’s stories in your inbox
Join Medium for free to get updates from this writer.
Note: Request the access token, not the ID token. Quick create configures the Allowed clients, which validates the token’s client_id claim and only access tokens carry that claim.
We can also decode the access token on jwt.io to view its claims, including the client_id, the cognito:groups claim, and the expiration which helps to verify that the token carries everything the authorizer will check.
Invoke the Harness with the JWT
We will invoke the harness from Postman using the access token obtained in the previous step.
Step 1: Build the request
- Open Postman and create a new HTTP request. Set the method to POST and enter the URL and query parameter.
URL: https://bedrock-agentcore.us-east-1.amazonaws.com/harnesses/invoke
Key: harnessArn
Value : your harness ARN (paste it from the harness details page in the console).- Add the Authorization with Bearer token as shown below. To copy your token, type $ACCESS_TOKEN in PowerShell and copy the printed value
- Open the Headers tab and add these headers:
Content-Type: application/json
X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: support-demo-session-00000000000001- Open the Body tab, select raw, choose JSON from the dropdown, and enter:
{
"messages": [
{
"role": "user",
"content": [{"text": "What is our refund policy?"}]
}
]
}Step 2: Send and verify
Click Send. The harness streams the answer back as a sequence of contentBlockDelta events which is the expected streaming format, not an error. Each event carries a small text fragment of the agent’s reply. Assemble the fragments and you get the full answer, which proves Alice’s token passed every gate: issuer, audience, client, and the cognito:groups claim condition.
Step 3: Verify the authorization gates
To confirm each gate does its job, run three invocations:
- Alice’s token succeeds. Valid signature, trusted issuer, matching audience, and the support-staff claim is present.
- Create a user bob without group membership, mint his token the same way, and invoke. The call is rejected at the custom claims gate, even though the issuer and audience are identical.
- A tampered token, or a token from a different user pool will be rejected during signature and issuer validation, before any gate is evaluated.
Conclusion
In this blog, we demonstrated how to enable JWT authentication for an Amazon Bedrock AgentCore Harness using Amazon Cognito. We used Quick create to provision the user pool and app client, reviewed what it wired into the authorizer, restricted invocation to the support-staff group with a claim condition, and invoked the harness with a real Cognito JWT, verifying each authorization gate along the way. This approach lets users without AWS credentials invoke your agents securely, without adding custom authentication logic in front of the harness. Following these steps, you can apply the same pattern to any harness in your AWS environment.









