A2A SecurityScheme: Declaring How Clients Authenticate
An A2A Agent Card does not authenticate anything by itself. It declares how: securitySchemes defines named authentication methods, and securityRequirements says which of them a client must satisfy. The client reads both from the Agent Card
, obtains credentials out-of-band, and sends them with every request. The server MUST authenticate every incoming request.
This page covers the objects. For the runtime rules, such as authorization scoping and in-task authorization, read Authentication, Authorization, and Security Considerations .
Three fields, three jobs
| Where | Field | Type | Job |
|---|---|---|---|
| Agent Card | securitySchemes | map of name to SecurityScheme | Define the methods you accept, under names you choose |
| Agent Card | securityRequirements | list of SecurityRequirement | State which defined schemes, and scopes, a client must satisfy |
AgentSkill | securityRequirements | list of SecurityRequirement | The same, for one skill (see AgentSkill ) |
A SecurityRequirement has one field, schemes: a map from a scheme name to { "list": [...] }, the list of required scopes. This is the specification’s sample card, which defines an OpenID Connect scheme named google and requires it with three scopes:
"securitySchemes": {
"google": {
"openIdConnectSecurityScheme": {
"openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration"
}
}
},
"securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }]The specification does not say how several entries in securityRequirements combine, so do not assume AND or OR semantics from the structure alone.
The five scheme types
SecurityScheme is a discriminated union (a protobuf oneof) based on the OpenAPI 3.2 Security Scheme Object. Each entry in securitySchemes sets exactly one of these keys:
| JSON key | Required fields | Optional fields |
|---|---|---|
apiKeySecurityScheme | location (query, header, or cookie) and name (the parameter’s name) | description |
httpAuthSecurityScheme | scheme (an RFC 7235 scheme name such as Bearer, which should be in the IANA registry) | bearerFormat (for example JWT, documentation only) and description |
oauth2SecurityScheme | flows | oauth2MetadataUrl (RFC 8414 authorization server metadata, TLS required) and description |
openIdConnectSecurityScheme | openIdConnectUrl (the OpenID Connect Discovery URL) | description |
mtlsSecurityScheme | none | description |
The specification gives a JSON example only for OpenID Connect. The next snippet is illustrative: it is built from the proto field names in the table, not copied from the official documents, and shows an HTTP Bearer scheme.
"securitySchemes": {
"bearerAuth": {
"httpAuthSecurityScheme": { "scheme": "Bearer", "bearerFormat": "JWT" }
}
},
"securityRequirements": [{ "schemes": { "bearerAuth": { "list": [] } } }]OAuth 2.0 flows
OAuthFlows is also a oneof: an oauth2SecurityScheme sets one flow under flows. In the v1.0.1 proto:
| JSON key | Required fields | Optional fields | Status |
|---|---|---|---|
authorizationCode | authorizationUrl, tokenUrl, scopes | refreshUrl, pkceRequired | Current |
clientCredentials | tokenUrl, scopes | refreshUrl | Current |
deviceCode | deviceAuthorizationUrl, tokenUrl, scopes | refreshUrl | Current; for CLI tools and input-constrained devices (RFC 8628) |
implicit | none marked | authorizationUrl, refreshUrl, scopes | Deprecated: “Use Authorization Code + PKCE instead” |
password | none marked | tokenUrl, refreshUrl, scopes | Deprecated: “Use Authorization Code + PKCE or Device Code” |
scopes maps a scope name to a short description. pkceRequired says whether PKCE (RFC 7636) is mandatory for the flow; the proto adds that PKCE should always be used for public clients and is recommended for all clients.
This second illustrative snippet declares an Authorization Code flow with PKCE required. The URLs are placeholders, and the scope is the one the migration guide uses in its own example.
"securitySchemes": {
"oauth": {
"oauth2SecurityScheme": {
"flows": {
"authorizationCode": {
"authorizationUrl": "https://auth.example.com/authorize",
"tokenUrl": "https://auth.example.com/token",
"pkceRequired": true,
"scopes": { "read": "Read access" }
}
}
}
}
},
"securityRequirements": [{ "schemes": { "oauth": { "list": ["read"] } } }]Three pitfalls in the official material
An old sample is still around. The copy of the sample card in the v1.0.1 tag of the specification wrote the requirement in the v0.3 shape, "security": [{ "google": ["openid", "profile", "email"] }]. The official repository corrected it after the release (pull request #2046, July 2026), and the shape used on this page is the one a2a.proto defines for v1.0. If you copy a card from an older copy of the specification, check this field first.
JSON keys follow the proto field names. The specification requires camelCase JSON names derived from the proto field names (section 5.5). The OAuth example in the v1.0 migration guide writes authorizationCodeFlow and implicitFlow, but the proto fields are authorization_code and implicit, so the keys are authorizationCode and implicit, as in the tables above. When the sources disagree, the specification names the proto as “the single authoritative normative definition” (section 1.4).
“Removed” flows are still in the proto. The migration guide lists ImplicitOAuthFlow and PasswordOAuthFlow as removed. The v1.0.0 and v1.0.1 protos still declare them as members 3 and 4 of OAuthFlows, marked deprecated, and section 4.5 of the specification documents only the three current flows. Do not declare Implicit or Password flows in new cards; treat them as deprecated rather than gone when you parse cards from other agents.
Coming from v0.3?
These are the differences between the a2a.proto files of v0.3.0 and v1.0.1:
| Change | Detail |
|---|---|
Security renamed | Now SecurityRequirement, with the same structure. AgentCard.security became securityRequirements (field 9) and AgentSkill.security became securityRequirements (field 8) |
| Device Code flow added | OAuthFlows.device_code (field 5) with DeviceCodeOAuthFlow |
| PKCE flag added | AuthorizationCodeOAuthFlow.pkce_required (field 5) |
| Implicit and Password flows | Still oneof members 3 and 4, now marked deprecated |
| Required fields | None of the security messages in the v0.3.0 proto carries a REQUIRED annotation; v1.0.1 marks the fields shown as required in the tables above |
| Unchanged | The five SecurityScheme members keep fields 1 to 5, and MutualTlsSecurityScheme exists in both versions |
The official migration guide covers the OAuth flow changes but not the security rename.
Related pages
- Agent Card
: where
securitySchemessits. - Enterprise Implementation of A2A : how these schemes fit into an enterprise deployment.
- Agent Card Proto Field Numbers: v0.3.0 vs v1.0.1 : the rename of field 9 in context.
Source: A2A official specification: Security Objects, JSON Field Naming Convention, Authentication and Authorization
; What’s New in A2A Protocol v1.0
; a2a.proto at v1.0.1
and v0.3.0