@@ -614,7 +614,7 @@ Client Agent MCP Server console.red
614614
615615The agent uses **Red Hat SSO** (Keycloak) for authentication via **token
616616introspection** (RFC 7662). Requests to the A2A endpoint (POST /) require a
617- Bearer token that is active and carries the `agent:insights` scope .
617+ Bearer token that is active and carries the `api.console` and `api.ocm` scopes .
618618
619619### Authentication Flow
620620
@@ -637,7 +637,7 @@ Bearer token that is active and carries the `agent:insights` scope.
637637 │ Bearer token │ │ │ │
638638 ├────────────────►│ 4. Introspect │ │ │
639639 │ │ token + check │ │ │
640- │ │ agent : insights │ │ │
640+ │ │ required scopes │ │ │
641641 │ ├───────────────────►│ │ │
642642 │ │ │ │ │
643643 │ │ 5. MCP tool call │ │ │
@@ -666,7 +666,7 @@ Bearer token that is active and carries the `agent:insights` scope.
666666| `redhat-sso-client-secret` | Resource Server client secret |
667667| `MARKETPLACE_HANDLER_URL` | URL of the marketplace-handler service. Used to build the DCR endpoints in the AgentCard. If empty, falls back to `AGENT_PROVIDER_URL`. Set automatically by `deploy.sh`. |
668668| `AGENT_PROVIDER_ORGANIZATION_URL` | Provider's organization website URL (default: `https://www.redhat.com`). Used in AgentCard `provider.url` and as the expected JWT audience for Google DCR `software_statement` validation. Set in YAML configs, not changed by `deploy.sh`. |
669- | `AGENT_REQUIRED_SCOPE` | OAuth scope required in tokens (default: `agent:insights `) |
669+ | `AGENT_REQUIRED_SCOPE` | Comma-separated OAuth scopes required in tokens (default: `api.console,api.ocm `) |
670670
671671### Development Mode
672672
@@ -1096,14 +1096,14 @@ The A2A protocol requires specific fields. A common mistake is omitting
10961096}
10971097```
10981098
1099- ** "Token is missing required scope: agent : insights "**
1099+ ** "Token is missing required scope(s): api.console, api.ocm "**
11001100
1101- The agent requires the ` agent:insights ` scope in the access token by
1102- default. If your Red Hat SSO client is not configured to issue this scope ,
1101+ The agent requires the ` api.console ` and ` api.ocm ` scopes in the access token
1102+ by default. If your Red Hat SSO client is not configured to issue these scopes ,
11031103you will see:
11041104
11051105``` json
1106- {"jsonrpc" :" 2.0" ,"error" :{"code" :-32003 ,"message" :" Forbidden" ,"data" :{"detail" :" Token is missing required scope: agent:insights " }},"id" :null }
1106+ {"jsonrpc" :" 2.0" ,"error" :{"code" :-32003 ,"message" :" Forbidden" ,"data" :{"detail" :" Token is missing required scope(s): api.console, api.ocm " }},"id" :null }
11071107```
11081108
11091109To temporarily disable the scope check for testing, set ` AGENT_REQUIRED_SCOPE `
@@ -1122,7 +1122,7 @@ To restore the scope requirement:
11221122gcloud run services update ${SERVICE_NAME:- lightspeed-agent} \
11231123 --region=$GOOGLE_CLOUD_LOCATION \
11241124 --project=$GOOGLE_CLOUD_PROJECT \
1125- --update-env-vars=" AGENT_REQUIRED_SCOPE=agent:insights "
1125+ --update-env-vars=" AGENT_REQUIRED_SCOPE=api.console,api.ocm "
11261126```
11271127
11281128This setting is also configurable in ` service.yaml ` via the
@@ -1406,13 +1406,13 @@ IAT=$(curl -s -X POST \
14061406echo " Initial Access Token: $IAT "
14071407```
14081408
1409- #### 5. Create the ` agent:insights ` Scope and Resource Server Client
1409+ #### 5. Create the ` api.console ` and ` api.ocm ` Scopes and Resource Server Client
14101410
1411- The agent validates tokens via introspection and checks for the ` agent:insights `
1412- scope. The scope must exist in the realm ** before** DCR creates clients that
1413- reference it .
1411+ The agent validates tokens via introspection and checks for the ` api.console `
1412+ and ` api.ocm ` scopes. The scopes must exist in the realm ** before** DCR
1413+ creates clients that reference them .
14141414
1415- ** Create the ` agent:insights ` client scope :**
1415+ ** Create the ` api.console ` and ` api.ocm ` client scopes :**
14161416
14171417``` bash
14181418# Get a fresh admin token (the one from step 4 expires after 60s)
@@ -1429,23 +1429,33 @@ curl -s -X POST "$KEYCLOAK_URL/admin/realms/test-realm/client-scopes" \
14291429 -H " Authorization: Bearer $ADMIN_TOKEN " \
14301430 -H " Content-Type: application/json" \
14311431 -d ' {
1432- "name": "agent:insights ",
1432+ "name": "api.console ",
14331433 "protocol": "openid-connect",
14341434 "attributes": {"include.in.token.scope": "true"}
14351435 }'
14361436
1437- # Allow agent:insights in the DCR client registration policy.
1437+ # Create the api.ocm scope
1438+ curl -s -X POST " $KEYCLOAK_URL /admin/realms/test-realm/client-scopes" \
1439+ -H " Authorization: Bearer $ADMIN_TOKEN " \
1440+ -H " Content-Type: application/json" \
1441+ -d ' {
1442+ "name": "api.ocm",
1443+ "protocol": "openid-connect",
1444+ "attributes": {"include.in.token.scope": "true"}
1445+ }'
1446+
1447+ # Allow api.console and api.ocm in the DCR client registration policy.
14381448# Keycloak restricts which scopes can be requested during DCR.
14391449# Get the "authenticated" Allowed Client Scopes policy and add
1440- # agent:insights to it.
1450+ # api.console and api.ocm to it.
14411451POLICY=$( curl -s \
14421452 " $KEYCLOAK_URL /admin/realms/test-realm/components?type=org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" \
14431453 -H " Authorization: Bearer $ADMIN_TOKEN " \
14441454 | python3 -c "
14451455import sys, json
14461456for p in json.load(sys.stdin):
14471457 if p.get('providerId') == 'allowed-client-templates' and p.get('subType') == 'authenticated':
1448- p['config']['allowed-client-scopes'] = ['agent:insights ']
1458+ p['config']['allowed-client-scopes'] = ['api.console', 'api.ocm ']
14491459 print(json.dumps(p))
14501460 break
14511461" )
@@ -1487,13 +1497,23 @@ echo "RED_HAT_SSO_CLIENT_ID=lightspeed-agent"
14871497echo " RED_HAT_SSO_CLIENT_SECRET=$CLIENT_SECRET "
14881498```
14891499
1490- ** Assign ` agent:insights ` to the Resource Server client:**
1500+ ** Assign ` api.console ` and ` api.ocm ` to the Resource Server client:**
14911501
14921502``` bash
14931503# Get the scope UUID
14941504SCOPE_UUID=$( curl -s " $KEYCLOAK_URL /admin/realms/test-realm/client-scopes" \
14951505 -H " Authorization: Bearer $ADMIN_TOKEN " \
1496- | python3 -c " import sys,json; print([s['id'] for s in json.load(sys.stdin) if s['name']=='agent:insights'][0])" )
1506+ | python3 -c " import sys,json; print([s['id'] for s in json.load(sys.stdin) if s['name']=='api.console'][0])" )
1507+
1508+ # Add as optional scope to the client
1509+ curl -s -X PUT \
1510+ " $KEYCLOAK_URL /admin/realms/test-realm/clients/$CLIENT_UUID /optional-client-scopes/$SCOPE_UUID " \
1511+ -H " Authorization: Bearer $ADMIN_TOKEN "
1512+
1513+ # Get the api.ocm scope UUID
1514+ SCOPE_UUID=$( curl -s " $KEYCLOAK_URL /admin/realms/test-realm/client-scopes" \
1515+ -H " Authorization: Bearer $ADMIN_TOKEN " \
1516+ | python3 -c " import sys,json; print([s['id'] for s in json.load(sys.stdin) if s['name']=='api.ocm'][0])" )
14971517
14981518# Add as optional scope to the client
14991519curl -s -X PUT \
@@ -1545,8 +1565,8 @@ echo -n "$CLIENT_SECRET" | \
15451565 --data-file=- --project=$GOOGLE_CLOUD_PROJECT
15461566```
15471567
1548- > ** Note:** Keycloak assigns the ` agent:insights ` scope to DCR-created
1549- > clients because the DCR request includes ` "scope": "agent:insights " ` and
1568+ > ** Note:** Keycloak assigns the ` api.console ` and ` api.ocm ` scopes to DCR-created
1569+ > clients because the DCR request includes ` "scope": "api.console api.ocm " ` and
15501570> the scope is in the Allowed Client Scopes registration policy (configured
15511571> above). However, Keycloak does ** not** enable ` serviceAccountsEnabled `
15521572> from the DCR ` grant_types ` field. After DCR, the agent automatically
@@ -1696,7 +1716,7 @@ python scripts/test_a2a_auth.py \
16961716 --message " What systems have critical advisories?"
16971717```
16981718
1699- The script requests ` scope=openid agent:insights ` via ` client_credentials `
1719+ The script requests ` scope=openid api.console api.ocm ` via ` client_credentials `
17001720grant, then sends an A2A ` message/send ` request with the resulting Bearer token.
17011721
17021722To just get a token (e.g. for pasting into the A2A Inspector):
0 commit comments