AWS Builder Center

Developing with an Agentic IDE and Budget Control: An Auth0 IdP Example

Whatever your team builds — internal tools, AI assistants, coding agents, or data pipelines — Amazon Bedrock can support it. But as adoption grows, so does the need to understand and control costs. Who is consuming what? Which team is driving spend? When should an alert fire? Let's continue with cost allocation, this time with a third party Identity provider, Auth0.

This guide teaches you how to set up per-developer cost tracking and budget management on Bedrock using Auth0 as the identity provider. By the end, every API call is tagged with the developer's identity automatically, costs are visible per user in Cost Explorer, and alerts notify individuals when they approach their budget — with no changes to how developers authenticate or work. Read more about cost allocation methods here .

Prerequisites

  • An AWS account with admin access
  • Bedrock model access enabled (at least one Claude model)
  • An Auth0 account (free tier works)
  • Python 3.10+ on the developer machine
  • A browser

Step 1: Create an Auth0 Application

  1. Open your Auth0 Dashboard -> left nav -> Applications -> Applications
  2. Click Create Application
  3. Name: bedrock-cli
  4. Type: Single Page Application
  5. Click Create
  6. Go to the Settings tab of the new application
  7. Verify Token Endpoint Authentication Method is set to None — this is set automatically for SPA but worth confirming
  8. Under Application URIs, set:
    • Allowed Callback URLs: http://localhost:8400/callback
    • Allowed Logout URLs: http://localhost:8400
  9. Scroll to the bottom -> click Show Advanced Settings -> Grant Types tab
    • Ensure Authorization Code is checked
  10. Click Save Changes
  11. Note down the Domain (e.g. your-tenant.auth0.com) and Client ID

Step 2: Create test users and set their metadata

Auth0 supports arbitrary key/value pairs on each user via user_metadata. The
Post-Login Action (Step 4) reads these and injects them as claims into the access
token. This means today you tag by alias, tomorrow you can add team, costcenter,
or any other dimension — just add the key to the user and update the Action.

Create users

  1. Auth0 Dashboard -> left nav -> User Management -> Users
  2. Click Create User
  3. Fill in:
    • Email: jack@yourcompany.com
    • Password: a temporary password
    • Connection: Username-Password-Authentication
  4. Click Create
  5. Repeat for bob@yourcompany.com

Set user metadata

After creating each user:
  1. Click the user -> scroll to Metadata section
  2. Under user_metadata, enter a JSON object with whatever tags you want:
1
2
3
4
{
"alias": "jack",
"team": "AI"
}
  1. Click Save
If alias is not set in user_metadata, the Action falls back to the email
prefix (jack@yourcompany.com -> jack). The team key (or any other key)
only appears as a session tag if you add it to both the user metadata and the
Action code in Step 4.

How tags are derived

user_metadata keySession tagExample value
aliasaliasjack
teamteamplatform
(fallback if alias missing)aliasemail prefix

Step 3: Create an Auth0 API (Resource Server)

AWS validates the aud claim in the JWT. Auth0 only includes aud in access
tokens when a resource server (API) is defined and requested.
  1. Auth0 Dashboard -> left nav -> Applications -> APIs
  2. Click Create API
  3. Fill in:
    • Name: AWS Bedrock
    • Identifier: https://bedrock.aws (this becomes the audience value — any URL works, it does not need to be reachable)
    • Signing Algorithm: RS256
  4. Click Create
  5. Note down the Identifier — you will use it as AUDIENCE in the login script and in the IAM trust policy

Allow user-delegated access

After creation, go to the API's Settings tab -> scroll to Access Settings:
  • User-delegated Access -> select All apps allowed
  • Client Access -> leave as No apps allowed (not needed for browser login)
Click Save.
This controls which applications can request tokens for this API on behalf of
users (Authorization Code flow). Without this, Auth0 returns:
Client is not authorized to access resource server

Step 4: Add a Post-Login Action to inject session tags

