|
| 1 | +tags:: [[Diataxis/How To]], [[Claude Code]], [[AWS/Bedrock]] |
| 2 | +alias:: [[Anthropic/App/Claude Code/Bedrock/How To/Get Around Security Token Timeout]] |
| 3 | + |
| 4 | +- # How To Handle Security Token Expiration Errors with Claude Code and AWS Bedrock |
| 5 | + - ## Problem |
| 6 | + - When using [[Claude Code]] with [[AWS/Bedrock]], you may encounter the error: |
| 7 | + - ``` |
| 8 | + API Error: The security token included in the request is expired |
| 9 | + ``` |
| 10 | + - This occurs when AWS credentials (STS tokens, SSO sessions, etc.) have expired and Claude Code needs to refresh them. |
| 11 | + - ## Expected Behavior |
| 12 | + - According to the [official documentation](https://code.claude.com/docs/en/amazon-bedrock), Claude Code should automatically detect expired credentials and run your configured `awsAuthRefresh` command before retrying the request. |
| 13 | + - Detection happens in two ways: |
| 14 | + - **Local detection**: Based on credential timestamp in `~/.aws/credentials` or SSO cache |
| 15 | + - **Remote detection**: When Bedrock returns a credential error (like the expired token error) |
| 16 | + - ## Configuration |
| 17 | + - ### Basic Setup |
| 18 | + - Add `awsAuthRefresh` to your Claude Code settings file (`~/.claude/settings.json`): |
| 19 | + - ```json |
| 20 | + { |
| 21 | + "awsAuthRefresh": "aws sso login --profile myprofile", |
| 22 | + "env": { |
| 23 | + "AWS_PROFILE": "myprofile", |
| 24 | + } |
| 25 | + } |
| 26 | + ``` |
| 27 | + - ### Command Types |
| 28 | + - **`awsAuthRefresh`**: For commands that modify the `.aws` directory (credentials, SSO cache, config files) |
| 29 | + - Output is shown to the user |
| 30 | + - User input is NOT supported (see [GitHub Issue #11264](https://github.com/anthropics/claude-code/issues/11264) for feature request to support interactive authentication) |
| 31 | + - Suitable for browser-based authentication flows |
| 32 | + - **Limitation**: Interactive authentication tools (like `gimme-aws-creds` with password/MFA prompts) cannot be used with `awsAuthRefresh` currently |
| 33 | + - **`awsCredentialExport`**: For commands that output credentials directly as JSON |
| 34 | + - Output is captured silently (not shown) |
| 35 | + - Must output JSON in this format: |
| 36 | + - ```json |
| 37 | + { |
| 38 | + "Credentials": { |
| 39 | + "AccessKeyId": "value", |
| 40 | + "SecretAccessKey": "value", |
| 41 | + "SessionToken": "value" |
| 42 | + } |
| 43 | + } |
| 44 | + ``` |
| 45 | + - **Example Commands**: |
| 46 | + - **Using AWS STS assume-role with jq** (most common): |
| 47 | + - ```json |
| 48 | + "awsCredentialExport": "aws sts assume-role --role-arn arn:aws:iam::123456789012:role/MyRole --role-session-name mysession | jq '{Credentials: .Credentials | {AccessKeyId, SecretAccessKey, SessionToken}}'" |
| 49 | + ``` |
| 50 | + - Reference: [AWS CLI Command Reference: assume-role](https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role.html) |
| 51 | + - **Using AWS STS get-session-token with jq**: |
| 52 | + - ```json |
| 53 | + "awsCredentialExport": "aws sts get-session-token | jq '{Credentials: .Credentials | {AccessKeyId, SecretAccessKey, SessionToken}}'" |
| 54 | + ``` |
| 55 | + - Reference: [AWS CLI Command Reference: get-session-token](https://docs.aws.amazon.com/cli/latest/reference/sts/get-session-token.html) |
| 56 | + - **Using a custom script**: |
| 57 | + - ```json |
| 58 | + "awsCredentialExport": "/path/to/generate_aws_grant.sh" |
| 59 | + ``` |
| 60 | + - The script should output the JSON format shown above to stdout |
| 61 | + - Reference: [Claude Code Settings Documentation](https://code.claude.com/docs/en/settings) - See `awsCredentialExport` setting |
| 62 | + - **Using AWS CLI export-credentials** (if your AWS CLI version supports it): |
| 63 | + - ```json |
| 64 | + "awsCredentialExport": "aws configure export-credentials --profile myprofile --format json | jq '{Credentials: {AccessKeyId: .AccessKeyId, SecretAccessKey: .SecretAccessKey, SessionToken: .SessionToken}}'" |
| 65 | + ``` |
| 66 | + - Reference: [AWS CLI Command Reference: configure export-credentials](https://docs.aws.amazon.com/cli/latest/reference/configure/export-credentials.html) |
| 67 | + - **Using a wrapper script with environment variables**: |
| 68 | + - ```json |
| 69 | + "awsCredentialExport": "bash -c 'aws sts assume-role --role-arn $AWS_ROLE_ARN --role-session-name $SESSION_NAME | jq \"{Credentials: .Credentials | {AccessKeyId, SecretAccessKey, SessionToken}}\"'" |
| 70 | + ``` |
| 71 | + - References: |
| 72 | + - [AWS CLI Command Reference: assume-role](https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role.html) |
| 73 | + - [jq Manual](https://stedolan.github.io/jq/manual/) - For [[jq]] filter syntax |
| 74 | + - **Important Notes**: |
| 75 | + - The command must output **only** valid JSON to stdout (no error messages or other output) |
| 76 | + - Use `jq` to filter AWS STS output, as it includes additional fields (`Expiration`, `AssumedRoleUser`, etc.) that Claude Code doesn't need |
| 77 | + - Ensure `jq` is available in Claude Code's PATH if your command uses it |
| 78 | + - For commands with pipes, you may need to wrap them in `bash -c` or `sh -c` |
| 79 | + - Test your command manually first to ensure it outputs the correct JSON format |
| 80 | + - ## Troubleshooting: When Automatic Refresh Doesn't Work |
| 81 | + - ### Issue: Command Not Triggering |
| 82 | + - If you see the expired token error but no indication that `awsAuthRefresh` ran: |
| 83 | + - **Check command path**: Ensure your command is in your PATH when Claude Code runs |
| 84 | + - Claude Code may not have access to the same PATH as your shell |
| 85 | + - Try using the full path: `"/usr/local/bin/aws sso login --profile myprofile"` |
| 86 | + - **Check command syntax**: Verify the command works when run manually |
| 87 | + - ```bash |
| 88 | + aws sso login --profile myprofile |
| 89 | + ``` |
| 90 | + - **Check permissions**: Ensure Claude Code has permission to execute the command |
| 91 | + - Check your `permissions` settings in `settings.json` |
| 92 | + - May need to add: `"Bash(aws:*)"` to allowed commands |
| 93 | + - **Workaround**: Manually refresh credentials before using Claude Code |
| 94 | + - ```bash |
| 95 | + aws sso login --profile myprofile |
| 96 | + ``` |
| 97 | + - Then retry your Claude Code request |
| 98 | + - ### Issue: Credentials Refreshed But Not Used (Known Bug) |
| 99 | + - **Symptom**: `awsAuthRefresh` runs successfully and credentials are updated in `~/.aws/credentials`, but Claude Code still fails with expired token errors |
| 100 | + - **Cause**: This is a [known bug in Claude Code](https://github.com/anthropics/claude-code/issues/3823) where the refreshed credentials aren't always picked up after `awsAuthRefresh` completes |
| 101 | + - **Workaround**: Exit and resume Claude Code to force it to reload credentials |
| 102 | + - Exit Claude Code: `Ctrl+C` or `exit` |
| 103 | + - Resume with: `claude -r` (resume last session) |
| 104 | + - This forces Claude Code to reload credentials from `~/.aws/credentials` |
| 105 | + - **Alternative Workaround**: Use `awsCredentialExport` instead of `awsAuthRefresh` |
| 106 | + - `awsCredentialExport` directly provides credentials to Claude Code, bypassing the credential file reload issue |
| 107 | + - See the `awsCredentialExport` examples above |
| 108 | + - **Note**: The issue tracker includes a request for a `/refresh-credential` command to manually trigger credential reload without exiting |
| 109 | + - ### Issue: Command Not Found |
| 110 | + - If your refresh command isn't available in Claude Code's environment: |
| 111 | + - **Option 1**: Use full path to the command |
| 112 | + - Find command location: `which aws` or `command -v aws` |
| 113 | + - Use full path in `awsAuthRefresh`: `"/usr/local/bin/aws sso login --profile myprofile"` |
| 114 | + - **Option 2**: Use direct script path |
| 115 | + - If you have a custom refresh script, reference it directly: |
| 116 | + - ```json |
| 117 | + "awsAuthRefresh": "/path/to/refresh_credentials.sh" |
| 118 | + ``` |
| 119 | + - **Option 3**: Use `awsCredentialExport` with a wrapper script |
| 120 | + - Create a script that outputs credentials in the required JSON format |
| 121 | + - See examples in the `awsCredentialExport` section above |
| 122 | + - ### Issue: Interactive Commands |
| 123 | + - If your refresh command requires user interaction (like password entry, MFA approval, Touch ID): |
| 124 | + - Claude Code's `awsAuthRefresh` shows output but doesn't support user input |
| 125 | + - This may cause the command to hang or fail |
| 126 | + - **Current Workaround**: Use `awsCredentialExport` instead, or ensure your command can run non-interactively |
| 127 | + - **Future Enhancement**: [GitHub Issue #11264](https://github.com/anthropics/claude-code/issues/11264) requests support for interactive `awsAuthRefresh` to enable enterprise authentication flows (gimme-aws-creds, saml2aws, etc.) |
| 128 | + - **Alternative**: For now, manually refresh credentials in a separate terminal before using Claude Code |
| 129 | + - ### Issue: Environment Variables Not Available |
| 130 | + - If your refresh command needs specific environment variables: |
| 131 | + - Add them to the `env` section of your settings.json |
| 132 | + - Example: |
| 133 | + - ```json |
| 134 | + { |
| 135 | + "awsAuthRefresh": "aws sso login --profile myprofile", |
| 136 | + "env": { |
| 137 | + "AWS_PROFILE": "myprofile", |
| 138 | + "OP_SESSION_myorg": "your-session-token", |
| 139 | + "PATH": "/custom/path:$PATH" |
| 140 | + } |
| 141 | + } |
| 142 | + ``` |
| 143 | + - ## Manual Refresh Workflow |
| 144 | + - When automatic refresh fails, use this workflow: |
| 145 | + 1. **Check current credentials**: |
| 146 | + - ```bash |
| 147 | + aws sts get-caller-identity --profile myprofile |
| 148 | + ``` |
| 149 | + 2. **Refresh credentials**: |
| 150 | + - ```bash |
| 151 | + aws sso login --profile myprofile |
| 152 | + ``` |
| 153 | + 3. **Verify new credentials**: |
| 154 | + - ```bash |
| 155 | + aws sts get-caller-identity --profile myprofile |
| 156 | + ``` |
| 157 | + 4. **Retry Claude Code request** |
| 158 | + - ## Related Pages |
| 159 | + - [[Claude Code/Bedrock]] - Main Bedrock integration guide |
| 160 | + - [[mise/Task/How To/invoke aws_okta_keyman from mise with a configuration that references a default AWS account]] - Example of setting up credential refresh scripts |
| 161 | + - [[Claude Code/Settings]] - Claude Code settings documentation |
| 162 | + - ## References |
| 163 | + - [Claude Code on Amazon Bedrock - Advanced Credential Configuration](https://code.claude.com/docs/en/amazon-bedrock#advanced-credential-configuration) |
| 164 | + - [Claude Code Settings Documentation](https://code.claude.com/docs/en/settings) |
| 165 | + - [GitHub Issue #3823: CC not taking the updated credentials with awsAuthRefresh](https://github.com/anthropics/claude-code/issues/3823) - Known bug where refreshed credentials aren't always used |
| 166 | + - [GitHub Issue #11264: Interactive awsAuthRefresh](https://github.com/anthropics/claude-code/issues/11264) - Feature request to support interactive authentication flows (password/MFA prompts) within Claude Code |
0 commit comments