Auth0 does not include email in access tokens by default. More importantly, AWS
supports reading session tags directly from the JWT — no second AssumeRole
call needed — if the claims follow the https://aws.amazon.com/tags namespace
format defined by AWS.
There are two supported formats. The nested format is the cleanest for Auth0:
1
2
3
4
5
6
7
"https://aws.amazon.com/tags": {
"principal_tags": {
"alias": ["jack"],
"team": ["AI"]
},
"transitive_tag_keys": ["alias", "team"]
}
The Action sets this structure from user_metadata. Any key you add to
user_metadata automatically becomes a session tag — no changes to the login
script needed.

Create the Action

  1. Auth0 Dashboard -> left nav -> Actions -> Library
  2. Click Build Custom
  3. Fill in:
    • Name: Inject AWS session tags
    • Trigger: Login / Post Login
    • Runtime: Node 18
  4. Click Create
  5. Replace the default code with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
exports.onExecutePostLogin = async (event, api) => {
const meta = event.user.user_metadata || {};

// Keys to forward as AWS session tags.
// Add any key here that exists in user_metadata.
const TAG_KEYS = ['alias', 'team', 'costcenter'];

const principal_tags = {};
const transitive_tag_keys = [];

// Derive alias: prefer explicit metadata key, fall back to email prefix
const alias = meta.alias
|| (event.user.email ? event.user.email.split('@')[0].toLowerCase() : null)
|| event.user.user_id;

if (alias) {
principal_tags['alias'] = [alias];
transitive_tag_keys.push('alias');
}

for (const key of TAG_KEYS) {
if (key !== 'alias' && meta[key]) {
principal_tags[key] = [meta[key]];
transitive_tag_keys.push(key);
}
}

api.accessToken.setCustomClaim('https://aws.amazon.com/tags', {
principal_tags,
transitive_tag_keys,
});
};
  1. Click Deploy
  2. Go to Actions -> Flows -> Login
  3. Drag Inject AWS session tags into the flow between Start and Complete
  4. Click Apply
To add a new tag tomorrow (e.g. department): add 'department' to TAG_KEYS,
set "department": "engineering" in the user's user_metadata, and redeploy
the Action. No changes to the login script or IAM role needed.
Auth0 requires custom claims to be namespaced with a URI. The
https://aws.amazon.com/tags namespace is the exact URI AWS expects for
session tags passed via AssumeRoleWithWebIdentity. Using any other namespace
(or no namespace) will cause AWS to ignore the tags.

Step 5: Register Auth0 as an IAM OIDC Provider

Unlike Cognito + Identity Pool (which registers the provider automatically), with
Auth0 you register it manually. This is a one-time account-level step.
  1. Open the AWS Console -> IAM -> left nav -> Identity providers
  2. Click Add provider
  3. Configure:
    • Provider type: OpenID Connect
    • Provider URL: https://your-tenant.auth0.com/ (include the trailing slash — Auth0 JWTs use it as the issuer)
    • Audience: your Auth0 Client ID (e.g. JvpNuUkyHb1SlPjUfINSqiun0f5PZPo6) — NOT the API identifier
  4. Click Get thumbprint — AWS fetches the TLS certificate fingerprint automatically
  5. Click Add provider
  6. Note down the Provider ARN (format: arn:aws:iam::<ACCOUNT_ID>:oidc-provider/your-tenant.auth0.com/)
Why the Client ID and not the API identifier? The script uses the id_token
for AssumeRoleWithWebIdentity. The id_token has aud = CLIENT_ID (a single
value). The access_token has multiple aud values including /userinfo,
which AWS rejects. AWS validates that the token's aud matches a registered
client ID in the OIDC provider.

Step 6: Create the IAM Role

6a. Create the role

  1. IAM -> Roles -> Create role
  2. Trusted entity type: Web identity
  3. Identity provider: select the Auth0 provider you just created
  4. Audience: your Client ID (same value used when registering the OIDC provider)
  5. Click Next
  6. Attach AmazonBedrockFullAccess (scope down in production)
  7. Click Next
  8. Role name: BedrockAuth0Role
  9. Click Create role

6b. Edit the trust policy

The condition key must use the provider URL (with trailing slash) and the audience
must be the Client ID — not the API identifier. The id_token has aud = CLIENT_ID
(single value), which is what AWS validates:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/your-tenant.auth0.com/"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"your-tenant.auth0.com/:aud": "<CLIENT_ID>"
}
}
}
]
}
Replace <ACCOUNT_ID>, your-tenant.auth0.com, and <CLIENT_ID> with your values.
The condition key is your-tenant.auth0.com/:aud — the trailing slash before
:aud must match the OIDC provider URL exactly.Do not use the API identifier (https://bedrock.aws) here. The access_token
has multiple aud values including /userinfo which AWS rejects. The
id_token has only aud = CLIENT_ID — a single value AWS accepts.

6c. No inline policy needed

Unlike the Cognito guide, there is no AllowSelfAssume inline policy required.
The role is ready after Steps 6a and 6b.

Step 7: Activate the cost allocation tag

  1. Open the AWS Console -> Billing and Cost Management -> left nav -> Cost allocation tags
  2. Click the AWS-generated cost allocation tags tab
  3. Search for aws:PrincipalTag/alias
    • If it does not appear yet, come back after Step 10 (first tagged call populates it)
  4. Select it -> click Activate
Note: It takes up to 24 hours for a newly activated tag to appear in Cost Explorer. CloudTrail shows the tags immediately.

Step 8: Developer login script

Save the following as ~/.aws/bedrock-login-auth0.py on the developer's machine and fill in the CONFIG section — that is the only change needed.
To delete cached credentials and re-login:
rm ~/.aws/.oidc_token_cache_auth0.json ~/.aws/.bedrock_creds_cache_auth0.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
"""
bedrock-login-auth0.py - Auth0 OIDC -> AWS credentials with session tags from JWT.
Called automatically by AWS credential_process.

Save as: ~/.aws/bedrock-login-auth0.py

Add to ~/.aws/config:
[profile bedrock-auth0]
credential_process = /bin/sh -c 'python3 $HOME/.aws/bedrock-login-auth0.py'
region = us-east-1

Session tags (alias, team, etc.) are injected directly into the JWT by the
Auth0 Post-Login Action using the https://aws.amazon.com/tags namespace.
AssumeRoleWithWebIdentity reads them from the id_token automatically.

Why id_token and not access_token?
Auth0 access tokens have multiple aud values (API identifier + /userinfo).
AWS rejects tokens with multiple audiences. The id_token has aud = CLIENT_ID only.
"""


import json, base64, re, sys, os, subprocess, hashlib
from urllib.parse import urlencode, urlparse, parse_qs
from http.server import HTTPServer, BaseHTTPRequestHandler

# -- Auto-install dependencies -------------------------------------------------
DEPS_DIR = os.path.expanduser("~/.aws/.bedrock_deps")

def ensure_deps():
sys.path.insert(0, DEPS_DIR)
try:
import boto3 # noqa: F401
import requests # noqa: F401
except ImportError:
print("First run: installing dependencies...", file=sys.stderr)
subprocess.check_call(
[sys.executable, "-m", "pip", "install", "--target", DEPS_DIR, "boto3", "requests"],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)

ensure_deps()

import boto3 # noqa: E402
import requests as req # noqa: E402

# ============ CONFIGURATION — fill in your values ============
AUTH0_DOMAIN = "your-tenant.auth0.com" # e.g. dev-abc123.us.auth0.com
CLIENT_ID = "<CLIENT_ID>" # Auth0 Application Client ID
AUDIENCE = "https://bedrock.aws" # Auth0 API Identifier (Step 3)
ROLE_ARN = "arn:aws:iam::<ACCOUNT_ID>:role/BedrockAuth0Role"
REGION = "us-east-1"
# =============================================================

REDIRECT_URI = "http://localhost:8400/callback"
SCOPES = ["openid", "email", "profile"]
TOKEN_CACHE = os.path.expanduser("~/.aws/.oidc_token_cache_auth0.json")
AWS_CREDS_CACHE = os.path.expanduser("~/.aws/.bedrock_creds_cache_auth0.json")

# -- Helpers -------------------------------------------------------------------
def decode_jwt(token):
payload = token.split(".")[1]
payload += "=" * (4 - len(payload) % 4)
return json.loads(base64.b64decode(payload))

def extract_session_name(claims):
"""Derive RoleSessionName from alias tag in JWT, fall back to email prefix."""
tags = claims.get("https://aws.amazon.com/tags", {})
principal_tags = tags.get("principal_tags", {})
alias = principal_tags.get("alias", [None])[0]
if not alias:
email = claims.get("email", "")
alias = email.split("@")[0].lower() if "@" in email else claims.get("sub", "unknown").split("|")[-1][:20]
return f"alias-{re.sub(r'[^a-zA-Z0-9=,.@_-]', '-', alias)[:58]}"

# -- Check cached AWS credentials first ----------------------------------------
def try_cached_creds():
if not os.path.exists(AWS_CREDS_CACHE):
return
try:
with open(AWS_CREDS_CACHE) as f:
cached = json.load(f)
from datetime import datetime, timezone
exp = datetime.strptime(cached["Expiration"], "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc)
if (exp - datetime.now(timezone.utc)).total_seconds() > 300:
print(json.dumps(cached))
sys.exit(0)
except (json.JSONDecodeError, KeyError, ValueError):
pass

try_cached_creds()

# -- Token cache ---------------------------------------------------------------
def load_token_cache():
if not os.path.exists(TOKEN_CACHE):
return None
try:
with open(TOKEN_CACHE) as f:
return json.load(f)
except (json.JSONDecodeError, ValueError):
return None

def save_token_cache(data):
os.makedirs(os.path.dirname(TOKEN_CACHE), exist_ok=True)
with open(TOKEN_CACHE, "w") as f:
json.dump(data, f)

def try_refresh_token(cached):
refresh_token = cached.get("refresh_token")
if not refresh_token:
return None
resp = req.post(f"https://{AUTH0_DOMAIN}/oauth/token", json={
"grant_type": "refresh_token",
"client_id": CLIENT_ID,
"refresh_token": refresh_token,
}, timeout=10)
if resp.status_code != 200:
return None
token_data = resp.json()
if "access_token" not in token_data:
return None
token_data.setdefault("refresh_token", refresh_token)
save_token_cache(token_data)
return token_data

def do_authorization_code_flow():
code_verifier = base64.urlsafe_b64encode(os.urandom(32)).rstrip(b"=").decode()
code_challenge = base64.urlsafe_b64encode(
hashlib.sha256(code_verifier.encode()).digest()
).rstrip(b"=").decode()
state = base64.urlsafe_b64encode(os.urandom(16)).rstrip(b"=").decode()

auth_url = f"https://{AUTH0_DOMAIN}/authorize?" + urlencode({
"client_id": CLIENT_ID,
"response_type": "code",
"redirect_uri": REDIRECT_URI,
"scope": " ".join(SCOPES),
"audience": AUDIENCE,
"state": state,
"code_challenge": code_challenge,
"code_challenge_method": "S256",
})

auth_code = [None]
auth_error = [None]

class CallbackHandler(BaseHTTPRequestHandler):
def do_GET(self):
qs = parse_qs(urlparse(self.path).query)
if qs.get("state", [None])[0] != state:
auth_error[0] = "State mismatch"
elif "error" in qs:
auth_error[0] = qs.get("error_description", qs["error"])[0]
elif "code" in qs:
auth_code[0] = qs["code"][0]
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.end_headers()
msg = b"<h2>Login successful. You can close this window.</h2>" \
if auth_code[0] else f"<h2>Login failed: {auth_error[0]}</h2>".encode()
self.wfile.write(msg)

def log_message(self, *args):
pass

server = HTTPServer(("localhost", 8400), CallbackHandler)
import webbrowser
webbrowser.open(auth_url)
server.timeout = 120
while auth_code[0] is None and auth_error[0] is None:
server.handle_request()
server.server_close()

if auth_error[0]:
print(f"Login error: {auth_error[0]}", file=sys.stderr)
sys.exit(1)
if not auth_code[0]:
print("Login timed out", file=sys.stderr)
sys.exit(1)

resp = req.post(f"https://{AUTH0_DOMAIN}/oauth/token", json={
"grant_type": "authorization_code",
"client_id": CLIENT_ID,
"code": auth_code[0],
"redirect_uri": REDIRECT_URI,
"code_verifier": code_verifier,
}, timeout=10)

if resp.status_code != 200:
print(f"Token exchange failed: {resp.text}", file=sys.stderr)
sys.exit(1)

token_data = resp.json()
if "access_token" not in token_data:
print(f"No access_token in response: {resp.text}", file=sys.stderr)
sys.exit(1)

save_token_cache(token_data)
return token_data

# -- Main flow -----------------------------------------------------------------
token_data = None
cached = load_token_cache()
if cached:
token_data = try_refresh_token(cached)

if not token_data:
token_data = do_authorization_code_flow()

# Use id_token for AssumeRoleWithWebIdentity.
# The access_token has multiple aud values (API + /userinfo) which AWS rejects.
# The id_token has aud = CLIENT_ID only — a single value AWS accepts.
# Session tags in the access_token's https://aws.amazon.com/tags claim are still
# read by AWS from the id_token because the Action sets them on the access_token
# and AWS reads principal_tags from whichever token is presented.
web_identity_token = token_data.get("id_token") or token_data["access_token"]
claims = decode_jwt(web_identity_token)
session_name = extract_session_name(claims)

# -- AssumeRoleWithWebIdentity — tags come from the JWT automatically ----------
sts = boto3.client("sts", region_name=REGION)
response = sts.assume_role_with_web_identity(
RoleArn=ROLE_ARN,
RoleSessionName=session_name,
WebIdentityToken=web_identity_token,
DurationSeconds=3600,
)
creds = response["Credentials"]

# -- Output and cache ----------------------------------------------------------
output = {
"Version": 1,
"AccessKeyId": creds["AccessKeyId"],
"SecretAccessKey": creds["SecretAccessKey"],
"SessionToken": creds["SessionToken"],
"Expiration": creds["Expiration"].strftime("%Y-%m-%dT%H:%M:%SZ"),
}

with open(AWS_CREDS_CACHE, "w") as f:
json.dump(output, f)

print(json.dumps(output))

Step 9: Configure the AWS profile and test

Add to ~/.aws/config:
1
2
3
[profile bedrock-auth0]
credential_process = /bin/sh -c 'python3 $HOME/.aws/bedrock-login-auth0.py'
region = us-east-1
Test authentication:
1
aws sts get-caller-identity --profile bedrock-auth0
Expected output:
1
2
3
4
5
{
"UserId": "AROAXXXXXXXXXXXX:alias-jack",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/BedrockAuth0Role/alias-jack"
}

Step 10: Make a Bedrock call

1
2
3
4
5
6
aws bedrock-runtime invoke-model \
--model-id us.anthropic.claude-sonnet-4-6 \
--body '{"anthropic_version":"bedrock-2023-05-31","max_tokens":50,"messages":[{"role":"user","content":"Say hello"}]}' \
--cli-binary-format raw-in-base64-out \
--profile bedrock-auth0 \
/tmp/out.json && cat /tmp/out.json

Step 11: Verify in CloudTrail (immediate)

1
2
3
4
5
6
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=Username,AttributeValue=alias-jack \
--region us-east-1 \
--max-results 10 \
--query 'Events[*].{Event:EventName,Time:EventTime,User:Username}' \
--output table
Expected output:
1
2
3
4
5
6
+--------------------+-----------------------------+--------------+
| Event | Time | User |
+--------------------+-----------------------------+--------------+
| InvokeModel | 2026-05-31T10:22:14+00:00 | alias-jack |
| GetCallerIdentity | 2026-05-31T10:20:03+00:00 | alias-jack |
+--------------------+-----------------------------+--------------+
To verify the tag is attached, look at the AssumeRole event:
1
2
3
4
5
6
7
8
9
10
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
--max-results 1 --region us-east-1 \
--query 'Events[0].CloudTrailEvent' --output text \
| python3 -c "
import sys, json
e = json.load(sys.stdin)
print('Session:', e['requestParameters'].get('roleSessionName'))
print('Tags:', json.dumps(e['requestParameters'].get('tags', []), indent=2))
"

Step 12: Verify in Cost Explorer (after 24h)

  1. Billing and Cost Management -> Cost Explorer -> Launch Cost Explorer
  2. Filter by Service: Amazon Bedrock
  3. Group by: Tag -> select alias

Step 13: Set per-developer budget alerts (optional)

  1. Billing and Cost Management -> Budgets -> Create budget
  2. Select Customize (advanced) -> Cost budget -> Next
  3. Fill in:
    • Budget name: jack-daily-bedrock
    • Period: Daily
    • Budgeted amount: e.g. $5
  4. Under Filters -> Add filter:
    • Filter dimension: Tag, key: alias, value: jack
    • Add second filter: Service = Amazon Bedrock
  5. Add alert threshold: Actual, 80%, email: jack@yourcompany.com
  6. Create budget

Summary

WhatWhereLatency
API call with user identityCloudTrail Event History5-15 minutes
Session tags on AssumeRoleCloudTrail Event History5-15 minutes
Per-user cost breakdownCost Explorer24 hours after tag activation

How this differs from the Cognito guide

Cognito (Part 1)Auth0 (Part 3)
Identity PoolRequiredNot needed
IAM OIDC providerAuto-created by Identity Pool wizardManual registration (Step 5)
Session tags in JWTNot supported nativelyhttps://aws.amazon.com/tags nested claim
Second AssumeRole callRequired (to attach tags)Not needed (tags come from JWT)
Trust policy self-assumeRequiredNot required
Token usedid_tokenid_token (access_token has multiple aud values AWS rejects)
Role path/service-role/BedrockCognitoRole/BedrockAuth0Role
Trust policy principalcognito-identity.amazonaws.comAuth0 OIDC provider ARN
Adding a new tag dimensionChange login scriptAdd key to Action's TAG_KEYS + user metadata

Troubleshooting

ErrorCauseFix
InvalidIdentityToken: No OpenIDConnect provider foundOIDC provider not registered or URL missing trailing slashStep 5: provider URL must be https://your-tenant.auth0.com/ — Auth0 JWTs include a trailing slash in the iss claim
InvalidIdentityToken: Incorrect token audienceUsing access_token (multiple aud values) or wrong condition keyScript uses id_token which has single aud = CLIENT_ID; trust policy condition must be your-tenant.auth0.com/:aud = <CLIENT_ID>
AccessDenied on AssumeRoleWithWebIdentityTrust policy condition mismatchCheck your-tenant.auth0.com:aud in the trust policy matches your API Identifier
Session tags missing in CloudTrailhttps://aws.amazon.com/tags claim not in JWTStep 4: verify the Action is deployed AND added to the Login flow; decode the access token at jwt.io to confirm the claim is present
alias is a random string in CloudTrailalias key missing from user_metadataStep 2: set "alias": "jack" in the user's metadata; the Action falls back to email prefix if missing
Tags not appearing in Cost ExplorerCost allocation tag not activatedStep 7: activate aws:PrincipalTag/alias in Billing -> Cost allocation tags
401 access_denied on token exchangeApp type is not SPA — token endpoint auth method is not NoneAuth0 app Settings -> Application Type must be Single Page Application; Token Endpoint Authentication Method must be None
Token exchange returns opaque token instead of JWTaudience param missing from auth URLThe script must pass "audience": AUDIENCE in the authorization URL — without it Auth0 returns an opaque token

References

Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article